diff --git a/apps/svelte.dev/package.json b/apps/svelte.dev/package.json index 85df3cc57..1d904e8bd 100644 --- a/apps/svelte.dev/package.json +++ b/apps/svelte.dev/package.json @@ -74,7 +74,7 @@ "jimp": "^1.1.1", "lightningcss": "^1.25.1", "magic-string": "^0.30.11", - "marked": "^12.0.2", + "marked": "^14.1.2", "prettier": "^3.3.2", "prettier-plugin-svelte": "^3.2.4", "satori": "^0.10.13", diff --git a/apps/svelte.dev/src/routes/content.json/+server.ts b/apps/svelte.dev/src/routes/content.json/+server.ts index cd0c45832..48f5556ea 100644 --- a/apps/svelte.dev/src/routes/content.json/+server.ts +++ b/apps/svelte.dev/src/routes/content.json/+server.ts @@ -91,13 +91,13 @@ async function content() { } async function plaintext(markdown: string) { - const block = (text: unknown) => `${text}\n`; + const block = ({ text }: any) => `${text}\n`; - const inline = (text: string) => text; + const inline = ({ text }: any) => text; return ( await markedTransform(markdown, { - code: (source) => source.split('// ---cut---\n').pop() || 'ERROR: ---cut--- not found', + code: ({ text }) => text.split('// ---cut---\n').pop() || 'ERROR: ---cut--- not found', blockquote: block, html: () => '\n', heading: (text) => `${text}\n`, @@ -108,7 +108,7 @@ async function plaintext(markdown: string) { paragraph: (text) => `${text}\n\n`, table: block, tablerow: block, - tablecell: (text, opts) => { + tablecell: ({ text }) => { return text + ' '; }, strong: inline, @@ -116,8 +116,8 @@ async function plaintext(markdown: string) { codespan: inline, br: () => '', del: inline, - link: (href, title, text) => text, - image: (href, title, text) => text, + link: inline, + image: inline, text: inline }) ) diff --git a/apps/svelte.dev/src/routes/tutorial/[slug]/markdown.server.js b/apps/svelte.dev/src/routes/tutorial/[slug]/markdown.server.js index 0ea12b6f9..05ffc9a7f 100644 --- a/apps/svelte.dev/src/routes/tutorial/[slug]/markdown.server.js +++ b/apps/svelte.dev/src/routes/tutorial/[slug]/markdown.server.js @@ -38,19 +38,19 @@ function highlight_spans(content, classname) { /** @type {Partial} */ const default_renderer = { - code: (source, language = '') => { + code: ({ text, lang = '' }) => { /** @type {Record} */ const options = {}; let html = ''; - source = source + let source = text .replace(/\/\/\/ (.+?)(?:: (.+))?\n/gm, (_, key, value) => { options[key] = value; return ''; }) .replace(/^([\-\+])?((?: )+)/gm, (match, prefix = '', spaces) => { - if (prefix && language !== 'diff') return match; + if (prefix && lang !== 'diff') return match; // for no good reason at all, marked replaces tabs with spaces let tabs = ''; @@ -64,7 +64,7 @@ const default_renderer = { }) .replace(/\*\\\//g, '*/'); - if (language === 'diff') { + if (lang === 'diff') { const lines = source.split('\n').map((content) => { let type = null; if (/^[\+\-]/.test(content)) { @@ -85,10 +85,9 @@ const default_renderer = { }) .join('')}`; } else { - const lang = /** @type {keyof languages} */ (language); - const plang = languages[lang]; + const plang = languages[/** @type {keyof languages} */ (lang)]; const highlighted = plang - ? PrismJS.highlight(source, PrismJS.languages[plang], language) + ? PrismJS.highlight(source, PrismJS.languages[plang], lang) : escape_html(source); html = `
${ diff --git a/apps/svelte.dev/src/routes/tutorial/content.json/+server.js b/apps/svelte.dev/src/routes/tutorial/content.json/+server.js index fa9227c71..5d6638dc6 100644 --- a/apps/svelte.dev/src/routes/tutorial/content.json/+server.js +++ b/apps/svelte.dev/src/routes/tutorial/content.json/+server.js @@ -33,17 +33,19 @@ async function content() { return { blocks }; } +// TODO is this still used? + /** @param {string} markdown */ async function plaintext(markdown) { - /** @param {unknown} text */ - const block = (text) => `${text}\n`; + /** @param {any} token */ + const block = ({ text }) => `${text}\n`; - /** @param {string} text */ - const inline = (text) => text; + /** @param {any} token */ + const inline = ({ text }) => text; return ( await markedTransform(markdown, { - code: (source) => source.split('// ---cut---\n').pop() ?? '', + code: ({ text }) => text.split('// ---cut---\n').pop() ?? '', blockquote: block, html: () => '\n', heading: (text) => `${text}\n`, @@ -54,7 +56,7 @@ async function plaintext(markdown) { paragraph: (text) => `${text}\n\n`, table: block, tablerow: block, - tablecell: (text, opts) => { + tablecell: ({ text }) => { return text + ' '; }, strong: inline, @@ -62,8 +64,8 @@ async function plaintext(markdown) { codespan: inline, br: () => '', del: inline, - link: (href, title, text) => text, - image: (href, title, text) => text, + link: inline, + image: inline, text: inline }) ) diff --git a/packages/repl/package.json b/packages/repl/package.json index 515db37a0..5fd8e0e9f 100644 --- a/packages/repl/package.json +++ b/packages/repl/package.json @@ -78,7 +78,7 @@ "acorn": "^8.11.3", "esm-env": "^1.0.0", "esrap": "^1.2.2", - "marked": "^11.2.0", + "marked": "^14.1.2", "resolve.exports": "^2.0.2", "svelte": "^5.0.0-next.243", "zimmerframe": "^1.1.2" diff --git a/packages/site-kit/package.json b/packages/site-kit/package.json index 1a029592a..7c06dcf4e 100644 --- a/packages/site-kit/package.json +++ b/packages/site-kit/package.json @@ -34,7 +34,7 @@ "@types/node": "^20.12.11", "flexsearch": "^0.7.43", "magic-string": "^0.30.11", - "marked": "^12.0.2", + "marked": "^14.1.2", "prettier": "^3.3.2", "prettier-plugin-svelte": "^3.2.4", "shiki-twoslash": "^3.1.2", diff --git a/packages/site-kit/src/lib/markdown/renderer.ts b/packages/site-kit/src/lib/markdown/renderer.ts index e99588a39..e5b1fdebc 100644 --- a/packages/site-kit/src/lib/markdown/renderer.ts +++ b/packages/site-kit/src/lib/markdown/renderer.ts @@ -259,42 +259,50 @@ async function parse({ // from linking to themselves let current = ''; - /** @type {string} */ - const content = await transform(body, { - text: smart_quotes, - heading(html, level, raw) { - const title = html + return await transform(body, { + text(token) { + // @ts-expect-error I think this is a bug in marked — some text tokens have children, + // but that's not reflected in the types. In these cases we can't just use `token.tokens` + // because that will result in e.g. `` elements not being generated + if (token.tokens) { + // @ts-expect-error + return this.parser!.parseInline(token.tokens); + } + + return smart_quotes(token.text); + }, + heading({ tokens, depth, raw }) { + const text = this.parser!.parseInline(tokens); + + const title = text .replace(/<\/?code>/g, '') .replace(/"/g, '"') .replace(/</g, '<') .replace(/>/g, '>'); - current = title; - const normalized = normalizeSlugify(raw); - - headings[level - 1] = normalized; - headings.length = level; - + headings[depth - 1] = normalized; + headings.length = depth; const slug = headings.filter(Boolean).join('-'); - - return `${html.replace( + return `${text.replace( /<\/?code>/g, '' - )}`; + )}`; + }, + code({ text, lang }) { + return code(text, lang ?? 'js', current); + }, + codespan({ text }) { + return codespan(text); }, - code: (source, language) => code(source, language ?? 'js', current), - codespan, - blockquote: (content) => { + blockquote(token) { + let content = this.parser?.parse(token.tokens) ?? ''; if (content.includes('[!LEGACY]')) { content = `
Legacy mode${content.replace('[!LEGACY]', '')}
`; } - return `
${content}
`; } }); - - return content; } /** diff --git a/packages/site-kit/src/lib/markdown/utils.ts b/packages/site-kit/src/lib/markdown/utils.ts index 4a0ff38da..f5b7433a9 100644 --- a/packages/site-kit/src/lib/markdown/utils.ts +++ b/packages/site-kit/src/lib/markdown/utils.ts @@ -91,126 +91,6 @@ export function smart_quotes(str: string) { }); } -const default_renderer: Partial = { - code(code, infostring, escaped) { - const lang = infostring?.match(/\S*/)?.[0]; - - code = code.replace(/\n$/, '') + '\n'; - - if (!lang) { - return '
' + (escaped ? code : escape(code, true)) + '
\n'; - } - - return ( - '
' +
-			(escaped ? code : escape(code, true)) +
-			'
\n' - ); - }, - - blockquote(quote) { - return '
\n' + quote + '
\n'; - }, - - html(html) { - return html; - }, - - heading(text, level) { - return '' + text + '\n'; - }, - - hr() { - return '
\n'; - }, - - list(body, ordered, start) { - const type = ordered ? 'ol' : 'ul', - startatt = ordered && start !== 1 ? ' start="' + start + '"' : ''; - return '<' + type + startatt + '>\n' + body + '\n'; - }, - - listitem(text) { - return '
  • ' + text + '
  • \n'; - }, - - checkbox(checked) { - return ' '; - }, - - paragraph(text) { - return '

    ' + text + '

    \n'; - }, - - table(header, body) { - if (body) body = '' + body + ''; - - return '\n' + '\n' + header + '\n' + body + '
    \n'; - }, - - tablerow(content) { - return '\n' + content + '\n'; - }, - - tablecell(content, flags) { - const type = flags.header ? 'th' : 'td'; - const tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>'; - return tag + content + '\n'; - }, - - // span level renderer - strong(text) { - return '' + text + ''; - }, - - em(text) { - return '' + text + ''; - }, - - codespan(text) { - return '' + text + ''; - }, - - br() { - return '
    '; - }, - - del(text) { - return '' + text + ''; - }, - - link(href, title, text) { - if (href === null) { - return text; - } - let out = ''; - return out; - }, - - image(href, title, text) { - if (href === null) { - return text; - } - - let out = '' + text + ' = {}) { const marked = new Marked({ - renderer: { - ...default_renderer, - ...renderer - }, + renderer, tokenizer }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 12e29ae18..01f39264b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -181,8 +181,8 @@ importers: specifier: ^0.30.11 version: 0.30.11 marked: - specifier: ^12.0.2 - version: 12.0.2 + specifier: ^14.1.2 + version: 14.1.2 prettier: specifier: ^3.3.2 version: 3.3.2 @@ -295,8 +295,8 @@ importers: specifier: ^1.2.2 version: 1.2.2 marked: - specifier: ^11.2.0 - version: 11.2.0 + specifier: ^14.1.2 + version: 14.1.2 resolve.exports: specifier: ^2.0.2 version: 2.0.2 @@ -378,8 +378,8 @@ importers: specifier: ^0.30.11 version: 0.30.11 marked: - specifier: ^12.0.2 - version: 12.0.2 + specifier: ^14.1.2 + version: 14.1.2 prettier: specifier: ^3.3.2 version: 3.3.2 @@ -1026,6 +1026,9 @@ packages: '@lezer/common@1.2.1': resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==} + '@lezer/common@1.2.2': + resolution: {integrity: sha512-Z+R3hN6kXbgBWAuejUNPihylAL1Z5CaFqnIe0nTX8Ej+XlIy3EGtXxn6WtLMO+os2hRkQvm2yvaGMYliUzlJaw==} + '@lezer/css@1.1.8': resolution: {integrity: sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==} @@ -2141,13 +2144,8 @@ packages: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} - marked@11.2.0: - resolution: {integrity: sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==} - engines: {node: '>= 18'} - hasBin: true - - marked@12.0.2: - resolution: {integrity: sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==} + marked@14.1.2: + resolution: {integrity: sha512-f3r0yqpz31VXiDB/wj9GaOB0a2PRLQl6vJmXiFrniNwjkKdvakqJRULhjFKJpxOchlCRiG5fcacoUZY5Xa6PEQ==} engines: {node: '>= 18'} hasBin: true @@ -3591,6 +3589,8 @@ snapshots: '@lezer/common@1.2.1': {} + '@lezer/common@1.2.2': {} + '@lezer/css@1.1.8': dependencies: '@lezer/common': 1.2.1 @@ -3603,7 +3603,7 @@ snapshots: '@lezer/highlight@1.2.1': dependencies: - '@lezer/common': 1.2.1 + '@lezer/common': 1.2.2 '@lezer/html@1.3.9': dependencies: @@ -3619,7 +3619,7 @@ snapshots: '@lezer/javascript@1.4.17': dependencies: - '@lezer/common': 1.2.1 + '@lezer/common': 1.2.2 '@lezer/highlight': 1.2.1 '@lezer/lr': 1.4.1 @@ -3635,7 +3635,7 @@ snapshots: '@lezer/lr@1.4.1': dependencies: - '@lezer/common': 1.2.1 + '@lezer/common': 1.2.2 '@lezer/markdown@1.3.0': dependencies: @@ -4815,9 +4815,7 @@ snapshots: dependencies: semver: 6.3.1 - marked@11.2.0: {} - - marked@12.0.2: {} + marked@14.1.2: {} merge2@1.4.1: {}