From 5d79eb809503c46ac06974160ada05ae1a7d775a Mon Sep 17 00:00:00 2001 From: Gabriel d`Agosto Date: Mon, 27 Nov 2023 15:16:27 -0300 Subject: [PATCH 1/6] feat: add KaTeX support --- packages/kit-docs/package.json | 2 ++ .../parser/create-markdown-parser.ts | 2 ++ .../markdown-plugin/parser/plugins/index.ts | 1 + .../parser/plugins/katex-plugin.ts | 10 +++++++++ pnpm-lock.yaml | 22 +++++++++++++++++++ 5 files changed, 37 insertions(+) create mode 100644 packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts diff --git a/packages/kit-docs/package.json b/packages/kit-docs/package.json index 7f72562..d52b89f 100644 --- a/packages/kit-docs/package.json +++ b/packages/kit-docs/package.json @@ -82,12 +82,14 @@ "autoprefixer": "^10.4.15", "globby": "^13.2.2", "gray-matter": "^4.0.3", + "katex": "^0.16.9", "lru-cache": "^10.0.1", "magic-string": "^0.30.3", "markdown-it": "^13.0.1", "markdown-it-anchor": "^8.6.7", "markdown-it-container": "^3.0.0", "markdown-it-emoji": "^2.0.2", + "markdown-it-texmath": "^1.0.0", "npm-run-all": "^4.1.5", "picomatch": "^2.3.1", "postcss": "^8.4.29", diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts b/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts index ac1fbf6..39c0bef 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts @@ -12,6 +12,7 @@ import { extractTitlePlugin, hoistTagsPlugin, importCodePlugin, + katexPlugin, linksPlugin, tocPlugin, } from './plugins'; @@ -50,6 +51,7 @@ export async function createMarkdownParser( const parser = MarkdownIt({ html: true }); parser.use(emojiPlugin); + parser.use(katexPlugin); parser.use(anchorPlugin); parser.use(tocPlugin); parser.use(extractHeadersPlugin); diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts index 85b9473..0f7b02e 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts @@ -7,6 +7,7 @@ export * from './extract-headers-plugin'; export * from './extract-title-plugin'; export * from './hoist-tags-plugin'; export * from './import-code-plugin'; +export * from './katex-plugin'; export * from './links-plugin'; export * from './shiki-plugin'; export * from './toc-plugin'; diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts new file mode 100644 index 0000000..9a30248 --- /dev/null +++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts @@ -0,0 +1,10 @@ +import katex from 'katex'; +import type { PluginSimple } from 'markdown-it'; +import rawKatexPlugin from 'markdown-it-texmath'; + +export const katexPlugin: PluginSimple = (parser) => { + return rawKatexPlugin(parser, { + engine: katex, + delimiters: 'dollars', + }); +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de7e5bf..d329479 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -221,6 +221,9 @@ importers: gray-matter: specifier: ^4.0.3 version: 4.0.3 + katex: + specifier: ^0.16.9 + version: 0.16.9 lru-cache: specifier: ^10.0.1 version: 10.0.1 @@ -239,6 +242,9 @@ importers: markdown-it-emoji: specifier: ^2.0.2 version: 2.0.2 + markdown-it-texmath: + specifier: ^1.0.0 + version: 1.0.0 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -1872,6 +1878,11 @@ packages: engines: {node: '>= 6'} dev: true + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + dev: true + /commander@9.5.0: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} @@ -3354,6 +3365,13 @@ packages: engines: {'0': node >= 0.2.0} dev: true + /katex@0.16.9: + resolution: {integrity: sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==} + hasBin: true + dependencies: + commander: 8.3.0 + dev: true + /keyv@4.5.3: resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} dependencies: @@ -3567,6 +3585,10 @@ packages: resolution: {integrity: sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==} dev: true + /markdown-it-texmath@1.0.0: + resolution: {integrity: sha512-4hhkiX8/gus+6e53PLCUmUrsa6ZWGgJW2XCW6O0ASvZUiezIK900ZicinTDtG3kAO2kon7oUA/ReWmpW2FByxg==} + dev: true + /markdown-it@13.0.1: resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} hasBin: true From 64987b49f091eb513d2e7e52905d37bba5669904 Mon Sep 17 00:00:00 2001 From: Gabriel d`Agosto Date: Mon, 27 Nov 2023 15:49:27 -0300 Subject: [PATCH 2/6] docs: demo KaTeX --- .../docs/[...7]testing/[...1]katex/+page.md | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 demo/src/routes/docs/[...7]testing/[...1]katex/+page.md diff --git a/demo/src/routes/docs/[...7]testing/[...1]katex/+page.md b/demo/src/routes/docs/[...7]testing/[...1]katex/+page.md new file mode 100644 index 0000000..35a81d8 --- /dev/null +++ b/demo/src/routes/docs/[...7]testing/[...1]katex/+page.md @@ -0,0 +1,20 @@ +# KaTeX support + +Mathematical expressions can be written inline, such as $a=1$, or as a block, such as the example below: + +$$ +b=2 +$$ + +You can add all sorts of mathematical operations. + +$$ +\frac {a}{b} = \frac {1}{2} +$$ + +$$ +\sum_{i=1}^{5}b*i = 30 +$$ + + +And also inline them $\sum_{i=1}^{5}b*i = 30$, just like that From 45a371b932326c85e1bc95f2e998c8ecd2698b33 Mon Sep 17 00:00:00 2001 From: Gabriel d`Agosto Date: Mon, 27 Nov 2023 17:07:35 -0300 Subject: [PATCH 3/6] fix: remove annotations from math tag, so it's svelte compatible --- .../parser/create-markdown-parser.ts | 2 ++ .../node/markdown-plugin/parser/plugins/index.ts | 1 + .../parser/plugins/remove-annotation-plugin.ts | 16 ++++++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts b/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts index 39c0bef..87d421b 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts @@ -14,6 +14,7 @@ import { importCodePlugin, katexPlugin, linksPlugin, + removeAnnotationPlugin, tocPlugin, } from './plugins'; import type { @@ -63,6 +64,7 @@ export async function createMarkdownParser( parser.use(importCodePlugin); parser.use(await createShikiPlugin(shiki)); parser.use(hoistTagsPlugin); + parser.use(removeAnnotationPlugin); responsiveTablePlugin(parser); diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts index 0f7b02e..de515dd 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/index.ts @@ -9,5 +9,6 @@ export * from './hoist-tags-plugin'; export * from './import-code-plugin'; export * from './katex-plugin'; export * from './links-plugin'; +export * from './remove-annotation-plugin'; export * from './shiki-plugin'; export * from './toc-plugin'; diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts new file mode 100644 index 0000000..9824670 --- /dev/null +++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts @@ -0,0 +1,16 @@ +import { type PluginSimple } from 'markdown-it'; +const annotationRe = //g; + +/** + * Resolves link URLs. + */ +export const removeAnnotationPlugin: PluginSimple = (parser) => { + Object.entries(parser.renderer.rules).forEach(([name, fn]) => { + if (!name.startsWith('math')) return; + if (!fn) return; + + // Fix math rules, to remove annotation blocks afterward + parser.renderer.rules[name] = (tokens, idx, options, env, renderer) => + fn(tokens, idx, options, env, renderer).replace(annotationRe, ''); + }); +}; From 75aad903425ebe75e397400acb8e7aecd16606f3 Mon Sep 17 00:00:00 2001 From: Gabriel d`Agosto Date: Mon, 27 Nov 2023 17:35:06 -0300 Subject: [PATCH 4/6] refactor: dont remove annotations, use @html --- .../plugins/remove-annotation-plugin.ts | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts index 9824670..009a279 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts @@ -1,5 +1,5 @@ import { type PluginSimple } from 'markdown-it'; -const annotationRe = //g; +const annotationRe = /()([\s\S]+?)(<\/annotation>)/g; /** * Resolves link URLs. @@ -10,7 +10,22 @@ export const removeAnnotationPlugin: PluginSimple = (parser) => { if (!fn) return; // Fix math rules, to remove annotation blocks afterward - parser.renderer.rules[name] = (tokens, idx, options, env, renderer) => - fn(tokens, idx, options, env, renderer).replace(annotationRe, ''); + parser.renderer.rules[name] = (tokens, idx, options, env, renderer) => { + let result = fn(tokens, idx, options, env, renderer); + + [...result.matchAll(annotationRe)].forEach((match) => { + /* Given an annotation rule with a backslash or curly braces, modify it using svelte's @html + to avoid svelte attempting to parse variables, or processing backslashes + + Input: \rule {braces} + Output: {@html `\\rule {braces}`} */ + result = result.replace( + match[0], + `${match[1]}{@html \`${match[2].replace('\\', '\\\\')}\`}${match[3]}`, + ); + }); + + return result; + }; }); }; From a07446db2cbaf62653413f54f24c73a54c6fcf59 Mon Sep 17 00:00:00 2001 From: Gabriel d`Agosto Date: Mon, 27 Nov 2023 17:35:51 -0300 Subject: [PATCH 5/6] docs: add katex css to demo --- demo/src/app.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/demo/src/app.html b/demo/src/app.html index 0e5ac56..52f1a61 100644 --- a/demo/src/app.html +++ b/demo/src/app.html @@ -5,6 +5,12 @@ + From 1ce10071ecb1b4a61c897709bfa55d414a3333fa Mon Sep 17 00:00:00 2001 From: Gabriel d`Agosto Date: Tue, 28 Nov 2023 14:30:30 -0300 Subject: [PATCH 6/6] refactor: make math dependencies optional --- packages/kit-docs/package.json | 14 ++++++++++++-- .../parser/create-markdown-parser.ts | 17 +++++++++++++++-- .../parser/plugins/katex-plugin.ts | 10 ++++------ pnpm-lock.yaml | 18 +++++++++--------- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/packages/kit-docs/package.json b/packages/kit-docs/package.json index d52b89f..26abd9a 100644 --- a/packages/kit-docs/package.json +++ b/packages/kit-docs/package.json @@ -82,14 +82,12 @@ "autoprefixer": "^10.4.15", "globby": "^13.2.2", "gray-matter": "^4.0.3", - "katex": "^0.16.9", "lru-cache": "^10.0.1", "magic-string": "^0.30.3", "markdown-it": "^13.0.1", "markdown-it-anchor": "^8.6.7", "markdown-it-container": "^3.0.0", "markdown-it-emoji": "^2.0.2", - "markdown-it-texmath": "^1.0.0", "npm-run-all": "^4.1.5", "picomatch": "^2.3.1", "postcss": "^8.4.29", @@ -107,6 +105,18 @@ "unplugin-icons": "^0.17.0", "vite": "^4.4.9" }, + "peerDependencies": { + "markdown-it-texmath": "^1.0.0", + "katex": "^0.16.9" + }, + "peerDependenciesMeta": { + "markdown-it-texmath": { + "optional": true + }, + "katex": { + "optional": true + } + }, "publishConfig": { "access": "public" }, diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts b/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts index 87d421b..39e8a65 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/create-markdown-parser.ts @@ -51,8 +51,22 @@ export async function createMarkdownParser( const parser = MarkdownIt({ html: true }); + // Optional math expressions plugins + try { + const markdownItTexmath = await import('markdown-it-texmath'); + const katex = await import('katex'); + + try { + parser.use(katexPlugin, { plugin: markdownItTexmath, katex }); + parser.use(removeAnnotationPlugin); + } catch (error) { + console.error(error); + } + } catch { + console.log('no KaTeX support, failed to import'); + } + parser.use(emojiPlugin); - parser.use(katexPlugin); parser.use(anchorPlugin); parser.use(tocPlugin); parser.use(extractHeadersPlugin); @@ -64,7 +78,6 @@ export async function createMarkdownParser( parser.use(importCodePlugin); parser.use(await createShikiPlugin(shiki)); parser.use(hoistTagsPlugin); - parser.use(removeAnnotationPlugin); responsiveTablePlugin(parser); diff --git a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts index 9a30248..51a1e82 100644 --- a/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts +++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts @@ -1,10 +1,8 @@ -import katex from 'katex'; -import type { PluginSimple } from 'markdown-it'; -import rawKatexPlugin from 'markdown-it-texmath'; +import type { PluginWithOptions } from 'markdown-it'; -export const katexPlugin: PluginSimple = (parser) => { - return rawKatexPlugin(parser, { - engine: katex, +export const katexPlugin: PluginWithOptions = (parser, { plugin, katex }) => { + return plugin.default(parser, { + engine: katex.default, delimiters: 'dollars', }); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d329479..2578260 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -160,9 +160,15 @@ importers: clsx: specifier: ^2.0.0 version: 2.0.0 + katex: + specifier: ^0.16.9 + version: 0.16.9 kleur: specifier: ^4.1.5 version: 4.1.5 + markdown-it-texmath: + specifier: ^1.0.0 + version: 1.0.0 shiki: specifier: ^0.14.4 version: 0.14.4 @@ -221,9 +227,6 @@ importers: gray-matter: specifier: ^4.0.3 version: 4.0.3 - katex: - specifier: ^0.16.9 - version: 0.16.9 lru-cache: specifier: ^10.0.1 version: 10.0.1 @@ -242,9 +245,6 @@ importers: markdown-it-emoji: specifier: ^2.0.2 version: 2.0.2 - markdown-it-texmath: - specifier: ^1.0.0 - version: 1.0.0 npm-run-all: specifier: ^4.1.5 version: 4.1.5 @@ -1881,7 +1881,7 @@ packages: /commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} - dev: true + dev: false /commander@9.5.0: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} @@ -3370,7 +3370,7 @@ packages: hasBin: true dependencies: commander: 8.3.0 - dev: true + dev: false /keyv@4.5.3: resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} @@ -3587,7 +3587,7 @@ packages: /markdown-it-texmath@1.0.0: resolution: {integrity: sha512-4hhkiX8/gus+6e53PLCUmUrsa6ZWGgJW2XCW6O0ASvZUiezIK900ZicinTDtG3kAO2kon7oUA/ReWmpW2FByxg==} - dev: true + dev: false /markdown-it@13.0.1: resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==}