Skip to content

Extract Markdown parse/produce as public pkg/markdown library - #343

Merged
jeduden merged 11 commits into
mainfrom
claude/public-markdown-library-iLDGm
May 18, 2026
Merged

Extract Markdown parse/produce as public pkg/markdown library#343
jeduden merged 11 commits into
mainfrom
claude/public-markdown-library-iLDGm

Conversation

@jeduden

@jeduden jeduden commented May 18, 2026

Copy link
Copy Markdown
Owner

Completes plan #163 by extracting mdsmith's Markdown parsing and production capabilities into a public Go library at pkg/markdown.

Summary

This PR establishes pkg/markdown as mdsmith's canonical, importable Markdown surface. It moves parsing logic, processing instruction handling, and frontmatter utilities from internal/lint into the public package, making them available to external consumers while maintaining a single goldmark parser configuration across the codebase.

Key Changes

  • New public package pkg/markdown: Exports the canonical goldmark parser and Markdown processing utilities

    • parser.go: NewParser() returns the shared parser instance with CommonMark + processing instruction support
    • parse.go: Parse() and Document type for parsing Markdown with frontmatter separation
    • pi.go & pi_parser.go: Processing instruction (<?...?>) AST node and parser
    • frontmatter.go: StripFrontMatter() utility for YAML frontmatter handling
    • produce.go: Edit and Splice() for Markdown mutation
    • doc.go: Package documentation and compatibility policy
  • Refactored internal/lint: Now imports from pkg/markdown instead of duplicating logic

    • pi.go, pi_parser.go, frontmatter.go reduced to thin wrappers or removed
    • file.go and lint_coverage_test.go updated to use public APIs
    • pi_test.go moved to pkg/markdown/pi_test.go with expanded coverage
  • Updated internal consumers: internal/release/syncdocs.go and internal/rules/markdownflavor/parser.go now import from pkg/markdown

  • Documentation: Added docs/development/markdown-library.md describing the public API, compatibility policy, and usage

  • Architecture updates: Updated architecture docs to reflect pkg/markdown as the single Markdown surface boundary

  • Test infrastructure: Added golden-file test for syncdocs reconciliation and comprehensive unit tests for all public APIs

  • Plan status: Marked plan Clean up completed and won't-fix plans #163 as complete (✅)

Implementation Details

  • Parser is cached via sync.Once to ensure a single instance across the application
  • Processing instructions are registered as a custom goldmark block parser
  • Frontmatter stripping is idempotent and handles edge cases (empty files, missing delimiters)
  • All public APIs include unit tests with 100% coverage expectations
  • Backward compatibility maintained: internal code continues to work via public imports

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX

claude added 6 commits May 18, 2026 20:13
Introduce github.com/jeduden/mdsmith/pkg/markdown as the one public
Markdown surface: Parse (front matter + body + AST), Splice (the
edit-based producer), ParseContext/NewParser/StripFrontMatter/
CountLines, and the ProcessingInstruction node primitive. The
canonical goldmark config and the PI block parser are moved here
verbatim from internal/lint so a single config can back every parse
path. internal/lint is repointed in a follow-up commit.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
internal/lint's PI node, PI block parser, canonical goldmark config,
parser pool, and front-matter split are now thin aliases/forwards to
pkg/markdown. NewFile and LinkReferences parse via
markdown.ParseContext, so exactly one goldmark configuration backs
every parse path. The ~150 lint consumers compile unchanged
(ProcessingInstruction is a type alias). The moved primitives' unit
tests now live in pkg/markdown; lint keeps the NewFile integration
smoke and its YAML-decoder tests. Full go test ./... stays green.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
…plan 163)

The MDS034 dual parser registered lint.PIBlockParserPrioritized,
making a parse path depend on the linter core. It now uses
markdown.PIBlockParserPrioritized from pkg/markdown; the rule logic
(detect/fix/rule) still uses lint.File as before. No public parse
path imports internal/lint.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
…lan 163)

Characterization golden over every docs/**/*.md plus synthetic edge
cases (setext H1, indented ATX, unterminated PI, frontmatter-only,
malformed frontmatter, PI in a code fence). Generated from the
pre-migration goldmark path; it is the AC4 byte-identical guard for
the upcoming pkg/markdown migration of sync-docs.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
…ark config (plan 163)

