Skip to content

Commit

Permalink
add utility function to calculate underline size for category names
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacob Gulan authored and jacobgulan committed Aug 2, 2024
1 parent fc3a255 commit d91fde9
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 4 deletions.
22 changes: 22 additions & 0 deletions src/towncrier/_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import re
import textwrap
import unicodedata

from collections import defaultdict
from pathlib import Path
Expand Down Expand Up @@ -181,6 +182,22 @@ def find_fragments(
return content, fragment_files


def get_underline_size(text: str) -> int:
"""
Given `text` determine the underline size needed for the reStructuredText output.
Particularly helps determine if an extra underline is needed for wide characters like emojis.
"""
underline_size: int = 0
for char in text:
if unicodedata.east_asian_width(char) in ("W", "F"):
underline_size += 2
else:
underline_size += 1

return underline_size


def indent(text: str, prefix: str) -> str:
"""
Adds `prefix` to the beginning of non-empty lines in `text`.
Expand Down Expand Up @@ -224,6 +241,11 @@ def split_fragments(
# it's recorded.
content = ""

# Calculate the underline size for the name of the category.
definitions[category]["underline_size"] = get_underline_size(
definitions[category]["name"]
)

texts = section.setdefault(category, {})

issues = texts.setdefault(content, [])
Expand Down
1 change: 1 addition & 0 deletions src/towncrier/newsfragments/626.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed section names not having enough underline characters for emojis.
2 changes: 1 addition & 1 deletion src/towncrier/templates/default.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section]%}
{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{{ underline * definitions[category]['underline_size'] }}

{% for text, values in sections[section][category].items() %}
- {% if text %}{{ text }}{% if values %} ({{ values|join(', ') }}){% endif %}{% else %}{{ values|join(', ') }}{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/towncrier/templates/hr-between-versions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section]%}
{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{{ underline * definitions[category]['underline_size'] }}

{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category].items() %}
Expand Down
2 changes: 1 addition & 1 deletion src/towncrier/templates/single-file-no-bullets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
{% for category, val in definitions.items() if category in sections[section] %}

{{ definitions[category]['name'] }}
{{ underline * definitions[category]['name']|length }}
{{ underline * definitions[category]['underline_size'] }}

{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category].items() %}
Expand Down
12 changes: 11 additions & 1 deletion src/towncrier/test/test_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from twisted.trial.unittest import TestCase

from .._builder import parse_newfragment_basename, render_fragments
from .._builder import get_underline_size, parse_newfragment_basename, render_fragments


class TestParseNewsfragmentBasename(TestCase):
Expand Down Expand Up @@ -208,3 +208,13 @@ def test_ordering(self):
- Added Fish
"""
)


class TestUtilityFunctions(TestCase):
def test_get_underline_size_ascii(self):
"""Determine underline size for normal ASCII strings."""
assert get_underline_size("bugfixes") == 8

def test_get_underline_size_wide_character(self):
"""Determine underline size for strings with wide characters."""
assert get_underline_size("🐛 Bugfixes") == 11

0 comments on commit d91fde9

Please sign in to comment.