@@ -210,6 +210,74 @@ And [another real link](https://real.example.com/page).
210210 expect ( result . externalLinks [ 1 ] . href ) . toBe ( 'https://real.example.com/page' )
211211 } )
212212
213+ test ( 'skips links inside inline code spans' , ( ) => {
214+ const content = `
215+ See [a real link](/real/path) for details.
216+
217+ * For links to other pages: \`See [AUTOTITLE](/PATH/TO/PAGE).\`
218+ * With a query: \`See [AUTOTITLE](/path/to/page?tool=TOOLNAME).\`
219+
220+ And [another real link](/another/real/path) here.
221+ `
222+ const result = extractLinksFromMarkdown ( content )
223+
224+ expect ( result . internalLinks ) . toHaveLength ( 2 )
225+ expect ( result . internalLinks . map ( ( l ) => l . href ) ) . toEqual ( [ '/real/path' , '/another/real/path' ] )
226+ } )
227+
228+ test ( 'handles inline code and a real link on the same line' , ( ) => {
229+ const content = `Use \`[AUTOTITLE](/PLACEHOLDER)\` and then see [the guide](/real/guide).`
230+ const result = extractLinksFromMarkdown ( content )
231+
232+ expect ( result . internalLinks ) . toHaveLength ( 1 )
233+ expect ( result . internalLinks [ 0 ] . href ) . toBe ( '/real/guide' )
234+ } )
235+
236+ test ( 'does not mask links when backtick runs are mismatched' , ( ) => {
237+ // Per CommonMark, a code span needs equal-length, maximal backtick runs on
238+ // both ends. These lines have mismatched runs, so they are NOT code spans
239+ // and the links between the backticks are real and must be extracted.
240+ const content = [
241+ `A single-open, double-close: \`[one](/real/one)\`\`` ,
242+ `A double-open, triple-close: \`\`[two](/real/two)\`\`\`` ,
243+ ] . join ( '\n' )
244+ const result = extractLinksFromMarkdown ( content )
245+
246+ expect ( result . internalLinks . map ( ( l ) => l . href ) ) . toEqual ( [ '/real/one' , '/real/two' ] )
247+ } )
248+
249+ test ( 'still masks links inside valid multi-backtick code spans' , ( ) => {
250+ // A matched double-backtick run is a real code span, even when it wraps an
251+ // inner single backtick, so the link inside must be ignored.
252+ const content = `Example: \`\` \`[skip](/placeholder)\` \`\` and see [the guide](/real/guide).`
253+ const result = extractLinksFromMarkdown ( content )
254+
255+ expect ( result . internalLinks ) . toHaveLength ( 1 )
256+ expect ( result . internalLinks [ 0 ] . href ) . toBe ( '/real/guide' )
257+ } )
258+
259+ test ( 'captures internal links with balanced parentheses in the path' , ( ) => {
260+ const content = `See the [privacy statement (PDF)](/assets/images/help/site-policy/github-privacy-statement(07.22.20)(fr).pdf).`
261+ const result = extractLinksFromMarkdown ( content )
262+
263+ expect ( result . internalLinks ) . toHaveLength ( 1 )
264+ expect ( result . internalLinks [ 0 ] . href ) . toBe (
265+ '/assets/images/help/site-policy/github-privacy-statement(07.22.20)(fr).pdf' ,
266+ )
267+ } )
268+
269+ test ( 'does not let an unclosed link destination span multiple lines' , ( ) => {
270+ const content = `
271+ Broken: [AUTOTITLE](/code-security/create-custom-configuration.
272+ 1. A following list item with [a real link](/real/target).
273+ `
274+ const result = extractLinksFromMarkdown ( content )
275+
276+ // The unclosed link is not extracted, and it does not swallow the real link
277+ // on the next line into a giant multi-line href.
278+ expect ( result . internalLinks . map ( ( l ) => l . href ) ) . toEqual ( [ '/real/target' ] )
279+ } )
280+
213281 test ( 'handles complex nested brackets' , ( ) => {
214282 const content = `
215283Use the [\`git clone\`](/repositories/cloning) command.
0 commit comments