reconcileDocForHugo dropped its interim goldmark.New() parser (the
PR #291 stopgap) for the canonical pkg/markdown parser and
markdown.Splice. Directive markers are now ProcessingInstruction
nodes instead of CommonMark type-3 HTML blocks; the span math is
unchanged. The docs-corpus golden confirms byte-identical output
before and after. Only one goldmark configuration now exists in the
tree.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
Add docs/development/markdown-library.md documenting the pkg/markdown
parse/produce API and its compatibility policy (task 6). Resolve the
architecture doc/code conflict: go.md no longer claims internal/mdtext
is the only goldmark home — pkg/markdown owns the parser config,
mdtext walks the AST it produces. Register pkg/markdown in the
cross-system boundaries table and versioning policy, and add it to
the hub layering map and the inline-parsing anti-pattern. Regenerated
catalogs (CLAUDE.md, AGENTS.md, copilot-instructions, dev index,
PLAN.md); trimmed two CLAUDE.md prose lines to stay within its
length limit after the new catalog rows. Refreshed the sync-docs
golden for the grown docs corpus. Plan 163 marked complete: all
tasks and acceptance criteria verified.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
Copilot AI review requested due to automatic review settings May 18, 2026 20:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extracts mdsmith's Markdown parsing and producing logic from internal/lint into a new public Go package pkg/markdown. The new package owns the single canonical goldmark parser configuration (CommonMark + <?…?> processing-instruction block parser), the Parse/ParseContext entry points with frontmatter splitting, the Splice byte-exact producer, and the ProcessingInstruction AST node. internal/lint now re-exports these via type aliases and forwarders, internal/release/syncdocs.go migrates off its private goldmark.New() parser onto the shared one, and internal/rules/markdownflavor/parser.go switches to the public PI block-parser registration. A new golden corpus test pins reconcileDocForHugo output byte-for-byte across docs/** plus synthetic edge cases. Plan 163 is marked ✅.

Changes:

  • New pkg/markdown package with Parse, ParseContext, NewParser, StripFrontMatter, CountLines, Splice/Edit, and ProcessingInstruction plus comprehensive unit tests, package docs, and a parser pool.
  • internal/lint and internal/release/syncdocs.go refactored to consume pkg/markdown; lint keeps thin forwarders/type aliases for backward compatibility; PI grammar/frontmatter unit tests relocated next to the canonical implementation.
  • New docs/development/markdown-library.md (compatibility policy, API surface) plus catalog/architecture/cross-system doc updates; new syncdocs_golden_test.go pins reconciliation output.

Reviewed changes

Copilot reviewed 32 out of 33 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pkg/markdown/parser.go Canonical goldmark parser + pooled ParseContext.
pkg/markdown/parse.go Parse + Document (frontmatter split + AST).
pkg/markdown/parse_test.go Unit tests for Parse, ParseContext, Splice.
pkg/markdown/parser_test.go Parser smoke + concurrent race-free pool test.
pkg/markdown/produce.go Edit + Splice byte-exact span surgery.
pkg/markdown/pi.go ProcessingInstruction AST node + KindProcessingInstruction.
pkg/markdown/pi_parser.go Block parser for <?…?> PIs, with extractPINameBytes.
pkg/markdown/pi_test.go Relocated PI grammar tests + parser/extract coverage.
pkg/markdown/frontmatter.go StripFrontMatter + CountLines.
pkg/markdown/frontmatter_test.go Frontmatter behavior incl. block-scalar fence regression.
pkg/markdown/doc.go Package documentation and compatibility pointer.
internal/lint/pi.go Reduced to type-alias forwarder over pkg/markdown.
internal/lint/pi_parser.go Reduced to forwarders for NewPIBlockParser/PIBlockParserPrioritized.
internal/lint/pi_test.go Removed PI grammar tests now living in pkg/markdown.
internal/lint/frontmatter.go Forwarders to pkg/markdown for frontmatter helpers.
internal/lint/frontmatter_test.go Removed forwarded-helper tests.
internal/lint/file.go NewParser/parse path delegates to markdown.ParseContext.
internal/lint/lint_coverage_test.go Removed tests now in pkg/markdown; left explanatory comments.
internal/rules/markdownflavor/parser.go Uses markdown.PIBlockParserPrioritized instead of lint.*.
internal/rules/markdownflavor/parser_test.go Updated import/comment to reference pkg/markdown.
internal/release/syncdocs.go Migrated to markdown.ParseContext/Splice; matches PI block nodes.
internal/release/syncdocs_golden_test.go New golden corpus test pinning reconcileDocForHugo output.
docs/development/markdown-library.md New page: API surface + compatibility policy.
docs/development/architecture/{index,go,cross-system}.md Reflect pkg/markdown as the single parse surface.
docs/development/index.md, CLAUDE.md, AGENTS.md, .github/copilot-instructions.md Catalog/link updates for the new doc; minor wording trims.
plan/163_public-markdown-library.md, PLAN.md Mark plan 163 ✅ and record decisions.

claude added 2 commits May 18, 2026 20:52
…ixtures

The plan-163 AC4 byte-identical proof was a full-docs-corpus snapshot
captured pre-migration; it passed unchanged at b150678 and has served
its purpose. As a permanent artifact it was wrong: re-rendering all of
docs/ churned ~22.8k lines of testdata on every docs edit (and broke
CI test once docs changed).

Replace it with 12 minimal Markdown fixtures under
testdata/reconcile/<case>/{in,golden}, one per reconcileDocForHugo
branch (ATX/setext/indented/no-FM/existing-title/no-liftable-H1 title
lift; single/multi-line/in-fence/unterminated PI strip; malformed and
FM-only). 141 fixture lines total vs 22,806. Inputs are checked in as
files like rule fixtures and use no .md extension so mdsmith does not
lint the deliberately malformed cases.

Also document in docs/development/markdown-library.md how pkg/markdown
differs from stock goldmark (PI node vs type-3 HTML, no renderer,
byte-split front matter, CommonMark-only, byte-stability contract).

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
Stray artifact from an interim golden approach; no test references it.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
Copilot AI review requested due to automatic review settings May 18, 2026 20:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 56 out of 56 changed files in this pull request and generated 1 comment.

Comment thread docs/development/markdown-library.md Outdated
@codecov

codecov Bot commented May 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.98%. Comparing base (b15766b) to head (30df496).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
Components Coverage Δ
Go 95.95% <100.00%> (+0.02%) ⬆️
TypeScript 99.35% <ø> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

claude added 2 commits May 18, 2026 21:01
internal/release/syncdocs_test.go already exercises reconcileDocForHugo
exhaustively via inline TestReconcileDocForHugo_{TitleLift,TitleNoOp,
StripMarkers,StripNoOp} table tests (the project's established style).
The golden corpus / per-case testdata I added was redundant with that
pre-existing coverage from the start — remove syncdocs_golden_test.go
and testdata/reconcile/ entirely. No release testdata, no duplication;
the migrated reconcileDocForHugo stays guarded by those inline tests
plus pkg/markdown's own unit tests.

Also: delete the dead lint.NewPIBlockParser forward (nothing calls it;
lint.PIBlockParserPrioritized is kept — internal/schema uses it). Add
direct-call unit tests for the PI parser's defensive Open/Continue
guards so pkg/markdown is 100% covered (codecov/patch). Fix the
compatibility-policy reference in markdown-library.md that pointed at
the removed corpus file (Copilot review).

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
Plan 185 extends 163. It promotes the five custom goldmark
extensions, the Flavor identity, and the feature-support model
into a public pkg/markdown/flavor sub-package; decouples Detect
from internal/lint; and retires the two remaining hand-rolled
goldmark configs (internal/schema, markdownflavor) so one parser
config remains. Tasks and acceptance criteria are annotated with
the SOLID principle each verifies and the dependency direction
each crosses, per the solid-architecture plan-mode workflow.
Deliverable is the design plan only; no source changed.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
Copilot AI review requested due to automatic review settings May 18, 2026 21:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated no new comments.

Reframe the move task as "every custom parser" with an explicit
inventory: an exhaustive scan (ast.NewNodeKind / Extend /
ASTTransformer) finds only the PI parser (already public via 163)
and the five markdownflavor/ext extensions, including the
abbreviation ASTTransformer. Add a verifiable acceptance
criterion that no custom parser, node kind, or transformer
remains under internal/ or cmd/.

https://claude.ai/code/session_01RBQSS4X7e6mfrkyXmDzGRX
@jeduden
jeduden merged commit 78e849b into main May 18, 2026
21 checks passed
jeduden added a commit that referenced this pull request May 18, 2026
Extend the check-performance gate to the public pkg/markdown
library (extracted in #343), which had no p95 backstop of its
own despite being a cross-system compatibility contract. Add
tiered BenchmarkParse{Small,Large} (canonical parser incl. the
<?...?> PI block) and a markdown-bench CI job mirroring
check-bench.

Pass 2 of the task-11 profiler loop on the post-#343 hot path:
unicode.IsSpace was ~5.5% of single-core check CPU (per-rune in
CountWords/CountSentences and MDS024 cheapBounds). Add
mdtext.IsSpace, an inlinable ASCII fast path proven byte-for-
byte equivalent to unicode.IsSpace by an exhaustive rune-domain
sweep. Single-core BenchmarkCheckCorpusLarge ~962 -> ~910-957
us/file. The #343 extraction preserved the Pass-1 gains.

https://claude.ai/code/session_017rv18FDob5NHAjSdSvfeha

Co-authored-by: Claude <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.

3 participants