diff --git a/.vscode/settings.json b/.vscode/settings.json index 43a5317..5627f3c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,8 @@ "cSpell.words": [ "bspwm", "cairographics", + "callout", + "callouts", "classnet", "createreactapp", "deno", @@ -32,7 +34,6 @@ "gnubash", "godotengine", "heroicon", - "hljs", "hongik", "hoofd", "inqling", @@ -41,7 +42,10 @@ "kunukn", "Librewolf", "linaria", + "mhchem", + "microflash", "nodedotjs", + "noopener", "noto", "planetscale", "pnpm", @@ -51,7 +55,9 @@ "pompup", "precompress", "rainmeter", + "rehype", "statcounter", + "supersub", "sxhkd", "tailwindcss", "tauri", diff --git a/apps/blog/src/main.tsx b/apps/blog/src/main.tsx index 533a692..34e42f7 100644 --- a/apps/blog/src/main.tsx +++ b/apps/blog/src/main.tsx @@ -6,8 +6,10 @@ import "./index.css" import "./styles/anchor.scss" import "./styles/blockQuote.scss" import "./styles/button.scss" +import "./styles/callout.scss" import "./styles/checkbox.scss" import "./styles/code.scss" +import "./styles/colorChip.scss" import "./styles/global.scss" import "./styles/heading.scss" import "./styles/hr.scss" diff --git a/apps/blog/src/styles/anchor.scss b/apps/blog/src/styles/anchor.scss index 7434adb..4b539c7 100644 --- a/apps/blog/src/styles/anchor.scss +++ b/apps/blog/src/styles/anchor.scss @@ -3,8 +3,15 @@ a { } /* The "#" thingy used beside headers */ -a.header-anchor { - @apply inline-block text-light-anchor-header dark:text-dark-anchor-header; +h1, +h2, +h3, +h4, +h5, +h6 { + a { + @apply mr-2 inline-block text-light-anchor-header dark:text-dark-anchor-header; + } } /* footnote anchors */ diff --git a/apps/blog/src/styles/callout.scss b/apps/blog/src/styles/callout.scss new file mode 100644 index 0000000..d2c052b --- /dev/null +++ b/apps/blog/src/styles/callout.scss @@ -0,0 +1,83 @@ +/* https://github.com/Microflash/remark-callout-directives/blob/e77daa802994094d40d6c504d5f9ed94f6c217fb/themes/microflash.css */ + +.callout { + --callout-color: hsl(207, 14%, 62%); + --callout-background: ; + --callout-border: 1px solid hsl(205, 15%, 33%); + --callout-radius: 12px; + --callout-padding: 2ch; + border: var(--callout-border); + border-radius: var(--callout-radius); + background: var(--callout-background); + @apply my-8; +} + +.callout code, +.callout pre { + color: hsl(0, 0%, 90%); + background-color: hsl(0, 0%, 100%, 0.1); +} + +.callout-content { + padding: var(--callout-padding); +} + +.callout-content:first-child, +.callout-content:only-child { + margin-block-start: 0; +} + +.callout-content:last-child, +.callout-content:only-child { + margin-block-end: 0; +} + +.callout-indicator { + display: flex; + align-items: center; + border-block-end: var(--callout-border); + padding: calc(var(--callout-padding) / 2); +} + +.callout-hint { + margin-inline-end: calc(var(--callout-padding) / 4); + color: var(--callout-color); +} + +.callout-title { + margin-inline-start: calc(var(--callout-padding) / 4); + font-size: 0.9em; + font-weight: bold; + color: var(--callout-color); + letter-spacing: 0.04em; +} + +.callout-note { + --callout-background: hsl(208, 20%, 13%); + --callout-color: hsl(207, 14%, 62%); + --callout-border: 1px solid hsl(206, 15%, 33%, 0.5); +} + +.callout-commend { + --callout-background: hsl(152, 100%, 7%); + --callout-color: hsl(153, 32%, 50%); + --callout-border: 1px solid hsl(159, 100%, 19%, 0.5); +} + +.callout-warn { + --callout-background: hsl(26, 100%, 10%); + --callout-color: hsl(32, 93%, 41%); + --callout-border: 1px solid hsl(31, 100%, 26%, 0.5); +} + +.callout-deter { + --callout-background: hsl(358, 100%, 10%); + --callout-color: hsl(2, 82%, 62%); + --callout-border: 1px solid hsl(357, 76%, 37%, 0.4); +} + +.callout-assert { + --callout-background: hsl(200, 100%, 10%); + --callout-color: hsl(200, 82%, 62%); + --callout-border: 1px solid hsl(199, 76%, 37%, 0.4); +} diff --git a/apps/blog/src/styles/colorChip.scss b/apps/blog/src/styles/colorChip.scss new file mode 100644 index 0000000..47149fa --- /dev/null +++ b/apps/blog/src/styles/colorChip.scss @@ -0,0 +1,8 @@ +.gfm-color-chip { + margin-left: 0.125rem; + display: inline-block; + height: 0.625rem; + width: 0.625rem; + border-radius: 9999px; + border: 1px solid gray; +} diff --git a/apps/blog/src/styles/img.scss b/apps/blog/src/styles/img.scss index 1022480..ca24c00 100644 --- a/apps/blog/src/styles/img.scss +++ b/apps/blog/src/styles/img.scss @@ -5,3 +5,11 @@ img { table img { max-width: fit-content; } + +figure { + @apply my-4 text-center italic text-light-text-gray dark:text-dark-text-gray; + + img { + @apply mx-auto; + } +} diff --git a/apps/blog/src/styles/mark.scss b/apps/blog/src/styles/mark.scss index 453b154..859bd62 100644 --- a/apps/blog/src/styles/mark.scss +++ b/apps/blog/src/styles/mark.scss @@ -1,3 +1,87 @@ mark { - @apply bg-light-mark-bg text-light-mark-text dark:bg-dark-mark-bg dark:text-dark-mark-text; + @apply text-light-mark-text dark:text-dark-mark-text; +} + +/* same as yellow */ +.flexible-marker-default { + @apply bg-light-mark-bg dark:bg-dark-mark-bg; +} + +.flexible-marker-amber { + @apply bg-amber-400 bg-opacity-100 dark:bg-amber-500 dark:bg-opacity-50; +} + +.flexible-marker-blue { + @apply bg-blue-400 bg-opacity-70 dark:bg-blue-500 dark:bg-opacity-50; +} + +.flexible-marker-cyan { + @apply bg-cyan-200 dark:bg-cyan-500 dark:bg-opacity-50; +} + +.flexible-marker-brown { + @apply bg-yellow-800 bg-opacity-70 dark:bg-opacity-80; +} + +/* same as magenta */ +.flexible-marker-fuchsia { + @apply bg-fuchsia-600 bg-opacity-70 dark:bg-fuchsia-400 dark:bg-opacity-50; +} + +.flexible-marker-green { + @apply bg-green-600 bg-opacity-70 dark:bg-green-400 dark:bg-opacity-50; +} + +.flexible-marker-hotpink { + @apply bg-pink-400 bg-opacity-70; +} + +.flexible-marker-lime { + @apply bg-lime-300 bg-opacity-90 dark:bg-lime-400 dark:bg-opacity-70; +} + +/* same as fuchsia */ +.flexible-marker-magenta { + @apply bg-fuchsia-600 bg-opacity-70 dark:bg-fuchsia-400 dark:bg-opacity-50; +} + +.flexible-marker-navyblue { + @apply bg-blue-700 bg-opacity-70 dark:bg-blue-600 dark:bg-opacity-70; +} + +.flexible-marker-orange { + @apply bg-orange-600 bg-opacity-80 dark:bg-orange-500 dark:bg-opacity-70; +} + +.flexible-marker-purple { + @apply bg-purple-700 bg-opacity-70 dark:bg-purple-500 dark:bg-opacity-70; +} + +.flexible-marker-pink { + @apply bg-pink-500 bg-opacity-80 dark:bg-pink-400 dark:bg-opacity-70; +} + +.flexible-marker-red { + @apply bg-red-600 bg-opacity-80 dark:bg-red-500 dark:bg-opacity-70; +} + +.flexible-marker-silver { + @apply bg-gray-500 bg-opacity-60 dark:bg-slate-400 dark:bg-opacity-70; +} + +.flexible-marker-teal { + @apply bg-teal-700 bg-opacity-50 dark:bg-teal-600 dark:bg-opacity-70; +} + +.flexible-marker-violet { + @apply bg-violet-600 bg-opacity-60 dark:bg-violet-600 dark:bg-opacity-70; +} + +.flexible-marker-gray { + @apply bg-neutral-600 bg-opacity-60 dark:bg-neutral-500 dark:bg-opacity-60; +} + +/* same as default */ +.flexible-marker-yellow { + @apply bg-light-mark-bg dark:bg-dark-mark-bg; } diff --git a/apps/portfolio/package.json b/apps/portfolio/package.json index 03c1ab3..1760add 100644 --- a/apps/portfolio/package.json +++ b/apps/portfolio/package.json @@ -22,6 +22,7 @@ "wouter": "^2.11.0" }, "devDependencies": { + "@developomp-site/blog": "workspace:*", "@developomp-site/content": "workspace:*", "@developomp-site/prettier-config": "workspace:*", "@developomp-site/tailwind-config": "workspace:*", diff --git a/apps/portfolio/src/index.scss b/apps/portfolio/src/index.scss index 14e2b50..20df570 100644 --- a/apps/portfolio/src/index.scss +++ b/apps/portfolio/src/index.scss @@ -18,27 +18,6 @@ body { @apply m-0 flex h-full w-full scroll-m-16 flex-col items-center p-0; } -a { - @apply text-anchor visited:text-anchor hover:text-anchor-accent active:text-anchor-accent; -} - -img { - @apply w-fit; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - @apply font-bold; - - a { - @apply dark:text-dark-anchor-header; - } -} - ul, ol { list-style: circle; diff --git a/apps/portfolio/src/main.tsx b/apps/portfolio/src/main.tsx index 51e561b..9f3ed5d 100644 --- a/apps/portfolio/src/main.tsx +++ b/apps/portfolio/src/main.tsx @@ -2,6 +2,12 @@ import "@fontsource/noto-sans-kr/400.css" import "@fontsource/noto-sans-kr/700.css" import "@fontsource/source-code-pro" import "./index.scss" +import "@developomp-site/blog/src/styles/anchor.scss" +import "@developomp-site/blog/src/styles/callout.scss" +import "@developomp-site/blog/src/styles/colorChip.scss" +import "@developomp-site/blog/src/styles/heading.scss" +import "@developomp-site/blog/src/styles/img.scss" +import "@developomp-site/blog/src/styles/mark.scss" import ReactDOM from "react-dom/client" diff --git a/packages/content/.eslintrc.js b/packages/content/.eslintrc.mjs similarity index 100% rename from packages/content/.eslintrc.js rename to packages/content/.eslintrc.mjs diff --git a/packages/content/markdown/posts/finding the ultimate browser.md b/packages/content/markdown/posts/finding the ultimate browser.md index 9c11758..b45ac2f 100644 --- a/packages/content/markdown/posts/finding the ultimate browser.md +++ b/packages/content/markdown/posts/finding the ultimate browser.md @@ -24,11 +24,12 @@ When I was old enough to understand language, my father introduced me to my firs At the time, it was everything I wished for and more, but little did I know, IE was already on the decline while another browser was quietly climbing up the market share. -

- browser market share -
- source: statcounter.com -

+
+ browser market share +
+ source: statcounter.com +
+
One day, probably after my father upgraded the PC to Windows 7, the default browser was changed to some colorful ball looking thing. diff --git a/packages/content/markdown/posts/test post.md b/packages/content/markdown/posts/test post.md index 3ec7f2b..b9e4fb4 100644 --- a/packages/content/markdown/posts/test post.md +++ b/packages/content/markdown/posts/test post.md @@ -15,7 +15,7 @@ This post exists to test various features such as markdown-to-html conversion, t ## Image -developomp icon +![alt text](/icon/icon.svg "title") ## Video @@ -51,15 +51,15 @@ This post exists to test various features such as markdown-to-html conversion, t ## Footnote -css only causes pain[^css_bad] and python is overrated[^python_is_overrated]. +everyone should use tailwind[^use_tailwind] and pineapple belongs on pizza[^pineapple_pizza_truth]. ## Code -Here's a `code`. +Here's a `code`. Here are color chips `#FFFFFF` `#E06C75` `#61AFEF` `#E5C07B`. -```python {7,12,14-15} +```python print("And here's a language-specific code block") -# with comments and line highlighting! +# with comments! x = 256 y = 256 @@ -81,13 +81,58 @@ print(z is w) # False. id(z) is not equal to id(w) > > > nested blockquote -**bold**
-_italic_
-~~strikethrough~~
-underlined
-==marked==
-this is a ^superscript^ (soon^TM^)
-and this is a ~subscript~ (H~2~O) +**bold** +_italic_ +~~strikethrough~~ +underlined +==marked== +=a=marked with color amber== +=b=blue== +=c=cyan== +=d=brown== +=f=fuchsia== +=g=green== +=h=hotpink== +=l=lime== +=m=magenta== +=n=navyblue== +=o=orange== +=p=purple== +=q=pink== +=r=red== +=s=silver== +=t=teal== +=v=violet== +=x=gray== +=y=yellow==. + +This is a ^superscript^ (soon^TM^) and this is a ~subscript~ (H~2~O) + +## Callouts & Directives + +:::note +Some **content** with _Markdown_ `syntax`. +::: + +:::commend +Some **content** with _Markdown_ `syntax`. +::: + +:::warn +Some **content** with _Markdown_ `syntax`. +::: + +:::deter +Some **content** with _Markdown_ `syntax`. +::: + +:::assert +Some **content** with _Markdown_ `syntax`. +::: + +:::note{title="Custom title using **directives**"} +Some **content** with _Markdown_ `syntax`. +::: ## CSS styling @@ -144,5 +189,5 @@ Lorem ipsum blah blah. -[^css_bad]: Based on my experience building this website, Dec 2021. -[^python_is_overrated]: Based on my infinite wisdom, Dec 2021. +[^use_tailwind]: Based on my experience building this website +[^pineapple_pizza_truth]: Based on my infinite wisdom diff --git a/packages/content/markdown/projects/wbm.md b/packages/content/markdown/projects/wbm.md index cf58ade..c9213a2 100644 --- a/packages/content/markdown/projects/wbm.md +++ b/packages/content/markdown/projects/wbm.md @@ -26,16 +26,12 @@ The War Brokers Mods (WBM) is a mod for the game different aspects of the game - [OBS overlay][overlays] - Customizable overlays for [OBS studio](https://github.com/obsproject/obs-studio) -

- Overlay image -

+![Overlay image](/img/portfolio/wbm-overlays.avif "Overlay image") - [installer][installer] - Utility for installing updating the mod. Built with [tauri][tauri], [rust][rust], [svelte][svelte], and [tailwind css][tailwindcss]. -

- Installer image -

+![Installer image](/img/portfolio/wbm-installer.avif "Installer image") [mod]: https://github.com/War-Brokers-Mods/WBM [overlays]: https://github.com/War-Brokers-Mods/WBM-Overlays diff --git a/packages/content/package.json b/packages/content/package.json index 4fc6312..0aeec52 100644 --- a/packages/content/package.json +++ b/packages/content/package.json @@ -1,52 +1,54 @@ { "name": "@developomp-site/content", "version": "0.0.0", - "license": "MIT", - "files": [ - "dist/**" - ], + "type": "module", "scripts": { - "build": "ts-node --experimental-specifier-resolution=node ./src", + "build": "rm -rf build && tsc && node --es-module-specifier-resolution=node build/index.js", "lint": "eslint .", - "clean": "rm -rf .turbo node_modules dist" + "clean": "rm -rf .turbo node_modules dist build" }, "dependencies": { + "@developomp-site/eslint-config": "workspace:^", + "@developomp-site/prettier-config": "workspace:^", + "@microflash/remark-callout-directives": "^1.6.0", + "@types/dompurify": "^3.0.2", "@types/ejs": "^3.1.2", + "@types/elasticlunr": "^0.9.5", + "@types/jsdom": "^21.1.1", "@types/katex": "^0.16.0", "@types/markdown-it": "^12.2.3", + "@types/node": "^20.4.1", "@types/read-time-estimate": "^0.0.0", "@types/svgo": "^3.0.0", "@types/tinycolor2": "^1.4.3", "canvas": "^2.11.2", "ejs": "^3.1.9", "elasticlunr": "^0.9.5", + "eslint": "^8.44.0", "gray-matter": "^4.0.3", "jsdom": "^22.1.0", - "markdown-it": "^13.0.1", - "markdown-it-anchor": "^8.6.7", - "markdown-it-attrs": "^4.1.6", - "markdown-it-footnote": "^3.0.3", - "markdown-it-highlight-lines": "^1.0.2", - "markdown-it-mark": "^3.0.1", - "markdown-it-sub": "^1.0.0", - "markdown-it-sup": "^1.0.0", - "markdown-it-task-checkbox": "^1.0.6", - "markdown-it-texmath": "^1.0.0", "markdown-toc": "^1.2.0", "read-time-estimate": "^0.0.3", + "rehype-autolink-headings": "^6.1.1", + "rehype-color-chips": "^0.1.3", + "rehype-highlight": "^6.0.0", + "rehype-katex": "^6.0.3", + "rehype-raw": "^6.1.1", + "rehype-slug": "^5.1.0", + "rehype-stringify": "^9.0.3", + "rehype-title-figure": "^0.1.2", + "remark-directive": "^2.0.1", + "remark-flexible-markers": "^1.0.3", + "remark-frontmatter": "^4.0.1", + "remark-gfm": "^3.0.1", + "remark-math": "^5.1.1", + "remark-parse": "^10.0.2", + "remark-rehype": "^10.1.0", + "remark-supersub": "^1.0.0", "simple-icons": "^9.4.0", - "slugify": "^1.6.6", "svgo": "^3.0.2", - "tinycolor2": "^1.6.0" - }, - "devDependencies": { - "@developomp-site/eslint-config": "workspace:*", - "@developomp-site/prettier-config": "workspace:*", - "@types/elasticlunr": "^0.9.5", - "@types/jsdom": "^21.1.1", - "@types/node": "^20.4.1", - "eslint": "^8.44.0", - "ts-node": "^10.9.1", - "typescript": "^5.1.6" + "tinycolor2": "^1.6.0", + "typescript": "^5.1.6", + "unified": "^10.1.2" } } diff --git a/packages/content/src/index.ts b/packages/content/src/index.ts index 5521bcd..fbca95c 100644 --- a/packages/content/src/index.ts +++ b/packages/content/src/index.ts @@ -34,53 +34,57 @@ export const portfolioData: PortfolioData = { projects: {}, } -/** - * Delete previously generated files - */ +async function main() { + /** + * Delete previously generated files + */ -try { - fs.rmSync("dist", { recursive: true }) - // eslint-disable-next-line no-empty -} catch (err) {} + try { + fs.rmSync("dist", { recursive: true }) + // eslint-disable-next-line no-empty + } catch (err) {} -/** - * Checking - */ + /** + * Checking + */ -if (!fs.lstatSync(markdownPath).isDirectory()) - throw Error("Invalid markdown path") + if (!fs.lstatSync(markdownPath).isDirectory()) + throw Error("Invalid markdown path") -if (!fs.lstatSync(markdownPath + "/posts").isDirectory()) - throw Error(`Cannot find directory: ${markdownPath + "/posts"}`) + if (!fs.lstatSync(markdownPath + "/posts").isDirectory()) + throw Error(`Cannot find directory: ${markdownPath + "/posts"}`) -if (!fs.lstatSync(markdownPath + "/series").isDirectory()) - throw Error(`Cannot find directory: ${markdownPath + "/posts"}`) + if (!fs.lstatSync(markdownPath + "/series").isDirectory()) + throw Error(`Cannot find directory: ${markdownPath + "/posts"}`) -/** - * Parse - */ + /** + * Parse + */ -// parse markdown -recursiveParse(ParseMode.POSTS, markdownPath + "/posts") -recursiveParse(ParseMode.SERIES, markdownPath + "/series") -recursiveParse(ParseMode.PORTFOLIO, markdownPath + "/projects") + // parse markdown + await recursiveParse(ParseMode.POSTS, markdownPath + "/posts") + await recursiveParse(ParseMode.SERIES, markdownPath + "/series") + await recursiveParse(ParseMode.PORTFOLIO, markdownPath + "/projects") -sortDates() -fillTags() -parseSeries() -generatePortfolioSVGs() + sortDates() + fillTags() + parseSeries() + generatePortfolioSVGs() -/** - * Save results - */ + /** + * Save results + */ -fs.writeFileSync(mapFilePath, JSON.stringify(contentMap)) -fs.writeFileSync( - portfolioFilePath, - JSON.stringify({ - ...portfolioData, - skills: Array.from(portfolioData.skills), - }) -) + fs.writeFileSync(mapFilePath, JSON.stringify(contentMap)) + fs.writeFileSync( + portfolioFilePath, + JSON.stringify({ + ...portfolioData, + skills: Array.from(portfolioData.skills), + }) + ) -saveIndex() + saveIndex() +} + +main() diff --git a/packages/content/src/parseMarkdown.ts b/packages/content/src/parseMarkdown.ts index d602633..9341530 100644 --- a/packages/content/src/parseMarkdown.ts +++ b/packages/content/src/parseMarkdown.ts @@ -1,58 +1,48 @@ -import "katex/contrib/mhchem" // chemical formula +import "katex/contrib/mhchem" // chemical formula, https://katex.org/docs/node.html#using-mhchem-extension +import remarkCalloutDirectives from "@microflash/remark-callout-directives" import matter from "gray-matter" -import hljs from "highlight.js" // code block syntax highlighting -import { JSDOM } from "jsdom" // HTML DOM parsing -import katex from "katex" // rendering mathematical expression -import markdownIt from "markdown-it" // rendering markdown -import markdownItAnchor from "markdown-it-anchor" // markdown anchor -import markdownItFootnote from "markdown-it-footnote" // markdown footnote -import highlightLines from "markdown-it-highlight-lines" // highlighting specific lines in code blocks -import markDownItMark from "markdown-it-mark" // text highlighting -import markdownItSub from "markdown-it-sub" // markdown subscript -import markdownItSup from "markdown-it-sup" // markdown superscript -import markdownItTaskCheckbox from "markdown-it-task-checkbox" // a TODO list checkboxes -import markdownItTexMath from "markdown-it-texmath" // rendering mathematical expression -import toc from "markdown-toc" // table of contents generation -import slugify from "slugify" +import { JSDOM } from "jsdom" +import toc from "markdown-toc" +import rehypeAutolinkHeadings from "rehype-autolink-headings" +import rehypeColorChips from "rehype-color-chips" +import rehypeHighlight from "rehype-highlight" +import rehypeKatex from "rehype-katex" +import rehypeRaw from "rehype-raw" +import rehypeSlug from "rehype-slug" +import rehypeStringify from "rehype-stringify" +import rehypeTitleFigure from "rehype-title-figure" +import remarkDirective from "remark-directive" +import remarkFlexibleMarkers from "remark-flexible-markers" +import remarkFrontmatter from "remark-frontmatter" +import remarkGfm from "remark-gfm" +import remarkMath from "remark-math" +import remarkParse from "remark-parse" +import remarkRehype from "remark-rehype" +import supersub from "remark-supersub" +import { unified } from "unified" import { MarkdownData, ParseMode } from "./types/types" import { nthIndex } from "./util" -const slugifyIt = (s: string) => slugify(s, { lower: true, strict: true }) - -const md = markdownIt({ - // https://github.com/highlightjs/highlight.js/blob/main/SUPPORTED_LANGUAGES.md - highlight: (str, lang) => { - if (lang && hljs.getLanguage(lang)) { - try { - return hljs.highlight(str, { language: lang }).value - // eslint-disable-next-line no-empty - } catch (error) {} - } - - return "" // use external default escaping - }, - html: true, -}) - .use(markdownItTexMath, { - engine: katex, - delimiters: "dollars", - }) - .use(markdownItAnchor, { - permalink: markdownItAnchor.permalink.ariaHidden({ - placement: "before", - symbol: "#", - renderHref: (s) => `#${slugifyIt(s)}`, - }), - slugify: slugifyIt, - }) - .use(markdownItTaskCheckbox) - .use(markDownItMark) - .use(markdownItSub) - .use(markdownItSup) - .use(highlightLines) - .use(markdownItFootnote) +const processor = unified() // interface for remark and rehype + .use(remarkParse) // markdown to AST + .use(remarkGfm, { singleTilde: false }) // https://github.com/remarkjs/remark-gfm + .use(supersub) // https://github.com/Symbitic/remark-plugins/tree/master/packages/remark-supersub + .use(remarkDirective) // https://github.com/remarkjs/remark-directive + .use(remarkCalloutDirectives) // https://github.com/Microflash/remark-callout-directives + .use(remarkMath) // https://github.com/remarkjs/remark-math + .use(remarkFlexibleMarkers) // https://github.com/ipikuka/remark-flexible-markers + .use(remarkFrontmatter, ["yaml", "toml"]) // https://github.com/remarkjs/remark-frontmatter + .use(remarkRehype, { allowDangerousHtml: true }) // markdown to HTML + .use(rehypeRaw) // https://github.com/rehypejs/rehype-raw + .use(rehypeSlug) // https://github.com/rehypejs/rehype-slug + .use(rehypeTitleFigure) // https://github.com/y-temp4/rehype-title-figure + .use(rehypeAutolinkHeadings, { content: { type: "text", value: "#" } }) // https://github.com/rehypejs/rehype-autolink-headings + .use(rehypeHighlight) // https://github.com/rehypejs/rehype-highlight + .use(rehypeKatex) // math and formula and stuff + .use(rehypeColorChips) // https://github.com/shreshthmohan/rehype-color-chips + .use(rehypeStringify) // syntax tree (hast) to HTML /** * parse the front matter if it exists @@ -61,11 +51,11 @@ const md = markdownIt({ * @param {string} path - filename of the markdown file * @param {ParseMode} mode */ -export default function parseMarkdown( +export default async function parseMarkdown( markdownRaw: string, path: string, mode: ParseMode -): MarkdownData { +): Promise { const fileHasFrontMatter = markdownRaw.startsWith("---") const frontMatter = fileHasFrontMatter @@ -83,31 +73,24 @@ export default function parseMarkdown( if (mode === ParseMode.PORTFOLIO) { if (frontMatter.overview) { - frontMatter.overview = md.render(frontMatter.overview) + frontMatter.overview = String( + processor.processSync(frontMatter.overview) + ) } } } - // - // work with rendered DOM - // - - const dom = new JSDOM( - md.render( - fileHasFrontMatter - ? markdownRaw.slice(nthIndex(markdownRaw, "---", 2) + 3) - : markdownRaw - ) || "" + frontMatter.content = touchupHTML( + String(processor.processSync(markdownRaw)) ) - // add .hljs class to all block codes + return frontMatter as MarkdownData +} - dom.window.document.querySelectorAll("pre > code").forEach((item) => { - item.classList.add("hljs") - }) +function touchupHTML(html: string): string { + const dom = new JSDOM(html) // add parent div to tables (horizontally scroll table on small displays) - dom.window.document.querySelectorAll("table").forEach((item) => { // `element` is the element you want to wrap const parent = item.parentNode @@ -119,13 +102,27 @@ export default function parseMarkdown( wrapper.appendChild(item) }) - frontMatter.content = dom.window.document.documentElement.innerHTML - - return frontMatter as MarkdownData -} - -export function generateToc(markdownRaw: string): string { - return md.render(toc(markdownRaw).content, { - slugify: slugifyIt, + // add hr before footnotes + dom.window.document.querySelectorAll(".footnotes").forEach((item) => { + item.parentNode?.insertBefore( + dom.window.document.createElement("hr"), + item + ) }) + + // https://developer.chrome.com/docs/lighthouse/best-practices/external-anchors-use-rel-noopener/ + // https://github.com/cure53/DOMPurify/issues/317#issuecomment-698800327 + dom.window.document.querySelectorAll("a").forEach((item) => { + if ("target" in item && item["target"] === "_blank") + item.setAttribute("rel", "noopener") + }) + + return dom.window.document.documentElement.innerHTML +} + +/** + * Generate Table of Contents as a HTML string + */ +export async function generateToc(markdownRaw: string): Promise { + return String(processor.processSync(toc(markdownRaw).content)) } diff --git a/packages/content/src/postProcess.ts b/packages/content/src/postProcess.ts index 6dabe4c..af903a5 100644 --- a/packages/content/src/postProcess.ts +++ b/packages/content/src/postProcess.ts @@ -5,7 +5,7 @@ import { optimize } from "svgo" import tinycolor from "tinycolor2" import { contentMap, seriesMap } from "." -import skills from "./portfolio/skills.json" +import skills from "./portfolio/skills.json" assert { type: "json" } import { Badge } from "./types/types" import { writeToFile } from "./util" diff --git a/packages/content/src/recursiveParse/index.ts b/packages/content/src/recursiveParse/index.ts index 4134d74..4cceeba 100644 --- a/packages/content/src/recursiveParse/index.ts +++ b/packages/content/src/recursiveParse/index.ts @@ -29,7 +29,10 @@ export interface DataToPass { * @param {ParseMode} mode - parse mode * @param {string} path - path of file or folder */ -export function recursiveParse(mode: ParseMode, path: string): void { +export async function recursiveParse( + mode: ParseMode, + path: string +): Promise { // get name of the file or folder that's currently being parsed const fileOrFolderName = path2FileOrFolderName(path) @@ -41,11 +44,11 @@ export function recursiveParse(mode: ParseMode, path: string): void { // if it's a directory, call this function to every files/directories in it // if it's a file, parse it and then save it to file if (stats.isDirectory()) { - fs.readdirSync(path).map((childPath) => { - recursiveParse(mode, `${path}/${childPath}`) - }) + for (const childPath of fs.readdirSync(path)) { + await recursiveParse(mode, `${path}/${childPath}`) + } } else if (stats.isFile()) { - parseFile(mode, path) + await parseFile(mode, path) } } @@ -55,7 +58,7 @@ export function recursiveParse(mode: ParseMode, path: string): void { * @param {ParseMode} mode - decides which function to use to parse the file * @param {string} path - path of the markdown file */ -function parseFile(mode: ParseMode, path: string): void { +async function parseFile(mode: ParseMode, path: string): Promise { // stop if it is not a markdown file if (!path.endsWith(".md")) { console.log(`Ignoring non markdown file at: ${path}`) @@ -67,8 +70,10 @@ function parseFile(mode: ParseMode, path: string): void { */ const markdownRaw = fs.readFileSync(path, "utf8") - const markdownData = parseMarkdown(markdownRaw, path, mode) - const { humanizedDuration, totalWords } = readTimeEstimate( + const markdownData = await parseMarkdown(markdownRaw, path, mode) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const { humanizedDuration, totalWords } = readTimeEstimate.default( markdownData.content, 275, 12, @@ -87,15 +92,15 @@ function parseFile(mode: ParseMode, path: string): void { switch (mode) { case ParseMode.POSTS: - parsePost(dataToPass) + await parsePost(dataToPass) break case ParseMode.SERIES: - parseSeries(dataToPass) + await parseSeries(dataToPass) break case ParseMode.PORTFOLIO: - parseProjects(dataToPass) + await parseProjects(dataToPass) break } } diff --git a/packages/content/src/recursiveParse/parsePost.ts b/packages/content/src/recursiveParse/parsePost.ts index 1749827..22f8c7c 100644 --- a/packages/content/src/recursiveParse/parsePost.ts +++ b/packages/content/src/recursiveParse/parsePost.ts @@ -6,7 +6,7 @@ import { PostData } from "../types/types" import { writeToFile } from "../util" import { DataToPass } from "." -export default function parsePost(data: DataToPass): void { +export default async function parsePost(data: DataToPass): Promise { const { urlPath, markdownRaw, @@ -70,7 +70,7 @@ export default function parsePost(data: DataToPass): void { `${contentDirectoryPath}${urlPath}.json`, JSON.stringify({ content: markdownData.content, - toc: generateToc(markdownRaw), + toc: await generateToc(markdownRaw), }) ) } diff --git a/packages/content/src/recursiveParse/parseProjects.ts b/packages/content/src/recursiveParse/parseProjects.ts index d48511d..f400f05 100644 --- a/packages/content/src/recursiveParse/parseProjects.ts +++ b/packages/content/src/recursiveParse/parseProjects.ts @@ -1,4 +1,5 @@ -import icons, { SimpleIcon } from "simple-icons" +import type { SimpleIcon } from "simple-icons" +import * as icons from "simple-icons" import tinycolor from "tinycolor2" import { portfolioData } from ".." @@ -7,9 +8,11 @@ import { generateToc } from "../parseMarkdown" import { writeToFile } from "../util" import { DataToPass } from "." -export default function parseProjects(data: DataToPass): void { - const { urlPath, markdownRaw, markdownData } = data - +export default async function parseProjects({ + urlPath, + markdownRaw, + markdownData, +}: DataToPass): Promise { if (markdownData.badges) { ;(markdownData.badges as string[]).forEach((slug) => { // todo: handle cases when icon is not on simple-icons @@ -48,7 +51,7 @@ export default function parseProjects(data: DataToPass): void { `${contentDirectoryPath}${urlPath}.json`, JSON.stringify({ content: markdownData.content, - toc: generateToc(markdownRaw), + toc: await generateToc(markdownRaw), }) ) } diff --git a/packages/content/src/recursiveParse/parseSeries.ts b/packages/content/src/recursiveParse/parseSeries.ts index 16eb18a..8bab489 100644 --- a/packages/content/src/recursiveParse/parseSeries.ts +++ b/packages/content/src/recursiveParse/parseSeries.ts @@ -6,7 +6,7 @@ import { PostData } from "../types/types" import { writeToFile } from "../util" import { DataToPass } from "." -export default function parseSeries(data: DataToPass): void { +export default async function parseSeries(data: DataToPass): Promise { const { path, urlPath: _urlPath, @@ -141,7 +141,7 @@ export default function parseSeries(data: DataToPass): void { `${contentDirectoryPath}${urlPath}.json`, JSON.stringify({ content: markdownData.content, - toc: generateToc(markdownRaw), + toc: await generateToc(markdownRaw), }) ) } diff --git a/packages/content/src/types/markdown-it-footnote.d.ts b/packages/content/src/types/markdown-it-footnote.d.ts deleted file mode 100644 index 7046cc6..0000000 --- a/packages/content/src/types/markdown-it-footnote.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "markdown-it-footnote" diff --git a/packages/content/src/types/markdown-it-highlight-lines.d.ts b/packages/content/src/types/markdown-it-highlight-lines.d.ts deleted file mode 100644 index 38d5f6d..0000000 --- a/packages/content/src/types/markdown-it-highlight-lines.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "markdown-it-highlight-lines" diff --git a/packages/content/src/types/markdown-it-mark.d.ts b/packages/content/src/types/markdown-it-mark.d.ts deleted file mode 100644 index 8fd714f..0000000 --- a/packages/content/src/types/markdown-it-mark.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "markdown-it-mark" diff --git a/packages/content/src/types/markdown-it-sub.d.ts b/packages/content/src/types/markdown-it-sub.d.ts deleted file mode 100644 index 1ab6246..0000000 --- a/packages/content/src/types/markdown-it-sub.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "markdown-it-sub" diff --git a/packages/content/src/types/markdown-it-sup.d.ts b/packages/content/src/types/markdown-it-sup.d.ts deleted file mode 100644 index 1c73173..0000000 --- a/packages/content/src/types/markdown-it-sup.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "markdown-it-sup" diff --git a/packages/content/src/types/markdown-it-task-checkbox.d.ts b/packages/content/src/types/markdown-it-task-checkbox.d.ts deleted file mode 100644 index 2cf33ad..0000000 --- a/packages/content/src/types/markdown-it-task-checkbox.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module "markdown-it-task-checkbox" diff --git a/packages/content/src/types/markdown-it-texmath.d.ts b/packages/content/src/types/markdown-it-texmath.d.ts deleted file mode 100644 index 61aae3d..0000000 --- a/packages/content/src/types/markdown-it-texmath.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module "markdown-it-texmath" { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - export default function texmath(md: MarkdownIt, ...params: any[]): void -} diff --git a/packages/content/tsconfig.json b/packages/content/tsconfig.json index 66218d4..447d92d 100644 --- a/packages/content/tsconfig.json +++ b/packages/content/tsconfig.json @@ -1,13 +1,15 @@ { "include": ["src"], - "ts-node": { - "esm": true - }, "compilerOptions": { + "outDir": "build", + "target": "ES2022", + "module": "ESNext", "moduleResolution": "Node", "noImplicitAny": false, - "resolveJsonModule": true, "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, "strict": true }, "exclude": ["dist", "node_modules"] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 98ace61..1bca2d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -241,6 +241,9 @@ importers: specifier: ^2.11.0 version: 2.11.0(react@18.2.0) devDependencies: + '@developomp-site/blog': + specifier: workspace:* + version: link:../blog '@developomp-site/content': specifier: workspace:* version: link:../../packages/content @@ -325,6 +328,9 @@ importers: '@developomp-site/prettier-config': specifier: workspace:^ version: link:../prettier-config + '@microflash/remark-callout-directives': + specifier: ^1.6.0 + version: 1.6.0 '@types/dompurify': specifier: ^3.0.2 version: 3.0.2 @@ -370,9 +376,6 @@ importers: gray-matter: specifier: ^4.0.3 version: 4.0.3 - isomorphic-dompurify: - specifier: ^1.7.0 - version: 1.7.0(canvas@2.11.2) jsdom: specifier: ^22.1.0 version: 22.1.0(canvas@2.11.2) @@ -382,15 +385,42 @@ importers: read-time-estimate: specifier: ^0.0.3 version: 0.0.3 + rehype-autolink-headings: + specifier: ^6.1.1 + version: 6.1.1 rehype-color-chips: specifier: ^0.1.3 version: 0.1.3 + rehype-highlight: + specifier: ^6.0.0 + version: 6.0.0 rehype-katex: specifier: ^6.0.3 version: 6.0.3 + rehype-raw: + specifier: ^6.1.1 + version: 6.1.1 + rehype-slug: + specifier: ^5.1.0 + version: 5.1.0 rehype-stringify: specifier: ^9.0.3 version: 9.0.3 + rehype-title-figure: + specifier: ^0.1.2 + version: 0.1.2 + remark-directive: + specifier: ^2.0.1 + version: 2.0.1 + remark-flexible-markers: + specifier: ^1.0.3 + version: 1.0.3 + remark-frontmatter: + specifier: ^4.0.1 + version: 4.0.1 + remark-gfm: + specifier: ^3.0.1 + version: 3.0.1 remark-math: specifier: ^5.1.1 version: 5.1.1 @@ -400,6 +430,9 @@ importers: remark-rehype: specifier: ^10.1.0 version: 10.1.0 + remark-supersub: + specifier: ^1.0.0 + version: 1.0.0 simple-icons: specifier: ^9.4.0 version: 9.4.0 @@ -2202,6 +2235,17 @@ packages: - supports-color dev: false + /@microflash/remark-callout-directives@1.6.0: + resolution: {integrity: sha512-W2ovtw9JdSpO/gjQb3wlf3o5AW4h+w6mewXybsrtSvifb/30P7ahBELDmFSCQBuXiofMbN8xO0/0GqVYoZrXmQ==} + dependencies: + defu: 6.1.2 + hastscript: 7.2.0 + mdast-util-from-markdown: 1.3.1 + unist-util-visit: 4.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /@nicolo-ribaudo/semver-v6@6.3.3: resolution: {integrity: sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==} hasBin: true @@ -2990,6 +3034,10 @@ packages: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} dev: false + /character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + dev: false + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -3056,6 +3104,10 @@ packages: delayed-stream: 1.0.0 dev: false + /comma-separated-tokens@1.0.8: + resolution: {integrity: sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==} + dev: false + /comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} dev: false @@ -3261,6 +3313,10 @@ packages: object-keys: 1.1.1 dev: true + /defu@6.1.2: + resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} + dev: false + /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -3352,10 +3408,6 @@ packages: domelementtype: 2.3.0 dev: false - /dompurify@3.0.4: - resolution: {integrity: sha512-ae0mA+Qiqp6C29pqZX3fQgK+F91+F7wobM/v8DRzDqJdZJELXiFUx4PP4pK/mzUS0xkiSEx3Ncd9gr69jg3YsQ==} - dev: false - /domutils@3.1.0: resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} dependencies: @@ -3513,6 +3565,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: false + /eslint-config-prettier@8.8.0(eslint@8.44.0): resolution: {integrity: sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==} hasBin: true @@ -3856,6 +3913,12 @@ packages: dependencies: reusify: 1.0.4 + /fault@2.0.1: + resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} + dependencies: + format: 0.2.2 + dev: false + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -3923,6 +3986,11 @@ packages: mime-types: 2.1.35 dev: false + /format@0.2.2: + resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} + engines: {node: '>=0.4.x'} + dev: false + /fraction.js@4.2.0: resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} dev: true @@ -3999,6 +4067,10 @@ packages: get-intrinsic: 1.2.1 dev: true + /github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + dev: false + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4193,6 +4265,16 @@ packages: web-namespaces: 2.0.1 dev: false + /hast-util-has-property@2.0.1: + resolution: {integrity: sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==} + dev: false + + /hast-util-heading-rank@2.1.1: + resolution: {integrity: sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==} + dependencies: + '@types/hast': 2.3.4 + dev: false + /hast-util-is-element@2.1.3: resolution: {integrity: sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==} dependencies: @@ -4200,6 +4282,10 @@ packages: '@types/unist': 2.0.6 dev: false + /hast-util-parse-selector@2.2.5: + resolution: {integrity: sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==} + dev: false + /hast-util-parse-selector@3.1.1: resolution: {integrity: sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==} dependencies: @@ -4268,6 +4354,16 @@ packages: resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} dev: false + /hastscript@6.0.0: + resolution: {integrity: sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==} + dependencies: + '@types/hast': 2.3.4 + comma-separated-tokens: 1.0.8 + hast-util-parse-selector: 2.2.5 + property-information: 5.6.0 + space-separated-tokens: 1.1.5 + dev: false + /hastscript@7.2.0: resolution: {integrity: sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==} dependencies: @@ -4370,6 +4466,17 @@ packages: side-channel: 1.0.4 dev: true + /is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + dev: false + + /is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + dev: false + /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: @@ -4430,6 +4537,10 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + dev: false + /is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -4456,6 +4567,10 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + dev: false + /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} @@ -4573,19 +4688,6 @@ packages: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} - /isomorphic-dompurify@1.7.0(canvas@2.11.2): - resolution: {integrity: sha512-Iqt+WDG6I6qjsHAV9k3TYXemKHz5pfMZbSDklCXY2KaQY/jY2s+VbpxKP4j0ujCZ+11/oUB4NPQMY+dVEJ9vPA==} - dependencies: - '@types/dompurify': 3.0.2 - dompurify: 3.0.4 - jsdom: 22.1.0(canvas@2.11.2) - transitivePeerDependencies: - - bufferutil - - canvas - - supports-color - - utf-8-validate - dev: false - /jake@10.8.7: resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==} engines: {node: '>=10'} @@ -4803,6 +4905,14 @@ packages: js-tokens: 4.0.0 dev: false + /lowlight@2.9.0: + resolution: {integrity: sha512-OpcaUTCLmHuVuBcyNckKfH5B0oA4JUavb/M/8n9iAvanJYNQkrVm4pvyX0SUaqkBG4dnWHKt7p50B3ngAG2Rfw==} + dependencies: + '@types/hast': 2.3.4 + fault: 2.0.1 + highlight.js: 11.8.0 + dev: false + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: @@ -4840,6 +4950,10 @@ packages: engines: {node: '>=0.10.0'} dev: false + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + /markdown-toc@1.2.0: resolution: {integrity: sha512-eOsq7EGd3asV0oBfmyqngeEIhrbkc7XVP63OwcJBIhH2EpG2PzFcbZdhy1jutXSlRBBVMNXHvMtSr5LAxSUvUg==} engines: {node: '>=0.10.0'} @@ -4871,6 +4985,29 @@ packages: unist-util-visit: 4.1.2 dev: false + /mdast-util-directive@2.2.4: + resolution: {integrity: sha512-sK3ojFP+jpj1n7Zo5ZKvoxP1MvLyzVG63+gm40Z/qI00avzdPCYxt7RBMgofwAva9gBjbDBWVRB/i+UD+fUCzQ==} + dependencies: + '@types/mdast': 3.0.11 + '@types/unist': 2.0.6 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + parse-entities: 4.0.1 + stringify-entities: 4.0.3 + unist-util-visit-parents: 5.1.3 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-find-and-replace@2.2.2: + resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==} + dependencies: + '@types/mdast': 3.0.11 + escape-string-regexp: 5.0.0 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + dev: false + /mdast-util-from-markdown@1.3.1: resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} dependencies: @@ -4890,6 +5027,70 @@ packages: - supports-color dev: false + /mdast-util-frontmatter@1.0.1: + resolution: {integrity: sha512-JjA2OjxRqAa8wEG8hloD0uTU0kdn8kbtOWpPP94NBkfAlbxn4S8gCGf/9DwFtEeGPXrDcNXdiDjVaRdUFqYokw==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-to-markdown: 1.5.0 + micromark-extension-frontmatter: 1.1.1 + dev: false + + /mdast-util-gfm-autolink-literal@1.0.3: + resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==} + dependencies: + '@types/mdast': 3.0.11 + ccount: 2.0.1 + mdast-util-find-and-replace: 2.2.2 + micromark-util-character: 1.2.0 + dev: false + + /mdast-util-gfm-footnote@1.0.2: + resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-to-markdown: 1.5.0 + micromark-util-normalize-identifier: 1.1.0 + dev: false + + /mdast-util-gfm-strikethrough@1.0.3: + resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-to-markdown: 1.5.0 + dev: false + + /mdast-util-gfm-table@1.0.7: + resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==} + dependencies: + '@types/mdast': 3.0.11 + markdown-table: 3.0.3 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item@1.0.2: + resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-to-markdown: 1.5.0 + dev: false + + /mdast-util-gfm@2.0.2: + resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==} + dependencies: + mdast-util-from-markdown: 1.3.1 + mdast-util-gfm-autolink-literal: 1.0.3 + mdast-util-gfm-footnote: 1.0.2 + mdast-util-gfm-strikethrough: 1.0.3 + mdast-util-gfm-table: 1.0.7 + mdast-util-gfm-task-list-item: 1.0.2 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + dev: false + /mdast-util-math@2.0.2: resolution: {integrity: sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==} dependencies: @@ -4970,6 +5171,99 @@ packages: uvu: 0.5.6 dev: false + /micromark-extension-directive@2.2.1: + resolution: {integrity: sha512-ZFKZkNaEqAP86IghX1X7sE8NNnx6kFNq9mSBRvEHjArutTCJZ3LYg6VH151lXVb1JHpmIcW/7rX25oMoIHuSug==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-factory-whitespace: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + parse-entities: 4.0.1 + uvu: 0.5.6 + dev: false + + /micromark-extension-frontmatter@1.1.1: + resolution: {integrity: sha512-m2UH9a7n3W8VAH9JO9y01APpPKmNNNs71P0RbknEmYSaZU5Ghogv38BYO94AI5Xw6OYfxZRdHZZ2nYjs/Z+SZQ==} + dependencies: + fault: 2.0.1 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-extension-gfm-autolink-literal@1.0.5: + resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==} + dependencies: + micromark-util-character: 1.2.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + + /micromark-extension-gfm-footnote@1.1.2: + resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==} + dependencies: + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-strikethrough@1.0.7: + resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==} + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-table@1.0.7: + resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm-tagfilter@1.0.2: + resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==} + dependencies: + micromark-util-types: 1.1.0 + dev: false + + /micromark-extension-gfm-task-list-item@1.0.5: + resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==} + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + dev: false + + /micromark-extension-gfm@2.0.3: + resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==} + dependencies: + micromark-extension-gfm-autolink-literal: 1.0.5 + micromark-extension-gfm-footnote: 1.1.2 + micromark-extension-gfm-strikethrough: 1.0.7 + micromark-extension-gfm-table: 1.0.7 + micromark-extension-gfm-tagfilter: 1.0.2 + micromark-extension-gfm-task-list-item: 1.0.5 + micromark-util-combine-extensions: 1.1.0 + micromark-util-types: 1.1.0 + dev: false + /micromark-extension-math@2.1.2: resolution: {integrity: sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==} dependencies: @@ -5405,6 +5699,19 @@ packages: dependencies: callsites: 3.1.0 + /parse-entities@4.0.1: + resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + dependencies: + '@types/unist': 2.0.6 + character-entities: 2.0.2 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.0.2 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + dev: false + /parse-json@5.2.0: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} @@ -5672,6 +5979,12 @@ packages: react-is: 16.13.1 dev: false + /property-information@5.6.0: + resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} + dependencies: + xtend: 4.0.2 + dev: false + /property-information@6.2.0: resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} dev: false @@ -5827,6 +6140,18 @@ packages: jsesc: 0.5.0 dev: true + /rehype-autolink-headings@6.1.1: + resolution: {integrity: sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==} + dependencies: + '@types/hast': 2.3.4 + extend: 3.0.2 + hast-util-has-property: 2.0.1 + hast-util-heading-rank: 2.1.1 + hast-util-is-element: 2.1.3 + unified: 10.1.2 + unist-util-visit: 4.1.2 + dev: false + /rehype-color-chips@0.1.3: resolution: {integrity: sha512-K9/YXDSdDFMVey9QFnZmECCDFoWVUMa82TnHsHbN02j+D+fvwclxlWGFhKfsR7SfWFh4abF83cSU2Yp6abDERg==} dependencies: @@ -5835,6 +6160,16 @@ packages: unist-util-visit: 4.1.2 dev: false + /rehype-highlight@6.0.0: + resolution: {integrity: sha512-q7UtlFicLhetp7K48ZgZiJgchYscMma7XjzX7t23bqEJF8m6/s+viXQEe4oHjrATTIZpX7RG8CKD7BlNZoh9gw==} + dependencies: + '@types/hast': 2.3.4 + hast-util-to-text: 3.1.2 + lowlight: 2.9.0 + unified: 10.1.2 + unist-util-visit: 4.1.2 + dev: false + /rehype-katex@6.0.3: resolution: {integrity: sha512-ByZlRwRUcWegNbF70CVRm2h/7xy7jQ3R9LaY4VVSvjnoVWwWVhNL60DiZsBpC5tSzYQOCvDbzncIpIjPZWodZA==} dependencies: @@ -5846,6 +6181,26 @@ packages: unist-util-visit: 4.1.2 dev: false + /rehype-raw@6.1.1: + resolution: {integrity: sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==} + dependencies: + '@types/hast': 2.3.4 + hast-util-raw: 7.2.3 + unified: 10.1.2 + dev: false + + /rehype-slug@5.1.0: + resolution: {integrity: sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==} + dependencies: + '@types/hast': 2.3.4 + github-slugger: 2.0.0 + hast-util-has-property: 2.0.1 + hast-util-heading-rank: 2.1.1 + hast-util-to-string: 2.0.0 + unified: 10.1.2 + unist-util-visit: 4.1.2 + dev: false + /rehype-stringify@9.0.3: resolution: {integrity: sha512-kWiZ1bgyWlgOxpqD5HnxShKAdXtb2IUljn3hQAhySeak6IOQPPt6DeGnsIh4ixm7yKJWzm8TXFuC/lPfcWHJqw==} dependencies: @@ -5854,6 +6209,52 @@ packages: unified: 10.1.2 dev: false + /rehype-title-figure@0.1.2: + resolution: {integrity: sha512-CHMIb46yg5/ocVYtLUlvxYSRLCLidijOkSBXRCebTWD6qOuJ3eo/J4gG4zri1Xo4fNH0C8KrA/J4aNdhikzYdQ==} + dependencies: + hastscript: 6.0.0 + unist-util-visit: 2.0.3 + dev: false + + /remark-directive@2.0.1: + resolution: {integrity: sha512-oosbsUAkU/qmUE78anLaJePnPis4ihsE7Agp0T/oqTzvTea8pOiaYEtfInU/+xMOVTS9PN5AhGOiaIVe4GD8gw==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-directive: 2.2.4 + micromark-extension-directive: 2.2.1 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-flexible-markers@1.0.3: + resolution: {integrity: sha512-O3aXLFXbPZRS9lZfTxqzgG0sknqgMdz0pfqp4vx5cofjlPfSJVyGMfTB5jxIdum4XzhN0FVtRBB+ksZocX168w==} + dependencies: + '@types/mdast': 3.0.11 + unist-builder: 3.0.1 + unist-util-visit: 4.1.2 + dev: false + + /remark-frontmatter@4.0.1: + resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-frontmatter: 1.0.1 + micromark-extension-frontmatter: 1.1.1 + unified: 10.1.2 + dev: false + + /remark-gfm@3.0.1: + resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} + dependencies: + '@types/mdast': 3.0.11 + mdast-util-gfm: 2.0.2 + micromark-extension-gfm: 2.0.3 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /remark-math@5.1.1: resolution: {integrity: sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==} dependencies: @@ -5882,6 +6283,12 @@ packages: unified: 10.1.2 dev: false + /remark-supersub@1.0.0: + resolution: {integrity: sha512-3SYsphMqpAWbr8AZozdcypozinl/lly3e7BEwPG3YT5J9uZQaDcELBF6/sr/OZoAlFxy2nhNFWSrZBu/ZPRT3Q==} + dependencies: + unist-util-visit: 4.1.2 + dev: false + /remarkable@1.7.4: resolution: {integrity: sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==} engines: {node: '>= 0.10.0'} @@ -6121,6 +6528,10 @@ packages: engines: {node: '>= 8'} dev: true + /space-separated-tokens@1.1.5: + resolution: {integrity: sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==} + dev: false + /space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} dev: false @@ -6707,6 +7118,12 @@ packages: vfile: 5.3.7 dev: false + /unist-builder@3.0.1: + resolution: {integrity: sha512-gnpOw7DIpCA0vpr6NqdPvTWnlPTApCTRzr+38E6hCWx3rz/cjo83SsKIlS1Z+L5ttScQ2AwutNnb8+tAvpb6qQ==} + dependencies: + '@types/unist': 2.0.6 + dev: false + /unist-util-find-after@4.0.1: resolution: {integrity: sha512-QO/PuPMm2ERxC6vFXEPtmAutOopy5PknD+Oq64gGwxKtk4xwo9Z97t9Av1obPmGU0IyTa6EKYUfTrK2QJS3Ozw==} dependencies: @@ -6718,6 +7135,10 @@ packages: resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} dev: false + /unist-util-is@4.1.0: + resolution: {integrity: sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==} + dev: false + /unist-util-is@5.2.1: resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} dependencies: @@ -6743,6 +7164,13 @@ packages: '@types/unist': 2.0.6 dev: false + /unist-util-visit-parents@3.1.1: + resolution: {integrity: sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 4.1.0 + dev: false + /unist-util-visit-parents@5.1.3: resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} dependencies: @@ -6750,6 +7178,14 @@ packages: unist-util-is: 5.2.1 dev: false + /unist-util-visit@2.0.3: + resolution: {integrity: sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 4.1.0 + unist-util-visit-parents: 3.1.1 + dev: false + /unist-util-visit@4.1.2: resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} dependencies: