Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/svelte.dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
12 changes: 6 additions & 6 deletions apps/svelte.dev/src/routes/content.json/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand All @@ -108,16 +108,16 @@ async function plaintext(markdown: string) {
paragraph: (text) => `${text}\n\n`,
table: block,
tablerow: block,
tablecell: (text, opts) => {
tablecell: ({ text }) => {
return text + ' ';
},
strong: inline,
em: inline,
codespan: inline,
br: () => '',
del: inline,
link: (href, title, text) => text,
image: (href, title, text) => text,
link: inline,
image: inline,
text: inline
})
)
Expand Down
13 changes: 6 additions & 7 deletions apps/svelte.dev/src/routes/tutorial/[slug]/markdown.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,19 @@ function highlight_spans(content, classname) {

/** @type {Partial<import('marked').Renderer>} */
const default_renderer = {
code: (source, language = '') => {
code: ({ text, lang = '' }) => {
/** @type {Record<string, string>} */
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 = '';
Expand All @@ -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)) {
Expand All @@ -85,10 +85,9 @@ const default_renderer = {
})
.join('')}</code></pre></div>`;
} 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 = `<div class="code-block">${
Expand Down
18 changes: 10 additions & 8 deletions apps/svelte.dev/src/routes/tutorial/content.json/+server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
Expand All @@ -54,16 +56,16 @@ async function plaintext(markdown) {
paragraph: (text) => `${text}\n\n`,
table: block,
tablerow: block,
tablecell: (text, opts) => {
tablecell: ({ text }) => {
return text + ' ';
},
strong: inline,
em: inline,
codespan: inline,
br: () => '',
del: inline,
link: (href, title, text) => text,
image: (href, title, text) => text,
link: inline,
image: inline,
text: inline
})
)
Expand Down
2 changes: 1 addition & 1 deletion packages/repl/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion packages/site-kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
48 changes: 28 additions & 20 deletions packages/site-kit/src/lib/markdown/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. `<code>` 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(/&quot;/g, '"')
.replace(/&lt;/g, '<')
.replace(/&gt;/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 `<h${level} id="${slug}">${html.replace(
return `<h${depth} id="${slug}">${text.replace(
/<\/?code>/g,
''
)}<a href="#${slug}" class="permalink"><span class="visually-hidden">permalink</span></a></h${level}>`;
)}<a href="#${slug}" class="permalink"><span class="visually-hidden">permalink</span></a></h${depth}>`;
},
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 = `<details class="legacy"><summary>Legacy mode</summary>${content.replace('[!LEGACY]', '')}</details>`;
}

return `<blockquote>${content}</blockquote>`;
}
});

return content;
}

/**
Expand Down
125 changes: 1 addition & 124 deletions packages/site-kit/src/lib/markdown/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,126 +91,6 @@ export function smart_quotes(str: string) {
});
}

const default_renderer: Partial<Renderer> = {
code(code, infostring, escaped) {
const lang = infostring?.match(/\S*/)?.[0];

code = code.replace(/\n$/, '') + '\n';

if (!lang) {
return '<pre><code>' + (escaped ? code : escape(code, true)) + '</code></pre>\n';
}

return (
'<pre><code class="language-' +
escape(lang, true) +
'">' +
(escaped ? code : escape(code, true)) +
'</code></pre>\n'
);
},

blockquote(quote) {
return '<blockquote>\n' + quote + '</blockquote>\n';
},

html(html) {
return html;
},

heading(text, level) {
return '<h' + level + '>' + text + '</h' + level + '>\n';
},

hr() {
return '<hr>\n';
},

list(body, ordered, start) {
const type = ordered ? 'ol' : 'ul',
startatt = ordered && start !== 1 ? ' start="' + start + '"' : '';
return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
},

listitem(text) {
return '<li>' + text + '</li>\n';
},

checkbox(checked) {
return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox"' + '' + '> ';
},

paragraph(text) {
return '<p>' + text + '</p>\n';
},

table(header, body) {
if (body) body = '<tbody>' + body + '</tbody>';

return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
},

tablerow(content) {
return '<tr>\n' + content + '</tr>\n';
},

tablecell(content, flags) {
const type = flags.header ? 'th' : 'td';
const tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>';
return tag + content + '</' + type + '>\n';
},

// span level renderer
strong(text) {
return '<strong>' + text + '</strong>';
},

em(text) {
return '<em>' + text + '</em>';
},

codespan(text) {
return '<code>' + text + '</code>';
},

br() {
return '<br>';
},

del(text) {
return '<del>' + text + '</del>';
},

link(href, title, text) {
if (href === null) {
return text;
}
let out = '<a href="' + escape(href) + '"';
if (title) {
out += ' title="' + title + '"';
}
out += '>' + text + '</a>';
return out;
},

image(href, title, text) {
if (href === null) {
return text;
}

let out = '<img src="' + href + '" alt="' + text + '"';
if (title) {
out += ' title="' + title + '"';
}
out += '>';
return out;
},

text(text) {
return text;
}
};

const tokenizer: TokenizerObject = {
url(src) {
// if `src` is a package version string, eg: [email protected]
Expand All @@ -225,10 +105,7 @@ const tokenizer: TokenizerObject = {

export async function transform(markdown: string, renderer: Partial<Renderer> = {}) {
const marked = new Marked({
renderer: {
...default_renderer,
...renderer
},
renderer,
tokenizer
});

Expand Down
Loading
Loading