Skip to content

Expand Markdown fixture corpus and add golden-test -update flag - #13

Open
fairbearlab wants to merge 4 commits into
mainfrom
fixtures/markdown-golden-corpus
Open

fairbearlab wants to merge 4 commits into
mainfrom
fixtures/markdown-golden-corpus

Conversation

@fairbearlab

Copy link
Copy Markdown
Owner

Summary

Grows engine/testdata/fixtures/ from 5 to 13 hand-synthesized (no scraped page content, no personal data) HTML → Markdown golden pairs, and adds a -update flag to TestMarkdown_Fixtures so the goldens can be regenerated from the converter's current output.

New fixtures:

  • google-docs-clipboard — Google Docs paste-style output (<b style="font-weight:normal" id="docs-internal-guid-..."> wrapper, <span style="font-weight:700"> bold, list items wrapped in <p>)
  • word-clipboard — MS Word paste-style output (mso-* classes/styles, <o:p>, fake bullet lists built from <span style='mso-list:Ignore'>·</span> + conditional comments, &nbsp; spacer paragraphs)
  • images-and-captions — <figure>/<img>/<figcaption>, inline image in a paragraph
  • rule-strikethrough-sub-sup — <hr>, <del>, <s>, <sub>, <sup>
  • definition-list — <dl>/<dt>/<dd>
  • loose-list-multi-paragraph — ordered list items containing multiple <p> blocks and a nested code block
  • table-colspan-alignment — table with text-align hints and a colspan="3" summary row
  • tracking-links-and-anchors — UTM-tagged links, an anchor-only <a name> fragment target, a same-page #top link, mailto:, and an empty href=""

The 5 pre-existing fixtures are unchanged except for whitespace-only golden-file cleanup (trailing newline added; blank continuation lines within nested lists stripped of trailing spaces) picked up by the new -update flag — no behavioral difference, and TestMarkdown_Fixtures still passes for all of them.

Suspected engine bugs (not fixed here, goldened as-is per the task)

A few of the new fixtures intentionally golden the engine's current (arguably wrong) output rather than the ideal one, so the corpus can catch regressions and future fixes can update these goldens deliberately:

  1. Google Docs bold-wrap bug (google-docs-clipboard): Google Docs wraps its whole clipboard payload in <b style="font-weight:normal">. The converter doesn't consider the style override and treats the outer <b> as literal bold, so the entire document comes out wrapped in **...**.
  2. List items lose their bullets under malformed nesting (google-docs-clipboard): the same Google Docs wrapper nests <ul><li><p>...</p></li></ul> inside a <b> (a <b> containing block-level content isn't valid HTML content model, but browsers/Docs still emit it). Under that nesting the converter drops the - bullet markers entirely, rendering list items as bare paragraphs. Note this is specific to the malformed nesting — the same <li><p>...</p></li> pattern converts correctly in loose-list-multi-paragraph, which doesn't have the outer <b>.
  3. Word's non-semantic "fake" bullet lists aren't recognized (word-clipboard): Word's clipboard HTML often has no real <ul>/<li> — just <p class=MsoListParagraph...> with an mso-list style and a literal · bullet glyph inside a <span style='mso-list:Ignore'>. The converter passes this through as literal · + runs of &nbsp; rather than emitting - Markdown list syntax.
  4. &nbsp;-only spacer paragraphs leak into the output (word-clipboard): Word often inserts empty <p>&nbsp;</p> paragraphs for vertical spacing; these come through as stray lines containing a single non-breaking space rather than being collapsed away.
  5. Strikethrough is silently dropped (rule-strikethrough-sub-sup): <del> and <s> content is unwrapped to plain text instead of being rendered as GFM ~~strikethrough~~. The converter is built from base + commonmark + table plugins; wiring in the library's strikethrough plugin would likely fix this.
  6. Definition lists lose all structure (definition-list): <dl>/<dt>/<dd> collapse to a sequence of plain paragraphs indistinguishable from unrelated prose — the term/definition relationship is lost entirely (no bolding of <dt>, no indentation of <dd>).
  7. Table colspan and alignment hints are ignored (table-colspan-alignment): a colspan="3" summary row has its content dumped into column 1 with columns 2–3 left as empty cells (structurally misleading — looks like missing data rather than a spanning cell), and per-column text-align CSS is ignored, so the generated alignment row is always ---|---|--- regardless of the source's alignment.
  8. Anchor-only fragment targets render as a bogus link (tracking-links-and-anchors): <a name="top"></a> (no href, no text — just a same-page jump target) comes out as a literal []() in the Markdown rather than being dropped.

None of these are fixed in this PR per the task instructions (record current output as golden, list suspected bugs for a human to triage/fix separately).

Test plan

  • cd engine && go test ./... — all pass, including the 13 TestMarkdown_Fixtures subtests
  • cd engine && go test ./transforms/... -run TestMarkdown_Fixtures -update regenerates goldens byte-identical to the committed ones (re-run without -update still passes)
  • go vet ./..., gofmt -l . (clean), go test -race ./..., go mod tidy (no diff), golangci-lint run (0 issues), govulncheck ./... (no vulnerabilities) — full local equivalent of make ci for the engine
  • No .github/workflows/* files touched

🤖 Generated with Claude Code

fairbearlab and others added 4 commits September 26, 2026 00:29
Grow engine/testdata/fixtures/ from 5 to 13 hand-synthesized HTML/MD
golden pairs, covering Google Docs- and Word-style clipboard spans,
images/captions, hr/strikethrough/sub-sup, definition lists, loose
multi-paragraph list items, table colspan/alignment, and tracking
link/anchor edge cases. TestMarkdown_Fixtures gains a -update flag to
regenerate .md goldens from the converter's current output.

Several new fixtures golden the engine's current (buggy) output on
purpose rather than the ideal one; suspected bugs are listed in the
PR description instead of being fixed here.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
golangci-lint v2.14's gosec now taint-tracks the -update write path
(mdFile derived from filepath.Glob) the same way it already does for
the read path. Wrap the write in filepath.Clean(), matching the repo's
documented gosec G304/G703 remedy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
filepath.Clean() alone didn't satisfy golangci-lint v2.14's gosec G703
taint check for os.WriteFile with a variable destination path. Switch
to the OpenFile(O_CREATE|O_TRUNC)+Write pattern already established
for this rule in rolodex's copyFile helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ntry

Six new fixtures deliberately golden the converter's current (wrong)
output. Record each pinned bug in TODOS.md so a future fix that changes
those goldens is recognisably intended, rather than pointing at PR
history. Add an Unreleased CHANGELOG line for the corpus + -update flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant