From 207bb14186b4635349ace7d646d8b36f17b0cb0f Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 29 Jul 2026 19:42:20 +0100 Subject: [PATCH] refactor: migrate to `comark` (#1877) --- app/components/{mdc => }/CalSchedule.vue | 0 app/components/{mdc => }/SocialPost.vue | 0 app/components/StaticMarkdownRender.server.ts | 8 +- app/components/{mdc => markdown}/ProseA.vue | 0 app/components/markdown/ProseH2.vue | 20 + app/components/markdown/ProseH3.vue | 20 + app/components/{mdc => markdown}/ProseImg.vue | 0 app/components/{mdc => markdown}/ProseTh.vue | 0 app/pages/blog/[article].vue | 9 + content/bio.md | 6 +- content/blog/a-letter-to-modern-frontends.md | 30 +- content/blog/nuxt-server-components.md | 2 +- content/blog/today-is-your-day.md | 16 +- modules/markdown.ts | 50 +- modules/router/index.ts | 7 + modules/shared/comark-heading-ids.ts | 61 ++ modules/shared/md-transforms.ts | 27 + nuxt.config.ts | 17 +- package.json | 6 +- pnpm-lock.yaml | 878 ++++-------------- test/unit/behaviour.spec.ts | 26 + test/unit/bundle.spec.ts | 192 +--- 22 files changed, 418 insertions(+), 957 deletions(-) rename app/components/{mdc => }/CalSchedule.vue (100%) rename app/components/{mdc => }/SocialPost.vue (100%) rename app/components/{mdc => markdown}/ProseA.vue (100%) create mode 100644 app/components/markdown/ProseH2.vue create mode 100644 app/components/markdown/ProseH3.vue rename app/components/{mdc => markdown}/ProseImg.vue (100%) rename app/components/{mdc => markdown}/ProseTh.vue (100%) create mode 100644 modules/shared/comark-heading-ids.ts diff --git a/app/components/mdc/CalSchedule.vue b/app/components/CalSchedule.vue similarity index 100% rename from app/components/mdc/CalSchedule.vue rename to app/components/CalSchedule.vue diff --git a/app/components/mdc/SocialPost.vue b/app/components/SocialPost.vue similarity index 100% rename from app/components/mdc/SocialPost.vue rename to app/components/SocialPost.vue diff --git a/app/components/StaticMarkdownRender.server.ts b/app/components/StaticMarkdownRender.server.ts index d1d8ab19..d9c20a98 100644 --- a/app/components/StaticMarkdownRender.server.ts +++ b/app/components/StaticMarkdownRender.server.ts @@ -1,7 +1,9 @@ -import { MDCRenderer } from '#components' +import { CalSchedule, ComarkRenderer, ProseA, ProseH2, ProseH3, ProseImg, ProseTh, SocialPost } from '#components' import { blogBodyLoaders } from '#build/markdown/blog/index.mjs' import { pageBodyLoaders } from '#build/markdown/page/index.mjs' +const components = { CalSchedule, ProseA, ProseH2, ProseH3, ProseImg, ProseTh, SocialPost } + export default defineComponent({ props: { collection: { type: String as () => 'page' | 'blog', required: true }, @@ -16,7 +18,7 @@ export default defineComponent({ return () => null } - const parsed = await loader() - return () => h(MDCRenderer, { body: parsed.body, tag: 'div' }) + const tree = await loader() + return () => h(ComarkRenderer, { tree, components }) }, }) diff --git a/app/components/mdc/ProseA.vue b/app/components/markdown/ProseA.vue similarity index 100% rename from app/components/mdc/ProseA.vue rename to app/components/markdown/ProseA.vue diff --git a/app/components/markdown/ProseH2.vue b/app/components/markdown/ProseH2.vue new file mode 100644 index 00000000..75ebd83d --- /dev/null +++ b/app/components/markdown/ProseH2.vue @@ -0,0 +1,20 @@ + + + diff --git a/app/components/markdown/ProseH3.vue b/app/components/markdown/ProseH3.vue new file mode 100644 index 00000000..fd3ed813 --- /dev/null +++ b/app/components/markdown/ProseH3.vue @@ -0,0 +1,20 @@ + + + diff --git a/app/components/mdc/ProseImg.vue b/app/components/markdown/ProseImg.vue similarity index 100% rename from app/components/mdc/ProseImg.vue rename to app/components/markdown/ProseImg.vue diff --git a/app/components/mdc/ProseTh.vue b/app/components/markdown/ProseTh.vue similarity index 100% rename from app/components/mdc/ProseTh.vue rename to app/components/markdown/ProseTh.vue diff --git a/app/pages/blog/[article].vue b/app/pages/blog/[article].vue index 4962e3f4..e11333c9 100644 --- a/app/pages/blog/[article].vue +++ b/app/pages/blog/[article].vue @@ -249,6 +249,15 @@ header dl dd:first-of-type { content: '›'; } + ul:global(.link-grid) { + display: grid; + grid-template-columns: auto auto auto; + } + + ul:global(.link-grid) li { + @apply my-0; + } + ol li::before { @apply text-xs; diff --git a/content/bio.md b/content/bio.md index f659c77d..6eef859d 100644 --- a/content/bio.md +++ b/content/bio.md @@ -1,8 +1,6 @@ -
- +::div{.text-xl.mb-4} Daniel leads the [Nuxt core team](https://nuxt.com). Previously, he was CTO of a SaaS startup and founder of a creative agency focusing on clarity of vision and message. - -
+:: He is part of the team at [Vercel](https://vercel.com) where he is employed to work full-time on Nuxt. diff --git a/content/blog/a-letter-to-modern-frontends.md b/content/blog/a-letter-to-modern-frontends.md index c49616ad..c2fca194 100644 --- a/content/blog/a-letter-to-modern-frontends.md +++ b/content/blog/a-letter-to-modern-frontends.md @@ -18,22 +18,20 @@ For a start, let me say how much I enjoyed myself. The speakers were great! What You and I had a few moments to chat, particularly when you were feeling embattled because of comments on Twitter, and I’m sure you’ve seen these posts as they went up: - +::ul{.link-grid} +- [Jo](https://dev.to/thisisjofrank/my-experience-of-modern-frontends-conference-1cgg) +- [Cassie](https://www.cassie.codes/posts/modern-frontends/) +- [Hidde](https://hidde.blog/modern-frontends-live/) +- [Mike](https://mhartington.io/post/modern-frontends-live/) +- [Todd](https://toddl.dev/posts/modern-frontends/) +- [Andy](https://andy-bell.co.uk/modern-frontends-live/) +- [Chris](https://christopherallanperry.github.io/blog/2022/11/20/modern_frontends-an_attendees_perspective.html) +- [JD](https://jdhillen.com/blog/my-experience-at-modern-frontends-live/) +- [Niamh](https://dev.to/niamhmccoo/my-experience-at-modern-frontends-live-1lcn) +- [Kent](https://kentcdodds.com/blog/my-modern-frontends-live-experience) +- [Dylan](https://dylanbeattie.net/2022/11/22/modern-frontends-2022.html) +- [Niels](https://nielsleenheer.com/articles/2022/red-flag-speakers-having-to-cover-their-own-travel/) +:: I would say their summary of the facts on the ground is fair. diff --git a/content/blog/nuxt-server-components.md b/content/blog/nuxt-server-components.md index 5c9ad868..90421ab3 100644 --- a/content/blog/nuxt-server-components.md +++ b/content/blog/nuxt-server-components.md @@ -35,7 +35,7 @@ It's possible to use server components within [Nuxt](https://nuxt.com/), even if
This means you can use server components on **static hosting** - no need to update to serverless/edge rendering in order to benefit. -
⚡️ Plus, if you have enabled payload extraction (which is enabled by default in generated/static sites, and can also be enabled for hybrid deployments), then Nuxt will even prefetch server components used in pages you might navigate to, so they will load instantly.
+ > ⚡️ Plus, if you have enabled payload extraction (which is enabled by default in generated/static sites, and can also be enabled for hybrid deployments), then Nuxt will even prefetch server components used in pages you might navigate to, so they will load instantly. 1. 🔄 Server components **are interchangeable with normal components**. diff --git a/content/blog/today-is-your-day.md b/content/blog/today-is-your-day.md index 9da7cd93..1ab8a709 100644 --- a/content/blog/today-is-your-day.md +++ b/content/blog/today-is-your-day.md @@ -13,8 +13,7 @@ Reflection isn't my strong suit. I think. But I wish it were more part of my lif ## Oh, the places you'll go! -
- +::div This year, I've attended conferences or meetups in Toronto, Prague, Seattle, Amsterdam, Glasgow, Middlesbrough, Bonn, Portlaoise, Athens, New Orleans, San Francisco, London and Edinburgh. I've also enjoyed making [EdinburghJS](https://www.edinburghjs.org/) a regular part of my life.

Flighty 'passport'

@@ -26,8 +25,7 @@ I also find that travelling can be productive. I love coding on the plane or tra - **Next year, I'd like to widen the circle**. I'd like to see more folk I don't already know. That will mean answering CFPs at conferences further afield. Recommendations welcome 🙏 - -
+:: ## You’ll be seeing great sights! @@ -57,17 +55,15 @@ I _love_ coding. It's fun and my hobby. I don't have an objective to be 'active' That's a side-effect of doing something that I enjoy. -
+::figure{.my-4} Git Wrapped profile for @danielroe, showing my 2024 Year in Code, with 👑 Universal Rank: Top 0.5%, ⚡️ Longest Streak: 366 days, 🏆 Total Commits: 13,020, 📅 Most Active Month: December, 📊 Most Active Day: Tuesday, ⭐ Stars Earned: 81,796, 🚀 Top Language: TypeScript, 🪐 Power Level: God Mode -
- +:::figcaption{.text-xs} the chart shows [issues, PRs, discussions and commits](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-settings-on-your-profile/why-are-my-contributions-not-showing-up-on-my-profile) on GitHub - -
-
+::: +:: I count myself incredibly fortunate to be able to make a living from being a [full-time open source maintainer](/blog/funding). diff --git a/modules/markdown.ts b/modules/markdown.ts index 283baa78..64f0bde6 100644 --- a/modules/markdown.ts +++ b/modules/markdown.ts @@ -7,9 +7,13 @@ import { filename } from 'pathe/utils' import { remark } from 'remark' import remarkHtml from 'remark-html' import { convert as htmlToText } from 'html-to-text' +import { createParse } from 'comark/parse' +import highlight from 'comark/plugins/highlight' +import palenight from 'shiki/themes/material-theme-palenight.mjs' +import { headingIds } from './shared/comark-heading-ids' import { serialize } from './shared/serialisers' -import { mdCleanHtml, mdInternalLinks } from './shared/md-transforms' +import { mdCleanHtml, mdInternalLinks, mdStripContainers } from './shared/md-transforms' import { tidFromDate } from './shared/tid' interface BlogFrontmatter { @@ -96,18 +100,23 @@ export default defineNuxtModule({ write: true, }) + const parse = createParse({ + plugins: [ + headingIds(), + // code blocks always render on a dark background, so both themes match + highlight({ + themes: { light: palenight, dark: palenight }, + }), + ], + }) + for (const post of blogPosts) { + const tree = await parse(post.body) addTemplate({ filename: `markdown/blog/${post.slug}.mjs`, - getContents: () => ` -import { parseMarkdown } from '@nuxtjs/mdc/runtime' - -let _parsed + getContents: () => `const tree = ${JSON.stringify(tree)} export async function getBody () { - if (!_parsed) { - _parsed = await parseMarkdown(${JSON.stringify(post.body)}) - } - return _parsed + return tree } `, write: true, @@ -115,17 +124,12 @@ export async function getBody () { } for (const slug of Object.keys(pageBodies)) { + const tree = await parse(pageBodies[slug]!) addTemplate({ filename: `markdown/page/${slug}.mjs`, - getContents: () => ` -import { parseMarkdown } from '@nuxtjs/mdc/runtime' - -let _parsed + getContents: () => `const tree = ${JSON.stringify(tree)} export async function getBody () { - if (!_parsed) { - _parsed = await parseMarkdown(${JSON.stringify(pageBodies[slug])}) - } - return _parsed + return tree } `, write: true, @@ -204,7 +208,7 @@ export async function getBody () { date: typeof post.date === 'string' ? post.date.split('T')[0] : post.date, tags: post.tags, description: post.description, - body: mdInternalLinks(serialize(post.body)).trim(), + body: mdInternalLinks(mdStripContainers(serialize(post.body))).trim(), })) nuxt.options.nitro.virtual['#md-raw-blog.json'] = () => @@ -212,7 +216,7 @@ export async function getBody () { const rawPageData: Record = {} for (const [slug, body] of Object.entries(pageBodies)) { - rawPageData[slug] = mdInternalLinks(mdCleanHtml(serialize(body))) + rawPageData[slug] = mdInternalLinks(mdCleanHtml(mdStripContainers(serialize(body)))) } nuxt.options.nitro.virtual['#md-raw-pages.json'] = () => @@ -240,13 +244,13 @@ declare module '#build/markdown/blog-entries.mjs' { } declare module '#build/markdown/blog/index.mjs' { - import type { MDCParserResult } from '@nuxtjs/mdc' - export const blogBodyLoaders: Record Promise> + import type { ComarkTree } from 'comark' + export const blogBodyLoaders: Record Promise> } declare module '#build/markdown/page/index.mjs' { - import type { MDCParserResult } from '@nuxtjs/mdc' - export const pageBodyLoaders: Record Promise> + import type { ComarkTree } from 'comark' + export const pageBodyLoaders: Record Promise> } declare module '#md-raw-blog.json' { diff --git a/modules/router/index.ts b/modules/router/index.ts index e3504606..4aac2753 100644 --- a/modules/router/index.ts +++ b/modules/router/index.ts @@ -2,6 +2,7 @@ import { statSync } from 'node:fs' import fsp from 'node:fs/promises' import { join, relative } from 'pathe' + import { genSafeVariableName, genArrayFromRaw, @@ -12,6 +13,7 @@ import { import { addComponent, addImports, + addPlugin, addTemplate, addRouteMiddleware, createResolver, @@ -31,6 +33,11 @@ export default defineNuxtModule({ const resolver = createResolver(import.meta.url) nuxt.options.pages = false + // https://github.com/nuxt/nuxt/pull/35794 + if (nuxt.options.experimental.payloadExtraction) { + addPlugin(join(nuxt.options.appDir, 'plugins/payload.client')) + } + addImports({ name: 'definePageMeta', from: resolver.resolve('./runtime/route-composables'), diff --git a/modules/shared/comark-heading-ids.ts b/modules/shared/comark-heading-ids.ts new file mode 100644 index 00000000..7445b966 --- /dev/null +++ b/modules/shared/comark-heading-ids.ts @@ -0,0 +1,61 @@ +import { defineComarkPlugin } from 'comark/parse' +import type { ComarkNode } from 'comark' + +const HEADINGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']) + +function textContent (nodes: ComarkNode[]): string { + let text = '' + for (const node of nodes) { + if (typeof node === 'string') { + text += node + } + else if (Array.isArray(node)) { + text += textContent(node.slice(2) as ComarkNode[]) + } + } + return text +} + +function slugify (text: string) { + const slug = text + .toLowerCase() + .trim() + .replace(/\s+/g, '-') + .replace(/[^\w-]+/g, '') + .replace(/-{2,}/g, '-') + .replace(/^-+|-+$/g, '') + + return /^\d/.test(slug) ? `_${slug}` : slug +} + +/** + * Rewrites heading `id`s so anchors match the slugs the site has always + * published. Comark derives its ids from a text extraction that interpolates + * the tag names of inline children (`## 1. Never let an LLM **speak** for you` + * becomes `_1-never-let-an-llm-strong-speak-for-you`) and prefixes nested + * headings with their parent's id. Both would break existing deep links. + */ +export const headingIds = defineComarkPlugin(() => ({ + name: 'heading-ids', + post (state) { + const counts = new Map() + + const walk = (nodes: ComarkNode[]) => { + for (const node of nodes) { + if (!Array.isArray(node)) continue + + const [tag, props, ...children] = node + if (typeof tag === 'string' && HEADINGS.has(tag) && props && typeof props === 'object') { + const slug = slugify(textContent(children as ComarkNode[])) + const count = counts.get(slug) ?? 0 + counts.set(slug, count + 1) + ;(props as Record).id = count > 0 ? `${slug}-${count}` : slug + } + + walk(children as ComarkNode[]) + } + } + + walk(state.tree.nodes) + }, +})) diff --git a/modules/shared/md-transforms.ts b/modules/shared/md-transforms.ts index 25a9f403..5ae026b0 100644 --- a/modules/shared/md-transforms.ts +++ b/modules/shared/md-transforms.ts @@ -16,6 +16,33 @@ export function mdInternalLinks (content: string): string { ) } +const PRESENTATIONAL_TAGS = ['div', 'span', 'p', 'ul', 'ol', 'figure', 'figcaption'] + +/** + * Drop MDC container markers around presentational elements (`::div{.text-xl}` + * … `::`) so the plain-markdown routes serve prose rather than layout syntax. + * Component containers such as `::social-post` are left alone; they are handled + * by the serialisers. + */ +export function mdStripContainers (content: string): string { + const open = new RegExp(`^:{2,}(?:${PRESENTATIONAL_TAGS.join('|')})(?:\\{[^}]*\\})?$`) + const lines = content.split('\n') + const depth: number[] = [] + + return lines.filter(line => { + const trimmed = line.trim() + if (open.test(trimmed)) { + depth.push(trimmed.match(/^:+/)![0].length) + return false + } + if (/^:+$/.test(trimmed) && depth.at(-1) === trimmed.length) { + depth.pop() + return false + } + return true + }).join('\n').replace(/\n{3,}/g, '\n\n') +} + /** Convert residual HTML elements in markdown to their markdown equivalents. */ export function mdCleanHtml (content: string): string { return content diff --git a/nuxt.config.ts b/nuxt.config.ts index 8a4272fe..aec6fdfb 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -19,7 +19,7 @@ export default defineNuxtConfig({ '@nuxtjs/html-validator', '@unocss/nuxt', '@nuxtjs/color-mode', - '@nuxtjs/mdc', + '@comark/nuxt', '@nuxtjs/plausible', '@nuxt/fonts', '@nuxt/scripts', @@ -65,6 +65,13 @@ export default defineNuxtConfig({ }, }, + components: [ + // markdown components are passed explicitly to `` rather + // than registered globally, so they stay out of the client bundle + { path: '~/components/markdown', pathPrefix: false }, + '~/components', + ], + imports: { polyfills: true, }, @@ -85,14 +92,6 @@ export default defineNuxtConfig({ url: 'https://roe.dev', }, - mdc: { - highlight: { - theme: 'material-theme-palenight', - langs: ['js', 'ts', 'json', 'vue', 'css', 'html', 'bash', 'md', 'mdc', 'yaml'], - noApiRoute: true, - }, - }, - runtimeConfig: { atproto: { password: '', diff --git a/package.json b/package.json index 223ec492..23203c29 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "test": "vitest run", "test:types": "nuxt prepare && vue-tsc -b --noEmit", "test:e2e": "playwright test test/e2e", - "test:e2e:update": "docker run --rm --network host -v $(pwd):/work/ -v /tmp/playwright-nm:/work/node_modules -w /work/ -it mcr.microsoft.com/playwright:v1.60.0-noble bash -c 'corepack enable && pnpm i && pnpm playwright test test/e2e --update-snapshots'", + "test:e2e:update": "docker run --rm --network host -v $(pwd):/work/ -v /tmp/playwright-nm:/work/node_modules -w /work/ -it mcr.microsoft.com/playwright:v1.62.0-noble bash -c 'corepack enable && pnpm i && pnpm playwright test test/e2e --update-snapshots'", "postinstall": "nuxt prepare && pnpm simple-git-hooks install", "auth:linkedin": "node --env-file=.env scripts/linkedin-auth.ts", "auth:youtube": "node --env-file=.env scripts/youtube-auth.ts", @@ -32,6 +32,7 @@ "@atproto/api": "^0.20.34", "@atproto/lexicon": "^0.7.7", "@atproto/oauth-client-node": "0.4.9", + "@comark/nuxt": "0.5.1", "@formkit/drag-and-drop": "0.5.3", "@iconify-json/ri": "^1.2.10", "@iconify-json/svg-spinners": "^1.2.4", @@ -42,7 +43,6 @@ "@nuxt/scripts": "^1.3.2", "@nuxtjs/color-mode": "^4.0.1", "@nuxtjs/html-validator": "2.1.0", - "@nuxtjs/mdc": "0.22.2", "@nuxtjs/plausible": "3.0.2", "@takumi-rs/core": "^2.5.2", "@unhead/vue": "3.2.3", @@ -51,6 +51,7 @@ "@unocss/reset": "66.7.5", "@vercel/blob": "^2.6.1", "citty": "^0.2.2", + "comark": "0.5.1", "defu": "^6.1.7", "exsolve": "^1.1.1", "feed": "^6.0.0", @@ -80,6 +81,7 @@ "remark-html": "^16.0.1", "rollup-plugin-node-polyfills": "^0.2.1", "scule": "^1.3.0", + "shiki": "^4.3.1", "std-env": "^4.2.0", "tinyglobby": "^0.2.17", "ufo": "^1.6.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b3926dd..847b0fb6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: '@atproto/oauth-client-node': specifier: 0.4.9 version: 0.4.9 + '@comark/nuxt': + specifier: 0.5.1 + version: 0.5.1(47698e3209970622e9895475e6de637b) '@formkit/drag-and-drop': specifier: 0.5.3 version: 0.5.3 @@ -53,9 +56,6 @@ importers: '@nuxtjs/html-validator': specifier: 2.1.0 version: 2.1.0(magicast@0.5.3)(vitest@4.1.10(@types/node@25.6.0)(happy-dom@20.11.1)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))) - '@nuxtjs/mdc': - specifier: 0.22.2 - version: 0.22.2(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(supports-color@10.2.2)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24))) '@nuxtjs/plausible': specifier: 3.0.2 version: 3.0.2(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24))) @@ -80,6 +80,9 @@ importers: citty: specifier: ^0.2.2 version: 0.2.2 + comark: + specifier: 0.5.1 + version: 0.5.1(shiki@4.3.1) defu: specifier: ^6.1.7 version: 6.1.7 @@ -167,6 +170,9 @@ importers: scule: specifier: ^1.3.0 version: 1.3.0 + shiki: + specifier: ^4.3.1 + version: 4.3.1 std-env: specifier: ^4.2.0 version: 4.2.0 @@ -579,6 +585,26 @@ packages: '@colordx/core@5.4.3': resolution: {integrity: sha512-kIxYSfA5T8HXjav55UaaH/o/cKivF6jCCGIb8eqtcsfI46wsvlSiT8jMDyrl779qLec3c2c2oHBZo4oAhvbjrQ==} + '@comark/nuxt@0.5.1': + resolution: {integrity: sha512-BvXUbzasGRqQ6bWGuRMO0E6KhWXXpv8FpursPHTixTwJxYVa7BFHUVqvq4cfjj5/6VgbXwofvHiawVQV2k33og==} + peerDependencies: + nuxt: ^4.0.0 + + '@comark/vue@0.5.1': + resolution: {integrity: sha512-uz5Oirzg7ruuJJItceWRswAftuMoY17Omge9bsUampmAL/XdI77YrBOozA5DlId+OCX0VXnt1tCCe4c1IrcJ7w==} + peerDependencies: + beautiful-mermaid: ^1.1.3 + katex: ^0.17.0 + shiki: ^4.3.1 + vue: ^3.5.0 + peerDependenciesMeta: + beautiful-mermaid: + optional: true + katex: + optional: true + shiki: + optional: true + '@commitlint/cli@21.2.1': resolution: {integrity: sha512-blsZGe29hJ72VGEFVl72IVYX+1vsfINpjA9yWQA6i7OKD/McGEOXg08sKIRKjFk4JvzhV/9n0l3i6NooPLTNfg==} engines: {node: '>=22.12.0'} @@ -1765,9 +1791,6 @@ packages: '@nuxtjs/html-validator@2.1.0': resolution: {integrity: sha512-ldo8ioSsH3OEumtgwDMokTxlhjgO9FxjJWViAxisq5l/wjvaVX8SYTQ02wjtQcQQPSvS6BwgypAp400RlyFHng==} - '@nuxtjs/mdc@0.22.2': - resolution: {integrity: sha512-bGI/tXOB7iOMY5LBmSICTVE1l2MsNdLnbZDc+zbaeVv6EXz8V7oyJgi+Fe32qWTS+k5cNjAzj90gvlQfJ/RW9g==} - '@nuxtjs/plausible@3.0.2': resolution: {integrity: sha512-6z01a7XbggSmI4CTWCkDDmLHQNm7wob2dx1QnvpIoo+YEV19298+GsuvlBclXVxXSk7op8r8qJpw25xKo8mzQQ==} @@ -2492,10 +2515,6 @@ packages: resolution: {integrity: sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==} engines: {node: '>=20'} - '@shikijs/transformers@4.3.1': - resolution: {integrity: sha512-z6ir0bGDgWcF2FduktEfPgIsdOtIlDiLAjFBgBzE42Q9xHbkkIXZtORHzlLVB71iZP9elEcqKg6keajvOUwE2A==} - engines: {node: '>=20'} - '@shikijs/types@4.3.1': resolution: {integrity: sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==} engines: {node: '>=20'} @@ -2527,10 +2546,6 @@ packages: resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} engines: {node: '>=18'} - '@sindresorhus/is@4.6.0': - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - '@sindresorhus/is@7.2.0': resolution: {integrity: sha512-P1Cz1dWaFfR4IR+U13mqqiGsLFf1KbayybWwdd2vfctdV6hDpUkgCY0nKOLLTMSoRd/jJNjtbqzf13K8DCCXQw==} engines: {node: '>=18'} @@ -2669,9 +2684,15 @@ packages: '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -2681,9 +2702,6 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} - '@types/unist@2.0.11': - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -3532,10 +3550,6 @@ packages: change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -3545,9 +3559,6 @@ packages: character-entities@2.0.2: resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - chokidar@5.0.0: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} @@ -3600,6 +3611,20 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + comark@0.5.1: + resolution: {integrity: sha512-RRRmUaEc6tokYJhgIGHrl8+pUt3kY1BxMnbRrxMxkCk2RcPcrilq9OmmPWIO7zuUIF7qLLRCCQz+wPuMg7Vz9w==} + peerDependencies: + beautiful-mermaid: ^1.1.3 + katex: ^0.17.0 + shiki: ^4.3.1 + peerDependenciesMeta: + beautiful-mermaid: + optional: true + katex: + optional: true + shiki: + optional: true + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -3866,9 +3891,6 @@ packages: destr@2.0.5: resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} - detab@3.0.2: - resolution: {integrity: sha512-7Bp16Bk8sk0Y6gdXiCtnpGbghn8atnTJdd/82aWvS5ESnlcNvgUc10U2NYS0PAiDSGjWiI8qs/Cv1b2uSGdQ8w==} - detect-indent@7.0.2: resolution: {integrity: sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A==} engines: {node: '>=12.20'} @@ -3909,16 +3931,32 @@ packages: dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + dom-serializer@3.1.1: + resolution: {integrity: sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==} + engines: {node: '>=20.19.0'} + domelementtype@2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + domelementtype@3.0.0: + resolution: {integrity: sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==} + engines: {node: '>=20.19.0'} + domhandler@5.0.3: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} + domhandler@6.0.1: + resolution: {integrity: sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==} + engines: {node: '>=20.19.0'} + domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + domutils@4.0.2: + resolution: {integrity: sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==} + engines: {node: '>=20.19.0'} + dot-prop@10.1.0: resolution: {integrity: sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==} engines: {node: '>=20'} @@ -3960,12 +3998,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - emojilib@2.4.0: - resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} - - emoticon@4.1.0: - resolution: {integrity: sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==} - encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -3978,10 +4010,6 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} - entities@7.0.1: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} @@ -4351,11 +4379,6 @@ packages: flat-cache@6.1.23: resolution: {integrity: sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==} - flat@6.0.1: - resolution: {integrity: sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==} - engines: {node: '>=18'} - hasBin: true - flatted@3.4.2: resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} @@ -4466,9 +4489,6 @@ packages: resolution: {integrity: sha512-r+mvuDjrjMpsdw46Kmeydb8bdHm7wOKw8wNBtTndkjbPjgAp5oUJUxRE76wZFknxIPokfWvep2qSXK37aXE6zg==} hasBin: true - github-slugger@2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -4609,63 +4629,15 @@ packages: resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} engines: {node: '>= 0.4'} - hast-util-embedded@3.0.0: - resolution: {integrity: sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==} - - hast-util-format@1.1.0: - resolution: {integrity: sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==} - - hast-util-from-parse5@8.0.3: - resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} - - hast-util-has-property@3.0.0: - resolution: {integrity: sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==} - - hast-util-heading-rank@3.0.0: - resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} - - hast-util-is-body-ok-link@3.0.1: - resolution: {integrity: sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==} - - hast-util-is-element@3.0.0: - resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} - - hast-util-minify-whitespace@1.0.1: - resolution: {integrity: sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==} - - hast-util-parse-selector@4.0.0: - resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} - - hast-util-phrasing@3.0.1: - resolution: {integrity: sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==} - - hast-util-raw@9.1.0: - resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} - hast-util-sanitize@5.0.2: resolution: {integrity: sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==} hast-util-to-html@9.0.5: resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} - hast-util-to-mdast@10.1.2: - resolution: {integrity: sha512-FiCRI7NmOvM4y+f5w32jPRzcxDIz+PUqDwEqn1A+1q2cdp3B8Gx7aVrXORdOKjMNDQsD1ogOr896+0jJHW1EFQ==} - - hast-util-to-parse5@8.0.1: - resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} - - hast-util-to-string@3.0.1: - resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==} - - hast-util-to-text@4.0.2: - resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} - hast-util-whitespace@3.0.0: resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - hastscript@9.0.1: - resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} - hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} @@ -4711,12 +4683,13 @@ packages: html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - html-whitespace-sensitive-tag-names@3.0.1: - resolution: {integrity: sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==} - htmlparser2@10.1.0: resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + htmlparser2@12.0.0: + resolution: {integrity: sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==} + engines: {node: '>=20.19.0'} + htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} @@ -4804,16 +4777,6 @@ packages: iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} - is-absolute-url@4.0.1: - resolution: {integrity: sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - - is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -4829,9 +4792,6 @@ packages: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} - is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - is-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -4858,9 +4818,6 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - is-in-ssh@1.0.0: resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==} engines: {node: '>=20'} @@ -5136,6 +5093,9 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + listhen@1.10.0: resolution: {integrity: sha512-kfz4C0OrC6IpaVMtYDJtf6PFjurxe9NBBoDAh/o2p587INryFOO4DQ9OetbCdDrWFt1m1CJKvYrzkGsuPHw8nQ==} hasBin: true @@ -5210,8 +5170,8 @@ packages: magicast@0.5.3: resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} - markdown-table@3.0.4: - resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + markdown-exit@1.1.0-beta.2: + resolution: {integrity: sha512-8CzMGVlFZ4DEfnc8KU+4ycUW2SIOuiXqCHD7z51ecVEi/weyc0f2ylQbCm4KoKuVlTZSuMUMnWT0hTyquZ7anQ==} marky@1.3.0: resolution: {integrity: sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==} @@ -5227,30 +5187,9 @@ packages: mathml-tag-names@4.0.0: resolution: {integrity: sha512-aa6AU2Pcx0VP/XWnh8IGL0SYSgQHDT6Ucror2j2mXeFAlN3ahaNs8EZtG1YiticMkSLj3Gt6VPFfZogt7G5iFQ==} - mdast-util-find-and-replace@3.0.2: - resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} - mdast-util-from-markdown@2.0.3: resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} - mdast-util-gfm-autolink-literal@2.0.1: - resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} - - mdast-util-gfm-footnote@2.1.0: - resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} - - mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} - - mdast-util-gfm-table@2.0.0: - resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} - - mdast-util-gfm-task-list-item@2.0.0: - resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} - - mdast-util-gfm@3.1.0: - resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} - mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} @@ -5269,6 +5208,9 @@ packages: mdn-data@2.27.1: resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + mdurl@2.1.0: + resolution: {integrity: sha512-1+HBaOx0zi/dQWht8rNv9MYf9qqpqL/kxI0hXImU6Y547zM6Sni8BQibt7ifgMcYtQg41ao3Ivd6cnSM86inpg==} + mediabunny@1.51.0: resolution: {integrity: sha512-u327374xU8Ho0gCaMII7fUK8t0PnqkabCox1k8uUwvgvGb9o6YQGZEG2Qr4DTe7nTMpzfL7ukgnHDvDROySZ+Q==} @@ -5286,27 +5228,6 @@ packages: micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} - micromark-extension-gfm-autolink-literal@2.1.0: - resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} - - micromark-extension-gfm-footnote@2.1.0: - resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - - micromark-extension-gfm-strikethrough@2.1.0: - resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - - micromark-extension-gfm-table@2.1.1: - resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} - - micromark-extension-gfm-tagfilter@2.0.0: - resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} - - micromark-extension-gfm-task-list-item@2.1.0: - resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} - - micromark-extension-gfm@3.0.0: - resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - micromark-factory-destination@2.0.1: resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} @@ -5506,10 +5427,6 @@ packages: engines: {node: '>=10.5.0'} deprecated: Use your platform's native DOMException instead - node-emoji@2.2.0: - resolution: {integrity: sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==} - engines: {node: '>=18'} - node-fetch-native@1.6.7: resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} @@ -5776,9 +5693,6 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-entities@4.0.2: - resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - parse-imports-exports@0.2.4: resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} @@ -5789,12 +5703,6 @@ packages: parse-statements@1.0.11: resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} - parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - - parse5@8.0.1: - resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} - parseley@0.13.1: resolution: {integrity: sha512-uNBJZzmb60l6p6VWLTmevizNAGnE0xoSf1n0B4q3ntegDNzcS68NRCcBDZTcyXHxt2XhBChsCuqj4M+nChvE/A==} @@ -6118,6 +6026,10 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -6196,46 +6108,12 @@ packages: resolution: {integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==} hasBin: true - rehype-external-links@3.0.0: - resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==} - - rehype-minify-whitespace@6.0.2: - resolution: {integrity: sha512-Zk0pyQ06A3Lyxhe9vGtOtzz3Z0+qZ5+7icZ/PL/2x1SHPbKao5oB/g/rlc6BCTajqBb33JcOe71Ye1oFsuYbnw==} - - rehype-raw@7.0.0: - resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} - - rehype-remark@10.0.1: - resolution: {integrity: sha512-EmDndlb5NVwXGfUa4c9GPK+lXeItTilLhE6ADSaQuHr4JUlKw9MidzGzx4HpqZrNCt6vnHmEifXQiiA+CEnjYQ==} - - rehype-slug@6.0.0: - resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} - - rehype-sort-attribute-values@5.0.1: - resolution: {integrity: sha512-lU3ABJO5frbUgV132YS6SL7EISf//irIm9KFMaeu5ixHfgWf6jhe+09Uf/Ef8pOYUJWKOaQJDRJGCXs6cNsdsQ==} - - rehype-sort-attributes@5.0.1: - resolution: {integrity: sha512-Bxo+AKUIELcnnAZwJDt5zUDDRpt4uzhfz9d0PVGhcxYWsbFj5Cv35xuWxu5r1LeYNFNhgGqsr9Q2QiIOM/Qctg==} - - remark-emoji@5.0.2: - resolution: {integrity: sha512-IyIqGELcyK5AVdLFafoiNww+Eaw/F+rGrNSXoKucjo95uL267zrddgxGM83GN1wFIb68pyDuAsY3m5t2Cav1pQ==} - engines: {node: '>=18'} - - remark-gfm@4.0.1: - resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} - remark-html@16.0.1: resolution: {integrity: sha512-B9JqA5i0qZe0Nsf49q3OXyGvyXuZFDzAP2iOFLEumymuYJITVpiH1IgsTEwTpdptDmZlMDMWeDmSawdaJIGCXQ==} - remark-mdc@3.11.1: - resolution: {integrity: sha512-bjH7Q1OO1BSXVPmUxYIrGH2dUAZkizNY3i9WJUEcIFLowZAEjLTT7fUAH2vH0Tpkeh+/MrzwFFmeWcZ66QLh7A==} - remark-parse@11.0.0: resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - remark-rehype@11.1.2: - resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} - remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} @@ -6461,10 +6339,6 @@ packages: peerDependencies: vue: ^3.5.30 - skin-tone@2.0.0: - resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} - engines: {node: '>=8'} - slash@5.1.0: resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} engines: {node: '>=14.16'} @@ -6807,9 +6681,6 @@ packages: trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - trim-trailing-lines@2.1.0: - resolution: {integrity: sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==} - trough@2.2.0: resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} @@ -6846,6 +6717,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + ufo@1.6.4: resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} @@ -6917,10 +6791,6 @@ packages: vite: optional: true - unicode-emoji-modifier-base@1.0.0: - resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} - engines: {node: '>=4'} - unicode-segmenter@0.14.5: resolution: {integrity: sha512-jHGmj2LUuqDcX3hqY12Ql+uhUTn8huuxNZGq7GvtF6bSybzH3aFgedYu/KTzQStEgt1Ra2F3HxadNXsNjb3m3g==} @@ -6950,12 +6820,6 @@ packages: rolldown: optional: true - unist-builder@4.0.0: - resolution: {integrity: sha512-wmRFnH+BLpZnTKpc5L7O67Kac89s9HMrtELpnNaE6TAobq5DTZZs5YaTQfAZBA9bFPECx2uVAPO31c+GVug8mg==} - - unist-util-find-after@5.0.0: - resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} - unist-util-is@6.0.1: resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} @@ -7142,9 +7006,6 @@ packages: resolution: {integrity: sha512-6M8R2xSKplkQ+0mAm07IMh548GLLPUnRQZJCCe/W4rfk/SXW2bs8ZJSWa5kjdIdsx3hLG5oLWROJ4+N5hpX08g==} engines: {node: '>=18.12.0'} - vfile-location@5.0.3: - resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} - vfile-message@4.0.3: resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} @@ -7354,9 +7215,6 @@ packages: resolution: {integrity: sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==} engines: {node: '>=10.13.0'} - web-namespaces@2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -7941,6 +7799,30 @@ snapshots: '@colordx/core@5.4.3': {} + '@comark/nuxt@0.5.1(47698e3209970622e9895475e6de637b)': + dependencies: + '@comark/vue': 0.5.1(shiki@4.3.1)(vue@3.5.40(typescript@6.0.3)) + '@nuxt/kit': 4.5.1(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24))) + comark: 0.5.1(shiki@4.3.1) + nuxt: 4.5.1(@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0(supports-color@10.2.2)))(@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.0(supports-color@10.2.2)))(@parcel/watcher@2.5.6)(@types/node@25.6.0)(@vercel/blob@2.6.1)(@vue/compiler-sfc@3.5.40)(db0@0.3.4)(esbuild@0.28.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(ioredis@5.10.1(supports-color@10.2.2))(lightningcss@1.32.0)(magicast@0.5.3)(meow@14.1.0)(optionator@0.9.4)(oxc-parser@0.131.0)(rollup-plugin-visualizer@7.0.1(rolldown@1.2.0)(rollup@4.62.3))(rollup@4.62.3)(srvx@0.11.22)(stylelint@17.14.1(supports-color@10.2.2)(typescript@6.0.3))(supports-color@10.2.2)(terser@5.49.0)(typescript@6.0.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(vue-tsc@3.3.8(typescript@6.0.3))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24))(yaml@2.9.0) + transitivePeerDependencies: + - beautiful-mermaid + - katex + - magic-string + - magicast + - oxc-parser + - rolldown + - shiki + - unplugin + - vue + + '@comark/vue@0.5.1(shiki@4.3.1)(vue@3.5.40(typescript@6.0.3))': + dependencies: + comark: 0.5.1(shiki@4.3.1) + vue: 3.5.40(typescript@6.0.3) + optionalDependencies: + shiki: 4.3.1 + '@commitlint/cli@21.2.1(@types/node@25.6.0)(conventional-commits-parser@7.1.1)(typescript@6.0.3)': dependencies: '@commitlint/config-conventional': 21.2.0 @@ -9450,60 +9332,6 @@ snapshots: - magicast - vitest - '@nuxtjs/mdc@0.22.2(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(supports-color@10.2.2)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24)))': - dependencies: - '@nuxt/kit': 4.5.1(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24))) - '@shikijs/core': 4.3.1 - '@shikijs/engine-javascript': 4.3.1 - '@shikijs/langs': 4.3.1 - '@shikijs/themes': 4.3.1 - '@shikijs/transformers': 4.3.1 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@vue/compiler-core': 3.5.40 - consola: 3.4.2 - debug: 4.4.3(supports-color@10.2.2) - defu: 6.1.7 - destr: 2.0.5 - detab: 3.0.2 - github-slugger: 2.0.0 - hast-util-format: 1.1.0 - hast-util-to-mdast: 10.1.2 - hast-util-to-string: 3.0.1 - mdast-util-to-hast: 13.2.1 - micromark-util-sanitize-uri: 2.0.1 - parse5: 8.0.1 - pathe: 2.0.3 - property-information: 7.2.0 - rehype-external-links: 3.0.0 - rehype-minify-whitespace: 6.0.2 - rehype-raw: 7.0.0 - rehype-remark: 10.0.1 - rehype-slug: 6.0.0 - rehype-sort-attribute-values: 5.0.1 - rehype-sort-attributes: 5.0.1 - remark-emoji: 5.0.2 - remark-gfm: 4.0.1(supports-color@10.2.2) - remark-mdc: 3.11.1(supports-color@10.2.2) - remark-parse: 11.0.0(supports-color@10.2.2) - remark-rehype: 11.1.2 - remark-stringify: 11.0.0 - scule: 1.3.0 - shiki: 4.3.1 - ufo: 1.6.4 - unified: 11.0.5 - unist-builder: 4.0.0 - unist-util-visit: 5.1.0 - unwasm: 0.5.3 - vfile: 6.0.3 - transitivePeerDependencies: - - magic-string - - magicast - - oxc-parser - - rolldown - - supports-color - - unplugin - '@nuxtjs/plausible@3.0.2(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24)))': dependencies: '@nuxt/kit': 4.5.1(magic-string@1.1.0)(magicast@0.5.3)(oxc-parser@0.131.0)(rolldown@1.2.0)(unplugin@3.3.0(esbuild@0.28.0)(rolldown@1.2.0)(rollup@4.62.3)(vite@8.1.5(@types/node@25.6.0)(esbuild@0.28.0)(jiti@2.7.0)(terser@5.49.0)(yaml@2.9.0))(webpack@5.105.2(cssnano@8.0.2(postcss@8.5.24))(csso@5.0.5)(esbuild@0.28.0)(lightningcss@1.32.0)(postcss@8.5.24))) @@ -9971,11 +9799,6 @@ snapshots: dependencies: '@shikijs/types': 4.3.1 - '@shikijs/transformers@4.3.1': - dependencies: - '@shikijs/core': 4.3.1 - '@shikijs/types': 4.3.1 - '@shikijs/types@4.3.1': dependencies: '@shikijs/vscode-textmate': 10.0.2 @@ -10002,8 +9825,6 @@ snapshots: '@sindresorhus/base62@1.0.0': {} - '@sindresorhus/is@4.6.0': {} - '@sindresorhus/is@7.2.0': {} '@sindresorhus/merge-streams@4.0.0': {} @@ -10113,10 +9934,14 @@ snapshots: '@types/json-schema@7.0.15': {} + '@types/linkify-it@5.0.0': {} + '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 + '@types/mdurl@2.0.0': {} + '@types/ms@2.1.0': {} '@types/node@25.6.0': @@ -10125,8 +9950,6 @@ snapshots: '@types/resolve@1.20.2': {} - '@types/unist@2.0.11': {} - '@types/unist@3.0.3': {} '@types/web-bluetooth@0.0.21': {} @@ -11206,16 +11029,12 @@ snapshots: change-case@5.4.4: {} - char-regex@1.0.2: {} - character-entities-html4@2.1.0: {} character-entities-legacy@3.0.0: {} character-entities@2.0.2: {} - character-reference-invalid@2.0.1: {} - chokidar@5.0.0: dependencies: readdirp: 5.0.0 @@ -11265,6 +11084,15 @@ snapshots: colorette@2.0.20: {} + comark@0.5.1(shiki@4.3.1): + dependencies: + entities: 8.0.0 + htmlparser2: 12.0.0 + js-yaml: 5.2.2 + markdown-exit: 1.1.0-beta.2 + optionalDependencies: + shiki: 4.3.1 + comma-separated-tokens@2.0.3: {} commander@10.0.1: {} @@ -11488,8 +11316,6 @@ snapshots: destr@2.0.5: {} - detab@3.0.2: {} - detect-indent@7.0.2: {} detect-libc@2.1.2: {} @@ -11541,18 +11367,36 @@ snapshots: domhandler: 5.0.3 entities: 4.5.0 + dom-serializer@3.1.1: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + entities: 8.0.0 + domelementtype@2.3.0: {} + domelementtype@3.0.0: {} + domhandler@5.0.3: dependencies: domelementtype: 2.3.0 + domhandler@6.0.1: + dependencies: + domelementtype: 3.0.0 + domutils@3.2.2: dependencies: dom-serializer: 2.0.0 domelementtype: 2.3.0 domhandler: 5.0.3 + domutils@4.0.2: + dependencies: + dom-serializer: 3.1.1 + domelementtype: 3.0.0 + domhandler: 6.0.1 + dot-prop@10.1.0: dependencies: type-fest: 5.6.0 @@ -11590,10 +11434,6 @@ snapshots: emoji-regex@9.2.2: {} - emojilib@2.4.0: {} - - emoticon@4.1.0: {} - encodeurl@2.0.0: {} enhanced-resolve@5.24.3: @@ -11603,8 +11443,6 @@ snapshots: entities@4.5.0: {} - entities@6.0.1: {} - entities@7.0.1: {} entities@8.0.0: {} @@ -12080,8 +11918,6 @@ snapshots: flatted: 3.4.2 hookified: 1.15.1 - flat@6.0.1: {} - flatted@3.4.2: {} fnv1a-64@0.1.2: {} @@ -12225,8 +12061,6 @@ snapshots: giget@3.3.1: {} - github-slugger@2.0.0: {} - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -12397,84 +12231,6 @@ snapshots: dependencies: function-bind: 1.1.2 - hast-util-embedded@3.0.0: - dependencies: - '@types/hast': 3.0.4 - hast-util-is-element: 3.0.0 - - hast-util-format@1.1.0: - dependencies: - '@types/hast': 3.0.4 - hast-util-embedded: 3.0.0 - hast-util-minify-whitespace: 1.0.1 - hast-util-phrasing: 3.0.1 - hast-util-whitespace: 3.0.0 - html-whitespace-sensitive-tag-names: 3.0.1 - unist-util-visit-parents: 6.0.2 - - hast-util-from-parse5@8.0.3: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - devlop: 1.1.0 - hastscript: 9.0.1 - property-information: 7.2.0 - vfile: 6.0.3 - vfile-location: 5.0.3 - web-namespaces: 2.0.1 - - hast-util-has-property@3.0.0: - dependencies: - '@types/hast': 3.0.4 - - hast-util-heading-rank@3.0.0: - dependencies: - '@types/hast': 3.0.4 - - hast-util-is-body-ok-link@3.0.1: - dependencies: - '@types/hast': 3.0.4 - - hast-util-is-element@3.0.0: - dependencies: - '@types/hast': 3.0.4 - - hast-util-minify-whitespace@1.0.1: - dependencies: - '@types/hast': 3.0.4 - hast-util-embedded: 3.0.0 - hast-util-is-element: 3.0.0 - hast-util-whitespace: 3.0.0 - unist-util-is: 6.0.1 - - hast-util-parse-selector@4.0.0: - dependencies: - '@types/hast': 3.0.4 - - hast-util-phrasing@3.0.1: - dependencies: - '@types/hast': 3.0.4 - hast-util-embedded: 3.0.0 - hast-util-has-property: 3.0.0 - hast-util-is-body-ok-link: 3.0.1 - hast-util-is-element: 3.0.0 - - hast-util-raw@9.1.0: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - '@ungap/structured-clone': 1.3.0 - hast-util-from-parse5: 8.0.3 - hast-util-to-parse5: 8.0.1 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.1 - parse5: 7.3.0 - unist-util-position: 5.0.0 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - hast-util-sanitize@5.0.2: dependencies: '@types/hast': 3.0.4 @@ -12495,56 +12251,10 @@ snapshots: stringify-entities: 4.0.4 zwitch: 2.0.4 - hast-util-to-mdast@10.1.2: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.0 - hast-util-phrasing: 3.0.1 - hast-util-to-html: 9.0.5 - hast-util-to-text: 4.0.2 - hast-util-whitespace: 3.0.0 - mdast-util-phrasing: 4.1.0 - mdast-util-to-hast: 13.2.1 - mdast-util-to-string: 4.0.0 - rehype-minify-whitespace: 6.0.2 - trim-trailing-lines: 2.1.0 - unist-util-position: 5.0.0 - unist-util-visit: 5.1.0 - - hast-util-to-parse5@8.0.1: - dependencies: - '@types/hast': 3.0.4 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - property-information: 7.2.0 - space-separated-tokens: 2.0.2 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - - hast-util-to-string@3.0.1: - dependencies: - '@types/hast': 3.0.4 - - hast-util-to-text@4.0.2: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - hast-util-is-element: 3.0.0 - unist-util-find-after: 5.0.0 - hast-util-whitespace@3.0.0: dependencies: '@types/hast': 3.0.4 - hastscript@9.0.1: - dependencies: - '@types/hast': 3.0.4 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 4.0.0 - property-information: 7.2.0 - space-separated-tokens: 2.0.2 - hookable@5.5.3: {} hookable@6.1.1: {} @@ -12580,8 +12290,6 @@ snapshots: html-void-elements@3.0.0: {} - html-whitespace-sensitive-tag-names@3.0.1: {} - htmlparser2@10.1.0: dependencies: domelementtype: 2.3.0 @@ -12589,6 +12297,13 @@ snapshots: domutils: 3.2.2 entities: 7.0.1 + htmlparser2@12.0.0: + dependencies: + domelementtype: 3.0.0 + domhandler: 6.0.1 + domutils: 4.0.2 + entities: 8.0.0 + htmlparser2@8.0.2: dependencies: domelementtype: 2.3.0 @@ -12723,15 +12438,6 @@ snapshots: iron-webcrypto@1.2.1: {} - is-absolute-url@4.0.1: {} - - is-alphabetical@2.0.1: {} - - is-alphanumerical@2.0.1: - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - is-arrayish@0.2.1: {} is-buffer@2.0.5: {} @@ -12744,8 +12450,6 @@ snapshots: dependencies: hasown: 2.0.3 - is-decimal@2.0.1: {} - is-docker@2.2.1: {} is-docker@3.0.0: {} @@ -12760,8 +12464,6 @@ snapshots: dependencies: is-extglob: 2.1.1 - is-hexadecimal@2.0.1: {} - is-in-ssh@1.0.0: {} is-inside-container@1.0.0: @@ -12986,6 +12688,10 @@ snapshots: lines-and-columns@1.2.4: {} + linkify-it@5.0.2: + dependencies: + uc.micro: 2.1.0 + listhen@1.10.0(srvx@0.11.22): dependencies: '@parcel/watcher': 2.5.6 @@ -13096,7 +12802,15 @@ snapshots: '@babel/types': 7.29.7 source-map-js: 1.2.1 - markdown-table@3.0.4: {} + markdown-exit@1.1.0-beta.2: + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + entities: 7.0.1 + linkify-it: 5.0.2 + mdurl: 2.1.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 marky@1.3.0: {} @@ -13110,13 +12824,6 @@ snapshots: mathml-tag-names@4.0.0: {} - mdast-util-find-and-replace@3.0.2: - dependencies: - '@types/mdast': 4.0.4 - escape-string-regexp: 5.0.0 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - mdast-util-from-markdown@2.0.3(supports-color@10.2.2): dependencies: '@types/mdast': 4.0.4 @@ -13134,63 +12841,6 @@ snapshots: transitivePeerDependencies: - supports-color - mdast-util-gfm-autolink-literal@2.0.1: - dependencies: - '@types/mdast': 4.0.4 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.2 - micromark-util-character: 2.1.1 - - mdast-util-gfm-footnote@2.1.0(supports-color@10.2.2): - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3(supports-color@10.2.2) - mdast-util-to-markdown: 2.1.2 - micromark-util-normalize-identifier: 2.0.1 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-strikethrough@2.0.0(supports-color@10.2.2): - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.3(supports-color@10.2.2) - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-table@2.0.0(supports-color@10.2.2): - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.3(supports-color@10.2.2) - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-task-list-item@2.0.0(supports-color@10.2.2): - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3(supports-color@10.2.2) - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm@3.1.0(supports-color@10.2.2): - dependencies: - mdast-util-from-markdown: 2.0.3(supports-color@10.2.2) - mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.1.0(supports-color@10.2.2) - mdast-util-gfm-strikethrough: 2.0.0(supports-color@10.2.2) - mdast-util-gfm-table: 2.0.0(supports-color@10.2.2) - mdast-util-gfm-task-list-item: 2.0.0(supports-color@10.2.2) - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - mdast-util-phrasing@4.1.0: dependencies: '@types/mdast': 4.0.4 @@ -13228,6 +12878,8 @@ snapshots: mdn-data@2.27.1: {} + mdurl@2.1.0: {} + mediabunny@1.51.0: dependencies: '@types/dom-mediacapture-transform': 0.1.11 @@ -13258,64 +12910,6 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - micromark-extension-gfm-autolink-literal@2.1.0: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-footnote@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-strikethrough@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-table@2.1.1: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-tagfilter@2.0.0: - dependencies: - micromark-util-types: 2.0.2 - - micromark-extension-gfm-task-list-item@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm@3.0.0: - dependencies: - micromark-extension-gfm-autolink-literal: 2.1.0 - micromark-extension-gfm-footnote: 2.1.0 - micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.1 - micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.1.0 - micromark-util-combine-extensions: 2.0.1 - micromark-util-types: 2.0.2 - micromark-factory-destination@2.0.1: dependencies: micromark-util-character: 2.1.1 @@ -13650,13 +13244,6 @@ snapshots: node-domexception@1.0.0: {} - node-emoji@2.2.0: - dependencies: - '@sindresorhus/is': 4.6.0 - char-regex: 1.0.2 - emojilib: 2.4.0 - skin-tone: 2.0.0 - node-fetch-native@1.6.7: {} node-fetch@2.7.0: @@ -14186,16 +13773,6 @@ snapshots: dependencies: callsites: 3.1.0 - parse-entities@4.0.2: - dependencies: - '@types/unist': 2.0.11 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.3.0 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - parse-imports-exports@0.2.4: dependencies: parse-statements: 1.0.11 @@ -14209,14 +13786,6 @@ snapshots: parse-statements@1.0.11: {} - parse5@7.3.0: - dependencies: - entities: 6.0.1 - - parse5@8.0.1: - dependencies: - entities: 8.0.0 - parseley@0.13.1: dependencies: leac: 0.7.0 @@ -14515,6 +14084,8 @@ snapshots: proto-list@1.2.4: {} + punycode.js@2.3.1: {} + punycode@2.3.1: {} qified@0.10.1: @@ -14595,72 +14166,6 @@ snapshots: dependencies: jsesc: 3.1.0 - rehype-external-links@3.0.0: - dependencies: - '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.3.0 - hast-util-is-element: 3.0.0 - is-absolute-url: 4.0.1 - space-separated-tokens: 2.0.2 - unist-util-visit: 5.1.0 - - rehype-minify-whitespace@6.0.2: - dependencies: - '@types/hast': 3.0.4 - hast-util-minify-whitespace: 1.0.1 - - rehype-raw@7.0.0: - dependencies: - '@types/hast': 3.0.4 - hast-util-raw: 9.1.0 - vfile: 6.0.3 - - rehype-remark@10.0.1: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - hast-util-to-mdast: 10.1.2 - unified: 11.0.5 - vfile: 6.0.3 - - rehype-slug@6.0.0: - dependencies: - '@types/hast': 3.0.4 - github-slugger: 2.0.0 - hast-util-heading-rank: 3.0.0 - hast-util-to-string: 3.0.1 - unist-util-visit: 5.1.0 - - rehype-sort-attribute-values@5.0.1: - dependencies: - '@types/hast': 3.0.4 - hast-util-is-element: 3.0.0 - unist-util-visit: 5.1.0 - - rehype-sort-attributes@5.0.1: - dependencies: - '@types/hast': 3.0.4 - unist-util-visit: 5.1.0 - - remark-emoji@5.0.2: - dependencies: - '@types/mdast': 4.0.4 - emoticon: 4.1.0 - mdast-util-find-and-replace: 3.0.2 - node-emoji: 2.2.0 - unified: 11.0.5 - - remark-gfm@4.0.1(supports-color@10.2.2): - dependencies: - '@types/mdast': 4.0.4 - mdast-util-gfm: 3.1.0(supports-color@10.2.2) - micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0(supports-color@10.2.2) - remark-stringify: 11.0.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - remark-html@16.0.1: dependencies: '@types/mdast': 4.0.4 @@ -14669,29 +14174,6 @@ snapshots: mdast-util-to-hast: 13.2.1 unified: 11.0.5 - remark-mdc@3.11.1(supports-color@10.2.2): - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - flat: 6.0.1 - mdast-util-from-markdown: 2.0.3(supports-color@10.2.2) - mdast-util-to-markdown: 2.1.2 - micromark: 4.0.2(supports-color@10.2.2) - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-factory-whitespace: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-types: 2.0.2 - parse-entities: 4.0.2 - scule: 1.3.0 - stringify-entities: 4.0.4 - unified: 11.0.5 - unist-util-visit: 5.1.0 - unist-util-visit-parents: 6.0.2 - yaml: 2.9.0 - transitivePeerDependencies: - - supports-color - remark-parse@11.0.0(supports-color@10.2.2): dependencies: '@types/mdast': 4.0.4 @@ -14701,14 +14183,6 @@ snapshots: transitivePeerDependencies: - supports-color - remark-rehype@11.1.2: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.1 - unified: 11.0.5 - vfile: 6.0.3 - remark-stringify@11.0.0: dependencies: '@types/mdast': 4.0.4 @@ -15022,10 +14496,6 @@ snapshots: ufo: 1.6.4 vue: 3.5.40(typescript@6.0.3) - skin-tone@2.0.0: - dependencies: - unicode-emoji-modifier-base: 1.0.0 - slash@5.1.0: {} slice-ansi@4.0.0: @@ -15357,8 +14827,6 @@ snapshots: trim-lines@3.0.1: {} - trim-trailing-lines@2.1.0: {} - trough@2.2.0: {} ts-api-utils@2.5.0(typescript@6.0.3): @@ -15383,6 +14851,8 @@ snapshots: typescript@6.0.3: {} + uc.micro@2.1.0: {} + ufo@1.6.4: {} ultrahtml@1.7.0: {} @@ -15465,8 +14935,6 @@ snapshots: - unloader - webpack - unicode-emoji-modifier-base@1.0.0: {} - unicode-segmenter@0.14.5: {} unicorn-magic@0.3.0: {} @@ -15518,15 +14986,6 @@ snapshots: - vite - webpack - unist-builder@4.0.0: - dependencies: - '@types/unist': 3.0.3 - - unist-util-find-after@5.0.0: - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.1 - unist-util-is@6.0.1: dependencies: '@types/unist': 3.0.3 @@ -15706,11 +15165,6 @@ snapshots: verkit@0.2.0: {} - vfile-location@5.0.3: - dependencies: - '@types/unist': 3.0.3 - vfile: 6.0.3 - vfile-message@4.0.3: dependencies: '@types/unist': 3.0.3 @@ -15943,8 +15397,6 @@ snapshots: dependencies: graceful-fs: 4.2.11 - web-namespaces@2.0.1: {} - web-streams-polyfill@3.3.3: {} webidl-conversions@3.0.1: {} diff --git a/test/unit/behaviour.spec.ts b/test/unit/behaviour.spec.ts index ebfa52f0..258cb975 100644 --- a/test/unit/behaviour.spec.ts +++ b/test/unit/behaviour.spec.ts @@ -41,4 +41,30 @@ describe('site behaviour', { timeout: 10000 }, () => { expect(logs).toMatchInlineSnapshot(`[]`) await page.close() }) + + it('renders blog posts navigated to on the client', async () => { + const errors: string[] = [] + const page = await createPage() + await page.route('**/api/discover-bluesky-post', route => + route.fulfill({ json: { uri: null } }), + ) + page.on('pageerror', error => errors.push(error.message)) + + await page.goto(url('/blog/')) + await page.waitForLoadState('networkidle') + + const link = page.locator('main a[href^="/blog/"]').first() + const title = await link.getAttribute('title') + + // the post metadata is only in the route payload, so a client-side + // navigation that fails to load it renders nothing at all + const rendered = page.locator('h1', { hasText: title! }).waitFor() + await link.click() + await Promise.race([rendered, page.waitForEvent('pageerror')]).catch(() => {}) + + expect(errors).toStrictEqual([]) + expect(await page.locator('h1').textContent()).toBe(title) + expect(await page.locator('section p').count()).toBeGreaterThan(0) + await page.close() + }) }) diff --git a/test/unit/bundle.spec.ts b/test/unit/bundle.spec.ts index a89e7faa..50a755fa 100644 --- a/test/unit/bundle.spec.ts +++ b/test/unit/bundle.spec.ts @@ -8,6 +8,13 @@ import { afterAll, beforeAll, describe, expect, it } from 'vitest' import { glob as globby } from 'tinyglobby' import { join } from 'pathe' +/** + * Prebuilt native binaries are resolved for whichever platform the build runs + * on, so their names and sizes can't be snapshotted. + */ +const NATIVE_BINARY_RE = /(?:linux|darwin|win32)-(?:arm64|x64)/ +const NATIVE_BINARY_GLOB = '!node_modules/**/*{linux,darwin,win32}-{arm64,x64}*/**' + describe('project sizes', () => { const rootDir = fileURLToPath(new URL('../..', import.meta.url)) const publicDir = join(rootDir, '.output/public') @@ -55,38 +62,11 @@ describe('project sizes', () => { expect .soft(roundToKilobytes(stats.client.totalBytes)) - .toMatchInlineSnapshot(`"284k"`) + .toMatchInlineSnapshot(`"263k"`) expect.soft(stats.client.files.map(f => f.replace(/\..*\.js/, '.js')).sort()) .toMatchInlineSnapshot(` [ "_nuxt/BlueskyComments.js", - "_nuxt/CalSchedule.js", - "_nuxt/ProseA.js", - "_nuxt/ProseBlockquote.js", - "_nuxt/ProseCode.js", - "_nuxt/ProseEm.js", - "_nuxt/ProseH1.js", - "_nuxt/ProseH2.js", - "_nuxt/ProseH3.js", - "_nuxt/ProseH4.js", - "_nuxt/ProseH5.js", - "_nuxt/ProseH6.js", - "_nuxt/ProseHr.js", - "_nuxt/ProseImg.js", - "_nuxt/ProseLi.js", - "_nuxt/ProseOl.js", - "_nuxt/ProseP.js", - "_nuxt/ProsePre.js", - "_nuxt/ProseScript.js", - "_nuxt/ProseStrong.js", - "_nuxt/ProseTable.js", - "_nuxt/ProseTbody.js", - "_nuxt/ProseTd.js", - "_nuxt/ProseTh.js", - "_nuxt/ProseThead.js", - "_nuxt/ProseTr.js", - "_nuxt/ProseUl.js", - "_nuxt/SocialPost.js", "_nuxt/entry.js", ] `) @@ -96,21 +76,20 @@ describe('project sizes', () => { stats.server = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir) expect .soft(roundToKilobytes(stats.server.totalBytes, 10)) - .toMatchInlineSnapshot(`"2980k"`) + .toMatchInlineSnapshot(`"1840k"`) const modules = await analyzeSizes('node_modules/**/*', serverDir) const portableModules = await analyzeSizes( - ['node_modules/**/*', '!node_modules/**/*linux-{arm64,x64}*/**'], + ['node_modules/**/*', NATIVE_BINARY_GLOB], serverDir, ) expect .soft(roundToKilobytes(portableModules.totalBytes, 10)) - .toMatchInlineSnapshot(`"20300k"`) + .toMatchInlineSnapshot(`"16680k"`) const packages = modules.files - .filter(m => m.endsWith('package.json')) + .filter(m => m.endsWith('package.json') && !NATIVE_BINARY_RE.test(m)) .map(m => m.replace('/package.json', '').replace('node_modules/', '')) - .map(m => m.replace(/linux-(?:arm64|x64)/, 'linux-')) .sort() expect.soft(packages).toMatchInlineSnapshot(` [ @@ -145,22 +124,8 @@ describe('project sizes', () => { "@fastify/accept-negotiator", "@formkit/drag-and-drop", "@img/colour", - "@img/sharp-libvips-linux-", - "@img/sharp-linux-", - "@shikijs/core", - "@shikijs/engine-javascript", - "@shikijs/engine-oniguruma", - "@shikijs/langs", - "@shikijs/primitive", - "@shikijs/themes", - "@shikijs/transformers", - "@shikijs/types", - "@shikijs/vscode-textmate", - "@sindresorhus/is", "@takumi-rs/core", - "@takumi-rs/core-linux--gnu", "@takumi-rs/helpers", - "@ungap/structured-clone", "@vue/compiler-core", "@vue/compiler-core/node_modules/entities", "@vue/compiler-core/node_modules/entities/dist/commonjs", @@ -172,15 +137,9 @@ describe('project sizes', () => { "@vue/server-renderer", "@vue/shared", "await-lock", - "bail", "boolbase", - "ccount", - "char-regex", - "character-entities", - "character-entities-html4", - "character-entities-legacy", - "character-reference-invalid", - "comma-separated-tokens", + "comark", + "comark/node_modules/entities", "consola", "cookie-es", "core-js", @@ -192,13 +151,10 @@ describe('project sizes', () => { "csso", "csso/node_modules/css-tree", "csso/node_modules/css-tree/node_modules/mdn-data", - "decode-named-character-reference", "defu", "destr", - "detab", "detect-libc", "devalue", - "devlop", "dom-serializer", "dom-serializer/lib/esm", "dom-serializer/node_modules/entities", @@ -209,101 +165,29 @@ describe('project sizes', () => { "domhandler/lib/esm", "domutils", "domutils/lib/esm", - "emojilib", - "emoticon", "entities", - "entities/dist/commonjs", - "escape-string-regexp", "estree-walker", "etag", "events-to-async", "events-to-async/module", - "extend", "feed", - "flat", "fnv1a-64", - "github-slugger", "h3", - "hast-util-embedded", - "hast-util-format", - "hast-util-from-parse5", - "hast-util-has-property", - "hast-util-is-body-ok-link", - "hast-util-is-element", - "hast-util-minify-whitespace", - "hast-util-parse-selector", - "hast-util-phrasing", - "hast-util-raw", - "hast-util-to-html", - "hast-util-to-mdast", - "hast-util-to-parse5", - "hast-util-to-string", - "hast-util-to-text", - "hast-util-whitespace", - "hastscript", "hookable", - "html-void-elements", - "html-whitespace-sensitive-tag-names", "image-meta", "ipaddr.js", "ipx", "iron-webcrypto", - "is-absolute-url", - "is-alphabetical", - "is-alphanumerical", - "is-decimal", - "is-hexadecimal", - "is-plain-obj", "iso-datestring-validator", "jose", "jose/dist/node/esm", - "longest-streak", + "js-yaml", "lru-cache", "lru-cache/dist/esm", - "markdown-table", - "mdast-util-find-and-replace", - "mdast-util-from-markdown", - "mdast-util-gfm", - "mdast-util-gfm-autolink-literal", - "mdast-util-gfm-footnote", - "mdast-util-gfm-strikethrough", - "mdast-util-gfm-table", - "mdast-util-gfm-task-list-item", - "mdast-util-phrasing", - "mdast-util-to-hast", - "mdast-util-to-markdown", - "mdast-util-to-string", "mdn-data", "mediabunny", - "micromark", - "micromark-core-commonmark", - "micromark-extension-gfm", - "micromark-extension-gfm-autolink-literal", - "micromark-extension-gfm-footnote", - "micromark-extension-gfm-strikethrough", - "micromark-extension-gfm-table", - "micromark-extension-gfm-tagfilter", - "micromark-extension-gfm-task-list-item", - "micromark-factory-destination", - "micromark-factory-label", - "micromark-factory-space", - "micromark-factory-title", - "micromark-factory-whitespace", - "micromark-util-character", - "micromark-util-chunked", - "micromark-util-classify-character", - "micromark-util-combine-extensions", - "micromark-util-decode-numeric-character-reference", - "micromark-util-decode-string", - "micromark-util-encode", - "micromark-util-html-tag-name", - "micromark-util-normalize-identifier", - "micromark-util-resolve-all", - "micromark-util-sanitize-uri", - "micromark-util-subtokenize", "modern-screenshot", "multiformats", - "node-emoji", "node-fetch-native", "node-mock-http", "nostics", @@ -312,47 +196,17 @@ describe('project sizes', () => { "nuxtseo-shared", "object-identity", "ofetch", - "oniguruma-parser", - "oniguruma-to-es", - "oniguruma-to-es/dist/esm", - "parse-entities", - "parse5", - "parse5/node_modules/entities", - "parse5/node_modules/entities/dist/esm", "partysocket", "pathe", - "property-information", "radix3", - "regex", - "regex-recursion", - "regex-utilities", - "rehype-external-links", - "rehype-minify-whitespace", - "rehype-raw", - "rehype-sort-attribute-values", - "rehype-sort-attributes", - "remark-emoji", - "remark-gfm", - "remark-mdc", - "remark-parse", - "remark-rehype", - "remark-stringify", "sax", - "scule", "semver", "sharp", - "shiki", - "skin-tone", "source-map-js", - "space-separated-tokens", - "stringify-entities", "svgo", "svgo/node_modules/css-tree", "svgo/node_modules/css-tree/node_modules/mdn-data", "tlds", - "trim-lines", - "trim-trailing-lines", - "trough", "ts-custom-error", "ufo", "ultrahtml", @@ -362,25 +216,11 @@ describe('project sizes', () => { "undici_v7", "undici_v8", "unhead", - "unicode-emoji-modifier-base", "unicode-segmenter", - "unified", - "unist-util-find-after", - "unist-util-is", - "unist-util-position", - "unist-util-stringify-position", - "unist-util-visit", - "unist-util-visit-parents", - "vfile", - "vfile-location", - "vfile-message", "vue", "vue-bundle-renderer", - "web-namespaces", "xml-js", - "yaml", "zod", - "zwitch", ] `) }) @@ -414,7 +254,7 @@ async function measureFiles (files: string[], rootDir: string) { * * "Reachable" means the transitive static-import closure of each entry, which * is what the SSR renderer emits as ``; anything - * reachable from a non-admin key is subtracted so shared chunks (entry, mdc + * reachable from a non-admin key is subtracted so shared chunks (entry, prose * components, etc.) stay in the public set. */ async function loadAdminOnlyChunks (manifestPath: string): Promise> { -- 2.51.2