This commit is contained in:
parent
21b857b457
commit
8d391a2e5e
42 changed files with 4590 additions and 40 deletions
|
|
@ -9,9 +9,9 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import remarkCodeFenceLanguages from "../../src/remark-code-fence-languages.mjs";
|
import remarkCodeFenceLanguages from "./src/remark/code-fence-languages.mjs";
|
||||||
import remarkInlineFootnotes from "../../src/remark-inline-footnotes.mjs";
|
import remarkInlineFootnotes from "./src/remark/inline-footnotes.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [
|
const remarkPlugins = [
|
||||||
|
|
|
||||||
232
sites/art/package-lock.json
generated
232
sites/art/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/art/src/remark/callouts.mjs
Normal file
101
sites/art/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/art/src/remark/code-fence-languages.mjs
Normal file
29
sites/art/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/art/src/remark/inline-footnotes.mjs
Normal file
289
sites/art/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
|
|
@ -8,7 +8,7 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [remarkMath, remarkCallouts];
|
const remarkPlugins = [remarkMath, remarkCallouts];
|
||||||
|
|
|
||||||
232
sites/poetry/package-lock.json
generated
232
sites/poetry/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/poetry/src/remark/callouts.mjs
Normal file
101
sites/poetry/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/poetry/src/remark/code-fence-languages.mjs
Normal file
29
sites/poetry/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/poetry/src/remark/inline-footnotes.mjs
Normal file
289
sites/poetry/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
|
|
@ -9,9 +9,9 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import remarkCodeFenceLanguages from "../../src/remark-code-fence-languages.mjs";
|
import remarkCodeFenceLanguages from "./src/remark/code-fence-languages.mjs";
|
||||||
import remarkInlineFootnotes from "../../src/remark-inline-footnotes.mjs";
|
import remarkInlineFootnotes from "./src/remark/inline-footnotes.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [
|
const remarkPlugins = [
|
||||||
|
|
|
||||||
232
sites/puzzles/package-lock.json
generated
232
sites/puzzles/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/puzzles/src/remark/callouts.mjs
Normal file
101
sites/puzzles/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/puzzles/src/remark/code-fence-languages.mjs
Normal file
29
sites/puzzles/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/puzzles/src/remark/inline-footnotes.mjs
Normal file
289
sites/puzzles/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
|
|
@ -9,9 +9,9 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import remarkCodeFenceLanguages from "../../src/remark-code-fence-languages.mjs";
|
import remarkCodeFenceLanguages from "./src/remark/code-fence-languages.mjs";
|
||||||
import remarkInlineFootnotes from "../../src/remark-inline-footnotes.mjs";
|
import remarkInlineFootnotes from "./src/remark/inline-footnotes.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [
|
const remarkPlugins = [
|
||||||
|
|
|
||||||
232
sites/reflections/package-lock.json
generated
232
sites/reflections/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/reflections/src/remark/callouts.mjs
Normal file
101
sites/reflections/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/reflections/src/remark/code-fence-languages.mjs
Normal file
29
sites/reflections/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/reflections/src/remark/inline-footnotes.mjs
Normal file
289
sites/reflections/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
|
|
@ -9,9 +9,9 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import remarkCodeFenceLanguages from "../../src/remark-code-fence-languages.mjs";
|
import remarkCodeFenceLanguages from "./src/remark/code-fence-languages.mjs";
|
||||||
import remarkInlineFootnotes from "../../src/remark-inline-footnotes.mjs";
|
import remarkInlineFootnotes from "./src/remark/inline-footnotes.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [
|
const remarkPlugins = [
|
||||||
|
|
|
||||||
232
sites/research/package-lock.json
generated
232
sites/research/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/research/src/remark/callouts.mjs
Normal file
101
sites/research/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/research/src/remark/code-fence-languages.mjs
Normal file
29
sites/research/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/research/src/remark/inline-footnotes.mjs
Normal file
289
sites/research/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
|
|
@ -9,9 +9,9 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import remarkCodeFenceLanguages from "../../src/remark-code-fence-languages.mjs";
|
import remarkCodeFenceLanguages from "./src/remark/code-fence-languages.mjs";
|
||||||
import remarkInlineFootnotes from "../../src/remark-inline-footnotes.mjs";
|
import remarkInlineFootnotes from "./src/remark/inline-footnotes.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [
|
const remarkPlugins = [
|
||||||
|
|
|
||||||
232
sites/reviews/package-lock.json
generated
232
sites/reviews/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/reviews/src/remark/callouts.mjs
Normal file
101
sites/reviews/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/reviews/src/remark/code-fence-languages.mjs
Normal file
29
sites/reviews/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/reviews/src/remark/inline-footnotes.mjs
Normal file
289
sites/reviews/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
|
|
@ -9,9 +9,9 @@ import sitemap from "@astrojs/sitemap";
|
||||||
import react from "@astrojs/react";
|
import react from "@astrojs/react";
|
||||||
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
// @ts-ignore - TailwindCSS v4 Vite plugin has type compatibility issues with Astro
|
||||||
import tailwindcss from "@tailwindcss/vite";
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
import remarkCallouts from "../../src/remark-callouts.mjs";
|
import remarkCallouts from "./src/remark/callouts.mjs";
|
||||||
import remarkCodeFenceLanguages from "../../src/remark-code-fence-languages.mjs";
|
import remarkCodeFenceLanguages from "./src/remark/code-fence-languages.mjs";
|
||||||
import remarkInlineFootnotes from "../../src/remark-inline-footnotes.mjs";
|
import remarkInlineFootnotes from "./src/remark/inline-footnotes.mjs";
|
||||||
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
import { ACTIVE_BLOG_SITE } from "./src/blog-sites.js";
|
||||||
|
|
||||||
const remarkPlugins = [
|
const remarkPlugins = [
|
||||||
|
|
|
||||||
232
sites/vibes/package-lock.json
generated
232
sites/vibes/package-lock.json
generated
|
|
@ -36,12 +36,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
@ -2826,6 +2831,60 @@
|
||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.0.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.4.3",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "0.2.11",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.4.3",
|
||||||
|
"@emnapi/runtime": "^1.4.3",
|
||||||
|
"@tybys/wasm-util": "^0.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.0",
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.11",
|
"version": "4.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz",
|
||||||
|
|
@ -2970,6 +3029,12 @@
|
||||||
"@types/unist": "*"
|
"@types/unist": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/katex": {
|
||||||
|
"version": "0.16.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz",
|
||||||
|
"integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/mdast": {
|
"node_modules/@types/mdast": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
|
||||||
|
|
@ -3979,6 +4044,15 @@
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/commander": {
|
||||||
|
"version": "8.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||||
|
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/common-ancestor-path": {
|
"node_modules/common-ancestor-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz",
|
||||||
|
|
@ -4691,6 +4765,21 @@
|
||||||
"uncrypto": "^0.1.3"
|
"uncrypto": "^0.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-dom": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hastscript": "^9.0.0",
|
||||||
|
"web-namespaces": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-html": {
|
"node_modules/hast-util-from-html": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz",
|
||||||
|
|
@ -4709,6 +4798,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hast-util-from-html-isomorphic": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hast-util-from-html-isomorphic/-/hast-util-from-html-isomorphic-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"hast-util-from-dom": "^5.0.0",
|
||||||
|
"hast-util-from-html": "^2.0.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hast-util-from-parse5": {
|
"node_modules/hast-util-from-parse5": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz",
|
||||||
|
|
@ -5193,6 +5298,22 @@
|
||||||
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/katex": {
|
||||||
|
"version": "0.17.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.17.0.tgz",
|
||||||
|
"integrity": "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/kleur": {
|
"node_modules/kleur": {
|
||||||
"version": "4.1.5",
|
"version": "4.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
|
||||||
|
|
@ -5556,9 +5677,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mdast-util-from-markdown": {
|
"node_modules/mdast-util-from-markdown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
|
||||||
"integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==",
|
"integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/mdast": "^4.0.0",
|
"@types/mdast": "^4.0.0",
|
||||||
|
|
@ -5680,6 +5801,25 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/mdast-util-math": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"longest-streak": "^3.0.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.0",
|
||||||
|
"mdast-util-to-markdown": "^2.1.0",
|
||||||
|
"unist-util-remove-position": "^5.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mdast-util-mdx": {
|
"node_modules/mdast-util-mdx": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz",
|
||||||
|
|
@ -6031,6 +6171,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromark-extension-math": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"devlop": "^1.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"micromark-factory-space": "^2.0.0",
|
||||||
|
"micromark-util-character": "^2.0.0",
|
||||||
|
"micromark-util-symbol": "^2.0.0",
|
||||||
|
"micromark-util-types": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/micromark-extension-math/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/micromark-extension-mdx-expression": {
|
"node_modules/micromark-extension-mdx-expression": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz",
|
||||||
|
|
@ -7291,6 +7466,41 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rehype-katex": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/hast": "^3.0.0",
|
||||||
|
"@types/katex": "^0.16.0",
|
||||||
|
"hast-util-from-html-isomorphic": "^2.0.0",
|
||||||
|
"hast-util-to-text": "^4.0.0",
|
||||||
|
"katex": "^0.16.0",
|
||||||
|
"unist-util-visit-parents": "^6.0.0",
|
||||||
|
"vfile": "^6.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rehype-katex/node_modules/katex": {
|
||||||
|
"version": "0.16.47",
|
||||||
|
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz",
|
||||||
|
"integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==",
|
||||||
|
"funding": [
|
||||||
|
"https://opencollective.com/katex",
|
||||||
|
"https://github.com/sponsors/katex"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "^8.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"katex": "cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/rehype-parse": {
|
"node_modules/rehype-parse": {
|
||||||
"version": "9.0.1",
|
"version": "9.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz",
|
||||||
|
|
@ -7369,6 +7579,22 @@
|
||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/remark-math": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/mdast": "^4.0.0",
|
||||||
|
"mdast-util-math": "^3.0.0",
|
||||||
|
"micromark-extension-math": "^3.0.0",
|
||||||
|
"unified": "^11.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/remark-mdx": {
|
"node_modules/remark-mdx": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz",
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,17 @@
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"embla-carousel-autoplay": "^8.5.2",
|
"embla-carousel-autoplay": "^8.5.2",
|
||||||
"embla-carousel-react": "^8.5.2",
|
"embla-carousel-react": "^8.5.2",
|
||||||
|
"katex": "^0.17.0",
|
||||||
"lucide-react": "^0.479.0",
|
"lucide-react": "^0.479.0",
|
||||||
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-fast-marquee": "^1.6.5",
|
"react-fast-marquee": "^1.6.5",
|
||||||
"react-hook-form": "^7.54.2",
|
"react-hook-form": "^7.54.2",
|
||||||
"react-icons": "^5.4.0",
|
"react-icons": "^5.4.0",
|
||||||
|
"rehype-katex": "^7.0.1",
|
||||||
|
"remark-gfm": "^4.0.1",
|
||||||
|
"remark-math": "^6.0.0",
|
||||||
"tailwind-merge": "^3.0.2",
|
"tailwind-merge": "^3.0.2",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
|
|
|
||||||
101
sites/vibes/src/remark/callouts.mjs
Normal file
101
sites/vibes/src/remark/callouts.mjs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
const CALLOUT_LABELS = new Map([
|
||||||
|
["aside", "Aside"],
|
||||||
|
["caution", "Caution"],
|
||||||
|
["note", "Note"],
|
||||||
|
["tip", "Tip"],
|
||||||
|
["warning", "Warning"],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function textFromInline(node) {
|
||||||
|
if (!node) return "";
|
||||||
|
if (typeof node.value === "string") return node.value;
|
||||||
|
if (!Array.isArray(node.children)) return "";
|
||||||
|
return node.children.map(textFromInline).join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeLabel(value) {
|
||||||
|
return value
|
||||||
|
.trim()
|
||||||
|
.replace(/^["“”]+|["“”]+$/g, "")
|
||||||
|
.replace(/:$/, "")
|
||||||
|
.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function paragraphCalloutLabel(paragraph) {
|
||||||
|
if (paragraph?.type !== "paragraph") return null;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
const match = first.value.match(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i);
|
||||||
|
if (match) {
|
||||||
|
return CALLOUT_LABELS.get(normalizeLabel(match[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first?.type !== "strong") return null;
|
||||||
|
|
||||||
|
const label = CALLOUT_LABELS.get(normalizeLabel(textFromInline(first)));
|
||||||
|
if (!label) return null;
|
||||||
|
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeLeadingLabel(paragraph, label) {
|
||||||
|
if (paragraph?.type !== "paragraph") return;
|
||||||
|
|
||||||
|
const first = paragraph.children?.[0];
|
||||||
|
if (first?.type === "text") {
|
||||||
|
first.value = first.value.replace(/^\s*\[!(aside|caution|note|tip|warning)\]\s*/i, "");
|
||||||
|
if (!first.value) paragraph.children.shift();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstText = normalizeLabel(textFromInline(first));
|
||||||
|
if (!first || first.type !== "strong" || firstText !== label.toLowerCase()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
paragraph.children.shift();
|
||||||
|
|
||||||
|
const next = paragraph.children[0];
|
||||||
|
if (next?.type === "text") {
|
||||||
|
next.value = next.value.replace(/^:\s*/, "").replace(/^\s+/, "");
|
||||||
|
if (!next.value) paragraph.children.shift();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformBlockquote(node) {
|
||||||
|
if (node.type !== "blockquote") return;
|
||||||
|
|
||||||
|
const first = node.children?.[0];
|
||||||
|
const label = paragraphCalloutLabel(first);
|
||||||
|
if (!label) return;
|
||||||
|
|
||||||
|
removeLeadingLabel(first, label);
|
||||||
|
if (first.children?.length === 0) {
|
||||||
|
node.children.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
node.data = {
|
||||||
|
hName: "aside",
|
||||||
|
hProperties: {
|
||||||
|
className: ["callout", `callout-${label.toLowerCase()}`],
|
||||||
|
dataCalloutLabel: label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function visit(node) {
|
||||||
|
transformBlockquote(node);
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function remarkCallouts() {
|
||||||
|
return function transformer(tree) {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
}
|
||||||
29
sites/vibes/src/remark/code-fence-languages.mjs
Normal file
29
sites/vibes/src/remark/code-fence-languages.mjs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
const LANGUAGE_ALIASES = new Map([["ojs", "js"]]);
|
||||||
|
|
||||||
|
const normalizeLanguage = (language) => {
|
||||||
|
if (!language) return language;
|
||||||
|
|
||||||
|
const match = language.match(/^\{(.+)\}$/);
|
||||||
|
if (!match) return language;
|
||||||
|
|
||||||
|
const normalized = match[1].trim().toLowerCase();
|
||||||
|
return LANGUAGE_ALIASES.get(normalized) ?? normalized;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visit = (node) => {
|
||||||
|
if (node.type === "code") {
|
||||||
|
node.lang = normalizeLanguage(node.lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(node.children)) return;
|
||||||
|
|
||||||
|
for (const child of node.children) {
|
||||||
|
visit(child);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkCodeFenceLanguages = () => (tree) => {
|
||||||
|
visit(tree);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkCodeFenceLanguages;
|
||||||
289
sites/vibes/src/remark/inline-footnotes.mjs
Normal file
289
sites/vibes/src/remark/inline-footnotes.mjs
Normal file
|
|
@ -0,0 +1,289 @@
|
||||||
|
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||||
|
|
||||||
|
const INLINE_FOOTNOTE_PREFIX = "inline-footnote";
|
||||||
|
|
||||||
|
const findInlineFootnote = (value, fromIndex = 0) => {
|
||||||
|
const start = value.indexOf("^[", fromIndex);
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let depth = 1;
|
||||||
|
|
||||||
|
for (let index = start + 2; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "[") {
|
||||||
|
depth += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
depth -= 1;
|
||||||
|
|
||||||
|
if (depth === 0) {
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: index + 1,
|
||||||
|
value: value.slice(start + 2, index).trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteChildren = (value) => {
|
||||||
|
const tree = fromMarkdown(value);
|
||||||
|
|
||||||
|
if (tree.children.length > 0) {
|
||||||
|
return tree.children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
type: "paragraph",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
const createFootnoteParagraph = (children) => ({
|
||||||
|
type: "paragraph",
|
||||||
|
children:
|
||||||
|
children.length > 0
|
||||||
|
? children
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
value: "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinition = (identifier, label, value) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: createFootnoteChildren(value),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteDefinitionFromChildren = (identifier, label, children) => ({
|
||||||
|
type: "footnoteDefinition",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
children: [createFootnoteParagraph(children)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const createFootnoteReference = (context) => {
|
||||||
|
context.count += 1;
|
||||||
|
|
||||||
|
const label = String(context.count);
|
||||||
|
const identifier = `${INLINE_FOOTNOTE_PREFIX}-${label}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
node: {
|
||||||
|
type: "footnoteReference",
|
||||||
|
identifier,
|
||||||
|
label,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const findClosingBracket = (value) => {
|
||||||
|
for (let index = 0; index < value.length; index += 1) {
|
||||||
|
const character = value[index];
|
||||||
|
|
||||||
|
if (character === "\\" && index + 1 < value.length) {
|
||||||
|
index += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (character === "]") {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneNode = (node) => JSON.parse(JSON.stringify(node));
|
||||||
|
|
||||||
|
const splitTextNode = (node, context) => {
|
||||||
|
const replacements = [];
|
||||||
|
let cursor = 0;
|
||||||
|
let match = findInlineFootnote(node.value, cursor);
|
||||||
|
|
||||||
|
while (match) {
|
||||||
|
if (match.start > cursor) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor, match.start),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match.value) {
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinition(reference.identifier, reference.label, match.value),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(match.start, match.end),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cursor = match.end;
|
||||||
|
match = findInlineFootnote(node.value, cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < node.value.length) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: node.value.slice(cursor),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return replacements;
|
||||||
|
};
|
||||||
|
|
||||||
|
const splitAcrossInlineNodes = (children, startIndex, context) => {
|
||||||
|
const startNode = children[startIndex];
|
||||||
|
const start = startNode.value.indexOf("^[");
|
||||||
|
|
||||||
|
if (start === -1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findInlineFootnote(startNode.value, start)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const footnoteChildren = [];
|
||||||
|
const replacements = [];
|
||||||
|
const before = startNode.value.slice(0, start);
|
||||||
|
const initialText = startNode.value.slice(start + 2);
|
||||||
|
|
||||||
|
if (before) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: before,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: initialText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = startIndex + 1; index < children.length; index += 1) {
|
||||||
|
const child = children[index];
|
||||||
|
|
||||||
|
if (child.type === "text") {
|
||||||
|
const closingIndex = findClosingBracket(child.value);
|
||||||
|
|
||||||
|
if (closingIndex !== -1) {
|
||||||
|
const footnoteText = child.value.slice(0, closingIndex);
|
||||||
|
const after = child.value.slice(closingIndex + 1);
|
||||||
|
|
||||||
|
if (footnoteText) {
|
||||||
|
footnoteChildren.push({
|
||||||
|
type: "text",
|
||||||
|
value: footnoteText,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const reference = createFootnoteReference(context);
|
||||||
|
replacements.push(reference.node);
|
||||||
|
|
||||||
|
if (after) {
|
||||||
|
replacements.push({
|
||||||
|
type: "text",
|
||||||
|
value: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
context.definitions.push(
|
||||||
|
createFootnoteDefinitionFromChildren(
|
||||||
|
reference.identifier,
|
||||||
|
reference.label,
|
||||||
|
footnoteChildren,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
consumed: index - startIndex + 1,
|
||||||
|
replacements,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
footnoteChildren.push(cloneNode(child));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visitChildren = (node, context) => {
|
||||||
|
if (!Array.isArray(node.children)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let index = 0; index < node.children.length; index += 1) {
|
||||||
|
const child = node.children[index];
|
||||||
|
|
||||||
|
if (child.type === "text" && child.value.includes("^[")) {
|
||||||
|
const acrossNodes = splitAcrossInlineNodes(node.children, index, context);
|
||||||
|
|
||||||
|
if (acrossNodes) {
|
||||||
|
node.children.splice(index, acrossNodes.consumed, ...acrossNodes.replacements);
|
||||||
|
index += acrossNodes.replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = splitTextNode(child, context);
|
||||||
|
node.children.splice(index, 1, ...replacements);
|
||||||
|
index += replacements.length - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visitChildren(child, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const remarkInlineFootnotes = () => (tree) => {
|
||||||
|
const context = {
|
||||||
|
count: 0,
|
||||||
|
definitions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
visitChildren(tree, context);
|
||||||
|
|
||||||
|
if (context.definitions.length > 0) {
|
||||||
|
tree.children.push(...context.definitions);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default remarkInlineFootnotes;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue