Skip to content

Commit f298c65

Browse files
authored
Upgrade marked (#217)
* remove default renderer, apparently we never needed this? * update to marked 13 * update to marked 14 * more * more * fix
1 parent 3b34bc6 commit f298c65

File tree

9 files changed

+71
-187
lines changed

9 files changed

+71
-187
lines changed

apps/svelte.dev/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"jimp": "^1.1.1",
7575
"lightningcss": "^1.25.1",
7676
"magic-string": "^0.30.11",
77-
"marked": "^12.0.2",
77+
"marked": "^14.1.2",
7878
"prettier": "^3.3.2",
7979
"prettier-plugin-svelte": "^3.2.4",
8080
"satori": "^0.10.13",

apps/svelte.dev/src/routes/content.json/+server.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,13 @@ async function content() {
9191
}
9292

9393
async function plaintext(markdown: string) {
94-
const block = (text: unknown) => `${text}\n`;
94+
const block = ({ text }: any) => `${text}\n`;
9595

96-
const inline = (text: string) => text;
96+
const inline = ({ text }: any) => text;
9797

9898
return (
9999
await markedTransform(markdown, {
100-
code: (source) => source.split('// ---cut---\n').pop() || 'ERROR: ---cut--- not found',
100+
code: ({ text }) => text.split('// ---cut---\n').pop() || 'ERROR: ---cut--- not found',
101101
blockquote: block,
102102
html: () => '\n',
103103
heading: (text) => `${text}\n`,
@@ -108,16 +108,16 @@ async function plaintext(markdown: string) {
108108
paragraph: (text) => `${text}\n\n`,
109109
table: block,
110110
tablerow: block,
111-
tablecell: (text, opts) => {
111+
tablecell: ({ text }) => {
112112
return text + ' ';
113113
},
114114
strong: inline,
115115
em: inline,
116116
codespan: inline,
117117
br: () => '',
118118
del: inline,
119-
link: (href, title, text) => text,
120-
image: (href, title, text) => text,
119+
link: inline,
120+
image: inline,
121121
text: inline
122122
})
123123
)

apps/svelte.dev/src/routes/tutorial/[slug]/markdown.server.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,19 @@ function highlight_spans(content, classname) {
3838

3939
/** @type {Partial<import('marked').Renderer>} */
4040
const default_renderer = {
41-
code: (source, language = '') => {
41+
code: ({ text, lang = '' }) => {
4242
/** @type {Record<string, string>} */
4343
const options = {};
4444

4545
let html = '';
4646

47-
source = source
47+
let source = text
4848
.replace(/\/\/\/ (.+?)(?:: (.+))?\n/gm, (_, key, value) => {
4949
options[key] = value;
5050
return '';
5151
})
5252
.replace(/^([\-\+])?((?: )+)/gm, (match, prefix = '', spaces) => {
53-
if (prefix && language !== 'diff') return match;
53+
if (prefix && lang !== 'diff') return match;
5454

5555
// for no good reason at all, marked replaces tabs with spaces
5656
let tabs = '';
@@ -64,7 +64,7 @@ const default_renderer = {
6464
})
6565
.replace(/\*\\\//g, '*/');
6666

67-
if (language === 'diff') {
67+
if (lang === 'diff') {
6868
const lines = source.split('\n').map((content) => {
6969
let type = null;
7070
if (/^[\+\-]/.test(content)) {
@@ -85,10 +85,9 @@ const default_renderer = {
8585
})
8686
.join('')}</code></pre></div>`;
8787
} else {
88-
const lang = /** @type {keyof languages} */ (language);
89-
const plang = languages[lang];
88+
const plang = languages[/** @type {keyof languages} */ (lang)];
9089
const highlighted = plang
91-
? PrismJS.highlight(source, PrismJS.languages[plang], language)
90+
? PrismJS.highlight(source, PrismJS.languages[plang], lang)
9291
: escape_html(source);
9392

9493
html = `<div class="code-block">${

apps/svelte.dev/src/routes/tutorial/content.json/+server.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,19 @@ async function content() {
3333
return { blocks };
3434
}
3535

36+
// TODO is this still used?
37+
3638
/** @param {string} markdown */
3739
async function plaintext(markdown) {
38-
/** @param {unknown} text */
39-
const block = (text) => `${text}\n`;
40+
/** @param {any} token */
41+
const block = ({ text }) => `${text}\n`;
4042

41-
/** @param {string} text */
42-
const inline = (text) => text;
43+
/** @param {any} token */
44+
const inline = ({ text }) => text;
4345

4446
return (
4547
await markedTransform(markdown, {
46-
code: (source) => source.split('// ---cut---\n').pop() ?? '',
48+
code: ({ text }) => text.split('// ---cut---\n').pop() ?? '',
4749
blockquote: block,
4850
html: () => '\n',
4951
heading: (text) => `${text}\n`,
@@ -54,16 +56,16 @@ async function plaintext(markdown) {
5456
paragraph: (text) => `${text}\n\n`,
5557
table: block,
5658
tablerow: block,
57-
tablecell: (text, opts) => {
59+
tablecell: ({ text }) => {
5860
return text + ' ';
5961
},
6062
strong: inline,
6163
em: inline,
6264
codespan: inline,
6365
br: () => '',
6466
del: inline,
65-
link: (href, title, text) => text,
66-
image: (href, title, text) => text,
67+
link: inline,
68+
image: inline,
6769
text: inline
6870
})
6971
)

packages/repl/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
"acorn": "^8.11.3",
7979
"esm-env": "^1.0.0",
8080
"esrap": "^1.2.2",
81-
"marked": "^11.2.0",
81+
"marked": "^14.1.2",
8282
"resolve.exports": "^2.0.2",
8383
"svelte": "^5.0.0-next.243",
8484
"zimmerframe": "^1.1.2"

packages/site-kit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"@types/node": "^20.12.11",
3535
"flexsearch": "^0.7.43",
3636
"magic-string": "^0.30.11",
37-
"marked": "^12.0.2",
37+
"marked": "^14.1.2",
3838
"prettier": "^3.3.2",
3939
"prettier-plugin-svelte": "^3.2.4",
4040
"shiki-twoslash": "^3.1.2",

packages/site-kit/src/lib/markdown/renderer.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -259,42 +259,50 @@ async function parse({
259259
// from linking to themselves
260260
let current = '';
261261

262-
/** @type {string} */
263-
const content = await transform(body, {
264-
text: smart_quotes,
265-
heading(html, level, raw) {
266-
const title = html
262+
return await transform(body, {
263+
text(token) {
264+
// @ts-expect-error I think this is a bug in marked — some text tokens have children,
265+
// but that's not reflected in the types. In these cases we can't just use `token.tokens`
266+
// because that will result in e.g. `<code>` elements not being generated
267+
if (token.tokens) {
268+
// @ts-expect-error
269+
return this.parser!.parseInline(token.tokens);
270+
}
271+
272+
return smart_quotes(token.text);
273+
},
274+
heading({ tokens, depth, raw }) {
275+
const text = this.parser!.parseInline(tokens);
276+
277+
const title = text
267278
.replace(/<\/?code>/g, '')
268279
.replace(/&quot;/g, '"')
269280
.replace(/&lt;/g, '<')
270281
.replace(/&gt;/g, '>');
271-
272282
current = title;
273-
274283
const normalized = normalizeSlugify(raw);
275-
276-
headings[level - 1] = normalized;
277-
headings.length = level;
278-
284+
headings[depth - 1] = normalized;
285+
headings.length = depth;
279286
const slug = headings.filter(Boolean).join('-');
280-
281-
return `<h${level} id="${slug}">${html.replace(
287+
return `<h${depth} id="${slug}">${text.replace(
282288
/<\/?code>/g,
283289
''
284-
)}<a href="#${slug}" class="permalink"><span class="visually-hidden">permalink</span></a></h${level}>`;
290+
)}<a href="#${slug}" class="permalink"><span class="visually-hidden">permalink</span></a></h${depth}>`;
291+
},
292+
code({ text, lang }) {
293+
return code(text, lang ?? 'js', current);
294+
},
295+
codespan({ text }) {
296+
return codespan(text);
285297
},
286-
code: (source, language) => code(source, language ?? 'js', current),
287-
codespan,
288-
blockquote: (content) => {
298+
blockquote(token) {
299+
let content = this.parser?.parse(token.tokens) ?? '';
289300
if (content.includes('[!LEGACY]')) {
290301
content = `<details class="legacy"><summary>Legacy mode</summary>${content.replace('[!LEGACY]', '')}</details>`;
291302
}
292-
293303
return `<blockquote>${content}</blockquote>`;
294304
}
295305
});
296-
297-
return content;
298306
}
299307

300308
/**

packages/site-kit/src/lib/markdown/utils.ts

Lines changed: 1 addition & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -91,126 +91,6 @@ export function smart_quotes(str: string) {
9191
});
9292
}
9393

94-
const default_renderer: Partial<Renderer> = {
95-
code(code, infostring, escaped) {
96-
const lang = infostring?.match(/\S*/)?.[0];
97-
98-
code = code.replace(/\n$/, '') + '\n';
99-
100-
if (!lang) {
101-
return '<pre><code>' + (escaped ? code : escape(code, true)) + '</code></pre>\n';
102-
}
103-
104-
return (
105-
'<pre><code class="language-' +
106-
escape(lang, true) +
107-
'">' +
108-
(escaped ? code : escape(code, true)) +
109-
'</code></pre>\n'
110-
);
111-
},
112-
113-
blockquote(quote) {
114-
return '<blockquote>\n' + quote + '</blockquote>\n';
115-
},
116-
117-
html(html) {
118-
return html;
119-
},
120-
121-
heading(text, level) {
122-
return '<h' + level + '>' + text + '</h' + level + '>\n';
123-
},
124-
125-
hr() {
126-
return '<hr>\n';
127-
},
128-
129-
list(body, ordered, start) {
130-
const type = ordered ? 'ol' : 'ul',
131-
startatt = ordered && start !== 1 ? ' start="' + start + '"' : '';
132-
return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
133-
},
134-
135-
listitem(text) {
136-
return '<li>' + text + '</li>\n';
137-
},
138-
139-
checkbox(checked) {
140-
return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox"' + '' + '> ';
141-
},
142-
143-
paragraph(text) {
144-
return '<p>' + text + '</p>\n';
145-
},
146-
147-
table(header, body) {
148-
if (body) body = '<tbody>' + body + '</tbody>';
149-
150-
return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
151-
},
152-
153-
tablerow(content) {
154-
return '<tr>\n' + content + '</tr>\n';
155-
},
156-
157-
tablecell(content, flags) {
158-
const type = flags.header ? 'th' : 'td';
159-
const tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>';
160-
return tag + content + '</' + type + '>\n';
161-
},
162-
163-
// span level renderer
164-
strong(text) {
165-
return '<strong>' + text + '</strong>';
166-
},
167-
168-
em(text) {
169-
return '<em>' + text + '</em>';
170-
},
171-
172-
codespan(text) {
173-
return '<code>' + text + '</code>';
174-
},
175-
176-
br() {
177-
return '<br>';
178-
},
179-
180-
del(text) {
181-
return '<del>' + text + '</del>';
182-
},
183-
184-
link(href, title, text) {
185-
if (href === null) {
186-
return text;
187-
}
188-
let out = '<a href="' + escape(href) + '"';
189-
if (title) {
190-
out += ' title="' + title + '"';
191-
}
192-
out += '>' + text + '</a>';
193-
return out;
194-
},
195-
196-
image(href, title, text) {
197-
if (href === null) {
198-
return text;
199-
}
200-
201-
let out = '<img src="' + href + '" alt="' + text + '"';
202-
if (title) {
203-
out += ' title="' + title + '"';
204-
}
205-
out += '>';
206-
return out;
207-
},
208-
209-
text(text) {
210-
return text;
211-
}
212-
};
213-
21494
const tokenizer: TokenizerObject = {
21595
url(src) {
21696
// if `src` is a package version string, eg: [email protected]
@@ -225,10 +105,7 @@ const tokenizer: TokenizerObject = {
225105

226106
export async function transform(markdown: string, renderer: Partial<Renderer> = {}) {
227107
const marked = new Marked({
228-
renderer: {
229-
...default_renderer,
230-
...renderer
231-
},
108+
renderer,
232109
tokenizer
233110
});
234111

0 commit comments

Comments
 (0)