Skip to content

Fix html escaping#30

Merged
chmouel merged 1 commit intochmouel:mainfrom
josecastillolema:html-escaping
Feb 3, 2026
Merged

Fix html escaping#30
chmouel merged 1 commit intochmouel:mainfrom
josecastillolema:html-escaping

Conversation

@josecastillolema
Copy link
Copy Markdown
Contributor

When meetings include some specific special chars, i.e.: &, ', etc. I am observing some waybar errors and calendar does not appear:

Feb 03 14:51:09 think waybar[2514877]: Failed to set text '38 minutes to go - Perf&amp...' from markup due to error parsing markup: Error on line 1: Entity did not end with a semicolon; most likely you used an ampersand character without intending to start an entity — escape ampersand as &

This PR fixes this error and adds some tests.

Signed-off-by: Jose Castillo Lema <josecastillolema@gmail.com>
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @josecastillolema, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue where special characters in meeting titles, when rendered by Waybar, could lead to markup parsing errors and prevent the calendar from displaying. The core change involves a robust refactor of the ellipsis string utility to intelligently truncate text while preserving the integrity of HTML entities, ensuring that meeting information is always displayed correctly without breaking the UI.

Highlights

  • HTML Escaping Fix: The ellipsis utility function has been updated to correctly handle HTML entities (e.g., &amp;, &#x27;) when truncating strings. This prevents Waybar errors caused by malformed markup and ensures that entities are treated as single display characters, avoiding truncation in the middle of an entity.
  • Enhanced Test Coverage: New unit tests have been added for the ellipsis function to verify its behavior under various conditions, including basic truncation, correct handling of HTML entities, and proper stripping of HTML tags.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/nextmeeting/cli.py
    • Refactored the ellipsis function to accurately calculate string length by treating HTML entities as single display characters.
    • Implemented logic to prevent HTML entities from being broken during truncation, ensuring they are kept intact.
  • tests/test_features.py
    • Added ellipsis to the import list.
    • Introduced several new test cases for the ellipsis function, covering scenarios like no truncation needed, basic truncation, handling of &amp; and numeric HTML entities, and stripping of HTML tags.
Activity
  • No human activity (comments, reviews) has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses an HTML escaping issue in meeting titles that was causing errors in Waybar. The core of the fix is a rewritten ellipsis function that is now aware of HTML entities during string truncation, which is a solid improvement. My review includes a suggestion to enhance the robustness of this new function by handling edge cases with small length values. Additionally, I've provided feedback on the new tests, recommending more precise assertions to ensure the function's behavior is validated as accurately as possible. Overall, these changes are a valuable fix for the reported problem.

Comment thread src/nextmeeting/cli.py
Comment on lines +819 to +837
# Truncate based on display length, keeping entities intact
result = []
current_display_len = 0
target_len = length - 3 # Leave room for "..."
i = 0

while i < len(clean_string) and current_display_len < target_len:
if clean_string[i] == "&":
end = clean_string.find(";", i)
if end != -1:
result.append(clean_string[i : end + 1])
i = end + 1
current_display_len += 1
continue
result.append(clean_string[i])
current_display_len += 1
i += 1

return "".join(result) + "..."
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current implementation of ellipsis doesn't handle small length values correctly. If length is less than 4, target_len can become zero or negative, causing the while loop to not execute. This results in the function returning just "...", which is 3 characters long and can be longer than the requested length. The function should be robust enough to handle any length value gracefully, for example by truncating without adding an ellipsis for small lengths.

    # Truncate based on display length, keeping entities intact
    result = []
    current_display_len = 0

    if length <= 3:
        target_len = length
        suffix = ""
    else:
        target_len = length - 3  # Leave room for "..."
        suffix = "..."

    i = 0

    while i < len(clean_string) and current_display_len < target_len:
        if clean_string[i] == "&":
            end = clean_string.find(";", i)
            if end != -1:
                result.append(clean_string[i : end + 1])
                i = end + 1
                current_display_len += 1
                continue
        result.append(clean_string[i])
        current_display_len += 1
        i += 1

    return "".join(result) + suffix

Comment thread tests/test_features.py
Comment on lines +129 to +154
def test_ellipsis_html_entity_not_broken():
# &amp; should count as 1 display char and not be split
result = ellipsis("Perf&amp;Scale meeting", 15)
assert "&amp;" in result or result.endswith("...")
# Ensure no broken entity like &amp without semicolon
assert "&amp" not in result or "&amp;" in result


def test_ellipsis_html_entity_counts_as_one_char():
# "Test&amp;Go" has display length 9 (Test&Go + 2 chars for entity displayed as 1)
# With length=12, should not truncate
result = ellipsis("Test&amp;Go", 12)
assert result == "Test&amp;Go"


def test_ellipsis_numeric_entity_not_broken():
# &#x27; is apostrophe, should count as 1 display char
result = ellipsis("What&#x27;s New in Tech", 15)
# Should not have broken entity
assert "&#x27" not in result or "&#x27;" in result


def test_ellipsis_strips_html_tags():
result = ellipsis("<span>Hello</span> World", 15)
assert "<span>" not in result
assert "Hello World" in result or "Hello Wor..." in result
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The assertions in these new tests for ellipsis could be more precise to make them more robust.

For example, in test_ellipsis_html_entity_not_broken, assert "&amp;" in result or result.endswith("...") is weak because it would pass for incorrect results like ... or Perf.... A precise check like assert result == "Perf&amp;Scale m..." would be better.

Similarly, in test_ellipsis_strips_html_tags, for length=15 the result is exactly "Hello World", so assert result == "Hello World" would be more accurate. If testing truncation (e.g., with length=10), the assertion should check for the exact truncated string, like assert result == "Hello W...".

Precise assertions ensure the function behaves exactly as expected.

@chmouel
Copy link
Copy Markdown
Owner

chmouel commented Feb 3, 2026

very nice thanks!

@chmouel chmouel merged commit 981e78e into chmouel:main Feb 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants