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 @@
+
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
diff --git a/packages/kit-docs/package.json b/packages/kit-docs/package.json
index 7f72562..26abd9a 100644
--- a/packages/kit-docs/package.json
+++ b/packages/kit-docs/package.json
@@ -105,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 ac1fbf6..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
@@ -12,7 +12,9 @@ import {
extractTitlePlugin,
hoistTagsPlugin,
importCodePlugin,
+ katexPlugin,
linksPlugin,
+ removeAnnotationPlugin,
tocPlugin,
} from './plugins';
import type {
@@ -49,6 +51,21 @@ 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(anchorPlugin);
parser.use(tocPlugin);
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..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
@@ -7,6 +7,8 @@ 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 './remove-annotation-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..51a1e82
--- /dev/null
+++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/katex-plugin.ts
@@ -0,0 +1,8 @@
+import type { PluginWithOptions } from 'markdown-it';
+
+export const katexPlugin: PluginWithOptions = (parser, { plugin, katex }) => {
+ return plugin.default(parser, {
+ engine: katex.default,
+ delimiters: 'dollars',
+ });
+};
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..009a279
--- /dev/null
+++ b/packages/kit-docs/src/node/markdown-plugin/parser/plugins/remove-annotation-plugin.ts
@@ -0,0 +1,31 @@
+import { type PluginSimple } from 'markdown-it';
+const annotationRe = /()([\s\S]+?)(<\/annotation>)/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) => {
+ 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;
+ };
+ });
+};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index de7e5bf..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
@@ -1872,6 +1878,11 @@ packages:
engines: {node: '>= 6'}
dev: true
+ /commander@8.3.0:
+ resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
+ engines: {node: '>= 12'}
+ dev: false
+
/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: false
+
/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: false
+
/markdown-it@13.0.1:
resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==}
hasBin: true