Skip to content

Fix nested display:none span handling in CustomHtmlParser#6631

Open
HakanIST wants to merge 1 commit into
wikimedia:mainfrom
HakanIST:fix/T426910-nested-display-none-spans
Open

Fix nested display:none span handling in CustomHtmlParser#6631
HakanIST wants to merge 1 commit into
wikimedia:mainfrom
HakanIST:fix/T426910-nested-display-none-spans

Conversation

@HakanIST
Copy link
Copy Markdown

Summary

Fix for T426910: Citation previews for the {{Cite}} template on Polish Wikipedia render garbled author names in the reference dialog.

Root Cause

CustomHtmlParser.CustomTagHandler used a single lastHiddenSpanPos variable to track <span style="display:none"> elements. When a hidden span contained child spans, the first inner </span> close event would trigger output deletion and reset the tracker. Subsequent sibling spans inside the hidden parent then rendered their content as visible text.

Polish Wikipedia's {{Cite}} template uses nested display:none spans to toggle between full author names and initials:

<span class="cite-name-after" style="display:none">
    <span>\&nbsp;</span>           <!-- closes first, resets tracker -->
    <span class="cite-name-full">Guy</span>    <!-- now visible (bug) -->
    <span class="cite-name-initials">G.</span> <!-- now visible (bug) -->
</span>

This produced output like Guy G. Mansell Guy G. instead of Guy Mansell.

Fix

Replace the single-variable approach with depth-tracked nesting:

  • hiddenSpanDepth counts nesting depth inside a display:none span
  • hiddenSpanStartPos records the output position where the outermost hidden span opened
  • Nested span open/close events adjust the depth counter without triggering premature deletion
  • When the outermost hidden span closes (depth returns to 0), all content appended since it opened is deleted

Testing

  • Added CustomHtmlParserTest with 9 test cases covering simple, nested, deeply nested, sequential, and empty hidden spans, plus the exact {{Cite}} template pattern from Polish Wikipedia
  • Verified existing StringUtilTest still passes
  • All tests pass locally with Robolectric

CustomHtmlParser used a single variable (lastHiddenSpanPos) to track
display:none spans. This broke when a hidden span contained child spans,
because the first inner </span> close would trigger deletion and reset
the tracker, causing subsequent nested content to leak into the output.

This is the root cause of T426910: Polish Wikipedia's {{Cite}} template
uses nested display:none spans to toggle between full names and initials.
The broken tracking produced garbled author names like
"Guy G. Mansell Guy G." instead of "Guy Mansell".

Replace the single-variable approach with depth-tracked nesting:
- hiddenSpanDepth counts nesting depth inside a display:none span
- hiddenSpanStartPos records where to truncate when the outermost
  hidden span closes
- Nested span open/close events adjust the depth counter without
  triggering premature deletion

Also adds CustomHtmlParserTest with 9 test cases covering simple,
nested, deeply nested, sequential, and empty hidden spans, as well
as the exact {{Cite}} template pattern from Polish Wikipedia.

Bug: T426910
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants