From 25cd43ba6e49a48f5372467ce679482ab3535e2d Mon Sep 17 00:00:00 2001 From: gs0428 Date: Tue, 30 Jun 2026 22:56:52 +0900 Subject: [PATCH 1/3] fix: parse link reference definitions with titles --- patches/@tanstack__markdown@0.0.5.patch | 13 ++++++ pnpm-lock.yaml | 7 ++- pnpm-workspace.yaml | 3 ++ ...arkdown-link-reference-definitions.test.ts | 43 +++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 patches/@tanstack__markdown@0.0.5.patch create mode 100644 tests/markdown-link-reference-definitions.test.ts diff --git a/patches/@tanstack__markdown@0.0.5.patch b/patches/@tanstack__markdown@0.0.5.patch new file mode 100644 index 000000000..294c09bab --- /dev/null +++ b/patches/@tanstack__markdown@0.0.5.patch @@ -0,0 +1,13 @@ +diff --git a/dist/parser.js b/dist/parser.js +index 6616130a037737d109c527ec23ea8149ad8a68aa..1b4898b9ac1e749eeb136a5b8d13f8338a026b2b 100644 +--- a/dist/parser.js ++++ b/dist/parser.js +@@ -334,7 +334,7 @@ function extractDefinitions(lines) { + footnotes[normalizeReferenceLabel(label)] = { label, content: content.join('\n') }; + continue; + } +- const definition = line.match(/^ {0,3}\[([^\]\n]+)\]:[ \t]*(\S+)[ \t]*$/); ++ const definition = line.match(/^ {0,3}\[([^\]\n]+)\]:[ \t]*(\S+)(?:[ \t]+"[^"]*"|[ \t]+'[^']*'|[ \t]+\([^)]*\))?[ \t]*$/); + if (definition) { + references[normalizeReferenceLabel(definition[1])] = { href: definition[2].replace(/^<|>$/g, '') }; + index++; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d935d005a..bdc9c5a25 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,6 +17,9 @@ overrides: minimatch@10.2.5>brace-expansion: 5.0.5 npm-run-path@6.0.0>unicorn-magic: 0.4.0 +patchedDependencies: + '@tanstack/markdown@0.0.5': ae0825e87ec7335f705ad024eb28d31d0a2e99c8d9acab09e671828b432dba89 + importers: .: @@ -107,7 +110,7 @@ importers: version: 0.0.2 '@tanstack/markdown': specifier: ^0.0.5 - version: 0.0.5(react@19.2.3) + version: 0.0.5(patch_hash=ae0825e87ec7335f705ad024eb28d31d0a2e99c8d9acab09e671828b432dba89)(react@19.2.3) '@tanstack/pacer': specifier: ^0.21.1 version: 0.21.1 @@ -9668,7 +9671,7 @@ snapshots: dependencies: '@tanstack/store': 0.11.0 - '@tanstack/markdown@0.0.5(react@19.2.3)': + '@tanstack/markdown@0.0.5(patch_hash=ae0825e87ec7335f705ad024eb28d31d0a2e99c8d9acab09e671828b432dba89)(react@19.2.3)': optionalDependencies: react: 19.2.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index e6add2aca..aa58df881 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -33,3 +33,6 @@ allowBuilds: # Cloudflare Workers local runtime workerd: true + +patchedDependencies: + '@tanstack/markdown@0.0.5': patches/@tanstack__markdown@0.0.5.patch diff --git a/tests/markdown-link-reference-definitions.test.ts b/tests/markdown-link-reference-definitions.test.ts new file mode 100644 index 000000000..a4f792cb0 --- /dev/null +++ b/tests/markdown-link-reference-definitions.test.ts @@ -0,0 +1,43 @@ +import assert from 'node:assert/strict' +import { parseSiteMarkdown } from '../src/utils/markdown' + +const markdownCases = [ + { + name: 'single-quoted title', + markdown: "[//]: # 'SomeLabel'\n\nVisible content.", + }, + { + name: 'double-quoted title', + markdown: '[//]: # "SomeLabel"\n\nVisible content.', + }, + { + name: 'parenthesized title', + markdown: '[//]: # (SomeLabel)\n\nVisible content.', + }, +] + +for (const testCase of markdownCases) { + const document = parseSiteMarkdown(testCase.markdown) + + assert.equal( + document.children.length, + 1, + `${testCase.name} reference definition is not rendered`, + ) + + const paragraph = document.children[0] + + assert.equal(paragraph?.type, 'paragraph', `${testCase.name} content remains`) + + if (paragraph?.type !== 'paragraph') { + throw new Error(`${testCase.name} did not produce a paragraph`) + } + + assert.deepEqual( + paragraph.children, + [{ type: 'text', value: 'Visible content.' }], + `${testCase.name} visible paragraph is preserved`, + ) +} + +console.log('markdown link reference definition tests passed') From 861553af526b57df23c02ce235a697dcf607f6ec Mon Sep 17 00:00:00 2001 From: gs0428 Date: Tue, 30 Jun 2026 23:19:07 +0900 Subject: [PATCH 2/3] fix(markdown): preserve link reference titles --- patches/@tanstack__markdown@0.0.5.patch | 12 +++-- pnpm-lock.yaml | 6 +-- ...arkdown-link-reference-definitions.test.ts | 48 +++++++++++++++++++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/patches/@tanstack__markdown@0.0.5.patch b/patches/@tanstack__markdown@0.0.5.patch index 294c09bab..06842b19c 100644 --- a/patches/@tanstack__markdown@0.0.5.patch +++ b/patches/@tanstack__markdown@0.0.5.patch @@ -1,13 +1,17 @@ diff --git a/dist/parser.js b/dist/parser.js -index 6616130a037737d109c527ec23ea8149ad8a68aa..1b4898b9ac1e749eeb136a5b8d13f8338a026b2b 100644 +index 6616130a037737d109c527ec23ea8149ad8a68aa..be8c5b941d9437324b74f353fb3a51293a029740 100644 --- a/dist/parser.js +++ b/dist/parser.js -@@ -334,7 +334,7 @@ function extractDefinitions(lines) { +@@ -334,9 +334,10 @@ function extractDefinitions(lines) { footnotes[normalizeReferenceLabel(label)] = { label, content: content.join('\n') }; continue; } - const definition = line.match(/^ {0,3}\[([^\]\n]+)\]:[ \t]*(\S+)[ \t]*$/); -+ const definition = line.match(/^ {0,3}\[([^\]\n]+)\]:[ \t]*(\S+)(?:[ \t]+"[^"]*"|[ \t]+'[^']*'|[ \t]+\([^)]*\))?[ \t]*$/); ++ const definition = line.match(/^ {0,3}\[([^\]\n]+)\]:[ \t]*(\S+)(?:[ \t]+(?:"([^"]*)"|'([^']*)'|\(([^)]*)\)))?[ \t]*$/); if (definition) { - references[normalizeReferenceLabel(definition[1])] = { href: definition[2].replace(/^<|>$/g, '') }; +- references[normalizeReferenceLabel(definition[1])] = { href: definition[2].replace(/^<|>$/g, '') }; ++ const title = definition[3] ?? definition[4] ?? definition[5]; ++ references[normalizeReferenceLabel(definition[1])] = { href: definition[2].replace(/^<|>$/g, ''), ...(title !== undefined ? { title } : {}) }; index++; + continue; + } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bdc9c5a25..f784409b5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,7 +18,7 @@ overrides: npm-run-path@6.0.0>unicorn-magic: 0.4.0 patchedDependencies: - '@tanstack/markdown@0.0.5': ae0825e87ec7335f705ad024eb28d31d0a2e99c8d9acab09e671828b432dba89 + '@tanstack/markdown@0.0.5': 42bdbc7f0f0d0183adfdfc9c93d706e36a0b099c6bd25a2ad09e22ddc94e426e importers: @@ -110,7 +110,7 @@ importers: version: 0.0.2 '@tanstack/markdown': specifier: ^0.0.5 - version: 0.0.5(patch_hash=ae0825e87ec7335f705ad024eb28d31d0a2e99c8d9acab09e671828b432dba89)(react@19.2.3) + version: 0.0.5(patch_hash=42bdbc7f0f0d0183adfdfc9c93d706e36a0b099c6bd25a2ad09e22ddc94e426e)(react@19.2.3) '@tanstack/pacer': specifier: ^0.21.1 version: 0.21.1 @@ -9671,7 +9671,7 @@ snapshots: dependencies: '@tanstack/store': 0.11.0 - '@tanstack/markdown@0.0.5(patch_hash=ae0825e87ec7335f705ad024eb28d31d0a2e99c8d9acab09e671828b432dba89)(react@19.2.3)': + '@tanstack/markdown@0.0.5(patch_hash=42bdbc7f0f0d0183adfdfc9c93d706e36a0b099c6bd25a2ad09e22ddc94e426e)(react@19.2.3)': optionalDependencies: react: 19.2.3 diff --git a/tests/markdown-link-reference-definitions.test.ts b/tests/markdown-link-reference-definitions.test.ts index a4f792cb0..4a134b2a5 100644 --- a/tests/markdown-link-reference-definitions.test.ts +++ b/tests/markdown-link-reference-definitions.test.ts @@ -5,14 +5,23 @@ const markdownCases = [ { name: 'single-quoted title', markdown: "[//]: # 'SomeLabel'\n\nVisible content.", + referenceMarkdown: + "[example]: https://example.com 'Example title'\n\n[Example][example]", + title: 'Example title', }, { name: 'double-quoted title', markdown: '[//]: # "SomeLabel"\n\nVisible content.', + referenceMarkdown: + '[example]: https://example.com "Example title"\n\n[Example][example]', + title: 'Example title', }, { name: 'parenthesized title', markdown: '[//]: # (SomeLabel)\n\nVisible content.', + referenceMarkdown: + '[example]: https://example.com (Example title)\n\n[Example][example]', + title: 'Example title', }, ] @@ -38,6 +47,45 @@ for (const testCase of markdownCases) { [{ type: 'text', value: 'Visible content.' }], `${testCase.name} visible paragraph is preserved`, ) + + const referenceDocument = parseSiteMarkdown(testCase.referenceMarkdown) + const referenceParagraph = referenceDocument.children[0] + + assert.equal( + referenceParagraph?.type, + 'paragraph', + `${testCase.name} reference link paragraph is parsed`, + ) + + if (referenceParagraph?.type !== 'paragraph') { + throw new Error(`${testCase.name} did not produce a reference paragraph`) + } + + const link = referenceParagraph.children[0] + + assert.equal(link?.type, 'link', `${testCase.name} reference link resolves`) + + if (link?.type !== 'link') { + throw new Error(`${testCase.name} did not produce a reference link`) + } + + assert.equal( + link.href, + 'https://example.com', + `${testCase.name} reference link href is preserved`, + ) + + assert.equal( + link.title, + testCase.title, + `${testCase.name} reference link title is preserved`, + ) + + assert.deepEqual( + link.children, + [{ type: 'text', value: 'Example' }], + `${testCase.name} reference link label is preserved`, + ) } console.log('markdown link reference definition tests passed') From 0a1d7701e32a21b31083dfabdf2c32ce264489ee Mon Sep 17 00:00:00 2001 From: gs0428 Date: Tue, 30 Jun 2026 23:31:48 +0900 Subject: [PATCH 3/3] test(markdown): cover comment-style reference links --- ...arkdown-link-reference-definitions.test.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tests/markdown-link-reference-definitions.test.ts b/tests/markdown-link-reference-definitions.test.ts index 4a134b2a5..594380976 100644 --- a/tests/markdown-link-reference-definitions.test.ts +++ b/tests/markdown-link-reference-definitions.test.ts @@ -48,6 +48,47 @@ for (const testCase of markdownCases) { `${testCase.name} visible paragraph is preserved`, ) + const commentReferenceDocument = parseSiteMarkdown( + `${testCase.markdown}\n\n[Example][//]`, + ) + const commentReferenceParagraph = commentReferenceDocument.children[1] + + assert.equal( + commentReferenceParagraph?.type, + 'paragraph', + `${testCase.name} comment reference link paragraph is parsed`, + ) + + if (commentReferenceParagraph?.type !== 'paragraph') { + throw new Error( + `${testCase.name} did not produce a comment reference paragraph`, + ) + } + + const commentReferenceLink = commentReferenceParagraph.children[0] + + assert.equal( + commentReferenceLink?.type, + 'link', + `${testCase.name} comment reference link resolves`, + ) + + if (commentReferenceLink?.type !== 'link') { + throw new Error(`${testCase.name} did not produce a comment reference link`) + } + + assert.equal( + commentReferenceLink.href, + '#', + `${testCase.name} comment reference link href is preserved`, + ) + + assert.equal( + commentReferenceLink.title, + 'SomeLabel', + `${testCase.name} comment reference link title is preserved`, + ) + const referenceDocument = parseSiteMarkdown(testCase.referenceMarkdown) const referenceParagraph = referenceDocument.children[0]