Skip to content

Commit bae0cfa

Browse files
committed
Fix duplicate link-ref transformer in newParserInternal
Copilot review caught a real bug: goldmark.New() calls DefaultParser() which already installs DefaultParagraphTransformers(), so the previous goldmark.WithParserOptions(parser.WithParagraphTransformers(defaults...)) call appended a second link-reference transformer on top. The reset closure only touched the appended instance; the one inside the default parser kept pinning the last parsed document's bytes. Build the parser explicitly with parser.NewParser (one set of block, inline, and paragraph parsers including the lrp captured for reset) and install it via goldmark.WithParser, then let goldmark.New's extension Extend hooks register the additional block / inline parsers they need. After this change there is exactly one link-ref transformer in the resulting parser, and the closure returned to NewPooledParser callers resets that instance. https://claude.ai/code/session_0144ZKUS2Zrg7xBft54qyoti
1 parent 98e117e commit bae0cfa

1 file changed

Lines changed: 21 additions & 11 deletions

File tree

pkg/markdown/flavor/parser.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,12 @@ func newPooled(exts []goldmark.Extender) (parser.Parser, func()) {
9191
}
9292

9393
// newParserInternal is the single goldmark.New call site in the tree.
94-
// It builds the canonical parser plus extracts the link-reference
95-
// paragraph transformer so pool callers can Reset its retained
96-
// document bytes.
94+
// It builds the canonical parser explicitly so the link-reference
95+
// paragraph transformer captured below is the same instance the
96+
// parser uses — and the only one. goldmark.New's own DefaultParser
97+
// would install a second link-ref transformer that the returned
98+
// reset closure could not reach, leaving pinned document bytes
99+
// alive in the pool slot.
97100
func newParserInternal(exts []goldmark.Extender) (parser.Parser, linkRefResetter) {
98101
defaults := parser.DefaultParagraphTransformers()
99102
var lrp linkRefResetter
@@ -103,15 +106,22 @@ func newParserInternal(exts []goldmark.Extender) (parser.Parser, linkRefResetter
103106
break
104107
}
105108
}
106-
md := goldmark.New(
107-
goldmark.WithExtensions(exts...),
108-
goldmark.WithParserOptions(
109-
parser.WithAttribute(),
110-
parser.WithBlockParsers(
109+
p := parser.NewParser(
110+
parser.WithBlockParsers(
111+
append(parser.DefaultBlockParsers(),
111112
markdown.PIBlockParserPrioritized(),
112-
),
113-
parser.WithParagraphTransformers(defaults...),
113+
)...,
114114
),
115+
parser.WithInlineParsers(parser.DefaultInlineParsers()...),
116+
parser.WithParagraphTransformers(defaults...),
117+
parser.WithAttribute(),
118+
)
119+
// goldmark.New invokes each Extender's Extend(md) hook, which
120+
// calls md.Parser().AddOptions(...) to register additional
121+
// block / inline parsers on the parser installed by WithParser.
122+
goldmark.New(
123+
goldmark.WithParser(p),
124+
goldmark.WithExtensions(exts...),
115125
)
116-
return md.Parser(), lrp
126+
return p, lrp
117127
}

0 commit comments

Comments
 (0)