diff --git a/site/content/docs/03-runtime/01-svelte.md b/site/content/docs/03-runtime/01-svelte.md index b62bdfeed8..1072949263 100644 --- a/site/content/docs/03-runtime/01-svelte.md +++ b/site/content/docs/03-runtime/01-svelte.md @@ -246,3 +246,7 @@ Events can be cancelable by passing a third parameter to the dispatch function. } ``` + +## Types + +> TYPES: svelte diff --git a/site/content/docs/03-runtime/02-svelte-store.md b/site/content/docs/03-runtime/02-svelte-store.md index 5f143b738c..9550a00529 100644 --- a/site/content/docs/03-runtime/02-svelte-store.md +++ b/site/content/docs/03-runtime/02-svelte-store.md @@ -192,3 +192,7 @@ import { get } from 'svelte/store'; const value = get(store); ``` + +## Types + +> TYPES: svelte/store diff --git a/site/content/docs/03-runtime/03-svelte-motion.md b/site/content/docs/03-runtime/03-svelte-motion.md index 4cab7725cc..c40991fafa 100644 --- a/site/content/docs/03-runtime/03-svelte-motion.md +++ b/site/content/docs/03-runtime/03-svelte-motion.md @@ -139,3 +139,7 @@ If the initial value is `undefined` or `null`, the first value change will take const size = spring(); $: $size = big ? 100 : 10; ``` + +## Types + +> TYPES: svelte/motion diff --git a/site/content/docs/03-runtime/04-svelte-transition.md b/site/content/docs/03-runtime/04-svelte-transition.md index bc33c6ee17..c30e659b51 100644 --- a/site/content/docs/03-runtime/04-svelte-transition.md +++ b/site/content/docs/03-runtime/04-svelte-transition.md @@ -262,3 +262,7 @@ The `crossfade` function creates a pair of [transitions](/docs/element-directive small elem {/if} ``` + +## Types + +> TYPES: svelte/transition diff --git a/site/content/docs/03-runtime/05-svelte-animate.md b/site/content/docs/03-runtime/05-svelte-animate.md index b9d71cee0b..3d9c719308 100644 --- a/site/content/docs/03-runtime/05-svelte-animate.md +++ b/site/content/docs/03-runtime/05-svelte-animate.md @@ -39,3 +39,7 @@ You can see a full example on the [animations tutorial](/tutorial/animate) {/each} ``` + +## Types + +> TYPES: svelte/animate diff --git a/sites/svelte.dev/src/lib/server/docs/index.js b/sites/svelte.dev/src/lib/server/docs/index.js index 53c8121687..5667d620ab 100644 --- a/sites/svelte.dev/src/lib/server/docs/index.js +++ b/sites/svelte.dev/src/lib/server/docs/index.js @@ -4,7 +4,7 @@ // import 'prismjs/components/prism-typescript.js'; import { createShikiHighlighter } from 'shiki-twoslash'; import { SHIKI_LANGUAGE_MAP, normalizeSlugify, transform } from '../markdown'; -// import { render, replace_placeholders } from './render.js'; +import { replace_placeholders } from './render.js'; // import { parse_route_id } from '../../../../../../packages/kit/src/utils/routing.js'; import { createHash } from 'crypto'; import MagicString from 'magic-string'; @@ -23,11 +23,13 @@ export async function get_parsed_docs(docs_data, slug) { const highlighter = await createShikiHighlighter({ theme: 'css-variables' }); + const placeholders_replaced_content = replace_placeholders(page.content); + return { ...page, content: parse({ file: page.file, - body: generate_ts_from_js(page.content), + body: generate_ts_from_js(placeholders_replaced_content), code: (source, language, current) => { const hash = createHash('sha256'); hash.update(source + language + current); diff --git a/sites/svelte.dev/src/lib/server/docs/render.js b/sites/svelte.dev/src/lib/server/docs/render.js new file mode 100644 index 0000000000..5db1dfce3c --- /dev/null +++ b/sites/svelte.dev/src/lib/server/docs/render.js @@ -0,0 +1,137 @@ +import { modules } from '$lib/generated/type-info.js'; + +/** @param {string} content */ +export function replace_placeholders(content) { + return content + .replace(/> EXPANDED_TYPES: (.+?)#(.+)$/gm, (_, name, id) => { + const module = modules.find((module) => module.name === name); + if (!module) throw new Error(`Could not find module ${name}`); + + console.log(module); + + const type = module.types.find((t) => t.name === id); + + return ( + type.comment + + type.children + .map((child) => { + let section = `### ${child.name}`; + + if (child.bullets) { + section += `\n\n
\n\n${child.bullets.join( + '\n' + )}\n\n
`; + } + + section += `\n\n${child.comment}`; + + if (child.children) { + section += `\n\n
\n\n${child.children + .map(stringify) + .join('\n')}\n\n
`; + } + + return section; + }) + .join('\n\n') + ); + }) + .replace(/> TYPES: (.+?)(?:#(.+))?$/gm, (_, name, id) => { + const module = modules.find((module) => module.name === name); + if (!module) throw new Error(`Could not find module ${name}`); + + if (id) { + const type = module.types.find((t) => t.name === id); + + return ( + `
${fence(type.snippet)}` + + type.children.map(stringify).join('\n\n') + + `
` + ); + } + + return `${module.comment}\n\n${module.types + .map((t) => { + let children = t.children.map(stringify).join('\n\n'); + if (t.name === 'Config' || t.name === 'KitConfig') { + // special case — we want these to be on a separate page + children = + '
\n\nSee the [configuration reference](/docs/configuration) for details.
'; + } + + const markdown = `
${fence(t.snippet)}` + children + `
`; + return `### ${t.name}\n\n${t.comment}\n\n${markdown}\n\n`; + }) + .join('')}`; + }) + .replace('> MODULES', () => { + return modules + .map((module) => { + if (module.exports.length === 0 && !module.exempt) return ''; + + let import_block = ''; + + if (module.exports.length > 0) { + // deduplication is necessary for now, because of `error()` overload + const exports = Array.from(new Set(module.exports.map((x) => x.name))); + + let declaration = `import { ${exports.join(', ')} } from '${module.name}';`; + if (declaration.length > 80) { + declaration = `import {\n\t${exports.join(',\n\t')}\n} from '${module.name}';`; + } + + import_block = fence(declaration, 'js'); + } + + return `## ${module.name}\n\n${import_block}\n\n${module.comment}\n\n${module.exports + .map((type) => { + const markdown = + `
${fence(type.snippet)}` + + type.children.map(stringify).join('\n\n') + + `
`; + return `### ${type.name}\n\n${type.comment}\n\n${markdown}`; + }) + .join('\n\n')}`; + }) + .join('\n\n'); + }); +} + +/** + * @param {string} code + * @param {string} lang + */ +function fence(code, lang = 'ts') { + return '\n\n```' + lang + '\n' + code + '\n```\n\n'; +} + +/** + * @param {import('./types').Type} member + */ +function stringify(member) { + const bullet_block = + member.bullets.length > 0 + ? `\n\n
\n\n${member.bullets.join('\n')}
` + : ''; + + const child_block = + member.children.length > 0 + ? `\n\n
${member.children + .map(stringify) + .join('\n')}
` + : ''; + + return ( + `
${fence(member.snippet)}` + + `
\n\n` + + bullet_block + + '\n\n' + + member.comment + .replace(/\/\/\/ type: (.+)/g, '/** @type {$1} */') + .replace(/^( )+/gm, (match, spaces) => { + return '\t'.repeat(match.length / 2); + }) + + child_block + + '\n
' + ); +}