diff --git a/patches/@tanstack__markdown@0.0.5.patch b/patches/@tanstack__markdown@0.0.5.patch new file mode 100644 index 000000000..06842b19c --- /dev/null +++ b/patches/@tanstack__markdown@0.0.5.patch @@ -0,0 +1,17 @@ +diff --git a/dist/parser.js b/dist/parser.js +index 6616130a037737d109c527ec23ea8149ad8a68aa..be8c5b941d9437324b74f353fb3a51293a029740 100644 +--- a/dist/parser.js ++++ b/dist/parser.js +@@ -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]*$/); + if (definition) { +- 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 d935d005a..f784409b5 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': 42bdbc7f0f0d0183adfdfc9c93d706e36a0b099c6bd25a2ad09e22ddc94e426e + 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=42bdbc7f0f0d0183adfdfc9c93d706e36a0b099c6bd25a2ad09e22ddc94e426e)(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=42bdbc7f0f0d0183adfdfc9c93d706e36a0b099c6bd25a2ad09e22ddc94e426e)(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..594380976 --- /dev/null +++ b/tests/markdown-link-reference-definitions.test.ts @@ -0,0 +1,132 @@ +import assert from 'node:assert/strict' +import { parseSiteMarkdown } from '../src/utils/markdown' + +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', + }, +] + +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`, + ) + + 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] + + 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')