diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs index aa0f04f..77818f3 100644 --- a/apps/docs/astro.config.mjs +++ b/apps/docs/astro.config.mjs @@ -1,6 +1,7 @@ // @ts-check import { defineConfig } from 'astro/config'; import starlight from '@astrojs/starlight'; +import starlightBlog from 'starlight-blog'; import react from '@astrojs/react'; import rawMarkdown from './src/integrations/raw-markdown'; @@ -8,11 +9,34 @@ const isDev = process.argv.includes('dev'); // https://astro.build/config export default defineConfig({ + // Canonical site URL — enables the sitemap, canonical links, and the + // blog's RSS feed (starlight-blog only emits /blog/rss.xml when `site` is set). + site: 'https://chkit.obsessiondb.com', integrations: [ starlight({ title: 'chkit Docs', description: 'Public documentation for chkit, the ClickHouse schema and migration CLI.', customCss: ['./src/styles/custom.css'], + // Blog lives at /blog. `navigation: 'none'` so the plugin doesn't + // override SiteTitle/ThemeSelect (we already override both) — we add + // our own "Blog" header link instead. + plugins: [ + starlightBlog({ + title: 'Blog', + navigation: 'none', + metrics: { readingTime: true }, + authors: { + chkit: { + name: 'The chkit team', + url: 'https://github.com/obsessiondb/chkit', + }, + obsessiondb: { + name: 'Lucas García de Viedma (ObsessionDB)', + url: 'https://obsessiondb.com', + }, + }, + }), + ], components: { Header: './src/components/Header.astro', Hero: './src/components/Hero.astro', diff --git a/apps/docs/package.json b/apps/docs/package.json index 0adf7b8..ea74ae4 100644 --- a/apps/docs/package.json +++ b/apps/docs/package.json @@ -23,6 +23,7 @@ "agentation": "^3.0.2", "react": "^19.2.6", "react-dom": "^19.2.6", + "starlight-blog": "0.25.0", "wrangler": "^4.65.0" } } diff --git a/apps/docs/src/components/Header.astro b/apps/docs/src/components/Header.astro index 90fc0a5..44b936b 100644 --- a/apps/docs/src/components/Header.astro +++ b/apps/docs/src/components/Header.astro @@ -29,6 +29,14 @@ function findGroupTrail(entries: SidebarItem[], trail: string[]): string[] | nul } const groups = isSplash ? [] : findGroupTrail(sidebar as SidebarItem[], []) ?? []; + +// Root crumb: "Blog" on blog routes, "Docs" elsewhere. +const path = Astro.url.pathname.replace(/\/$/, ''); +const isBlog = path === '/blog' || path.startsWith('/blog/'); +const rootLabel = isBlog ? 'Blog' : 'Docs'; +const rootHref = isBlog ? '/blog/' : '/'; +// Skip the root crumb on a section's own index so it doesn't read "Blog › Blog". +const isRootIndex = groups.length === 0 && title === rootLabel; --- @@ -37,14 +45,18 @@ const groups = isSplash ? [] : findGroupTrail(sidebar as SidebarItem[], []) ?? [ !isSplash && (
diff --git a/apps/docs/src/components/SiteTitle.astro b/apps/docs/src/components/SiteTitle.astro index c1d9309..a3f9d77 100644 --- a/apps/docs/src/components/SiteTitle.astro +++ b/apps/docs/src/components/SiteTitle.astro @@ -17,6 +17,7 @@ const isSplash = entry.data.template === 'splash'; { @@ -33,6 +34,7 @@ const isSplash = entry.data.template === 'splash'; ) diff --git a/apps/docs/src/components/SocialIcons.astro b/apps/docs/src/components/SocialIcons.astro index 4f64408..2715a84 100644 --- a/apps/docs/src/components/SocialIcons.astro +++ b/apps/docs/src/components/SocialIcons.astro @@ -8,7 +8,10 @@ import config from 'virtual:starlight/user-config'; import { Icon } from '@astrojs/starlight/components'; -const links = config.social || []; +// Drop the RSS feed link from the header — the blog sidebar already links +// the feed, and we don't want it duplicated up here (starlight-blog pushes +// an `icon: 'rss'` entry into `social` when `site` is set). +const links = (config.social || []).filter((s) => s.icon !== 'rss'); const repo = 'obsessiondb/chkit'; --- diff --git a/apps/docs/src/content.config.ts b/apps/docs/src/content.config.ts index d9ee8c9..8b0b5eb 100644 --- a/apps/docs/src/content.config.ts +++ b/apps/docs/src/content.config.ts @@ -1,7 +1,11 @@ import { defineCollection } from 'astro:content'; import { docsLoader } from '@astrojs/starlight/loaders'; import { docsSchema } from '@astrojs/starlight/schema'; +import { blogSchema } from 'starlight-blog/schema'; export const collections = { - docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), + docs: defineCollection({ + loader: docsLoader(), + schema: docsSchema({ extend: (context) => blogSchema(context) }), + }), }; diff --git a/apps/docs/src/content/docs/blog/olap-deserves-better-tooling.md b/apps/docs/src/content/docs/blog/olap-deserves-better-tooling.md new file mode 100644 index 0000000..75d8a09 --- /dev/null +++ b/apps/docs/src/content/docs/blog/olap-deserves-better-tooling.md @@ -0,0 +1,230 @@ +--- +title: The era of OLAP deserves the tooling relational has had for years +description: "Why we built ch-kit: schema-as-code, migrations, and guardrails for ClickHouse, after running it at near-petabyte scale." +date: 2026-06-25 +authors: obsessiondb +excerpt: "If you build on Postgres or MySQL, you have not hand-written a migration in years. ClickHouse should not be the exception. Here is why we built ch-kit, after running ClickHouse at near-petabyte scale." +tags: + - announcement + - clickhouse +--- + +If you build on Postgres or MySQL, you have not hand written a migration in years. You change a TypeScript schema, a tool diffs it, generates the SQL, applies it, and fails your CI if production has drifted. Drizzle, Prisma, and Flyway made that the default. It is boring, and boring is exactly what you want from the thing that changes your database. + +Now switch to ClickHouse®. Suddenly you are back in 2010: hand written DDL, diffs done by eye, a `migrations/` folder that may or may not match what is actually running, and a sinking feeling every time someone runs an `ALTER` in production. OLAP is becoming the default for analytics, but the tooling around it never caught up to what the relational world treats as table stakes. + +We felt this acutely. In our previous venture, Numia, we ran ClickHouse at near-petabyte scale for real-time blockchain analytics. We hit two walls. The first was scaling the database like serious infrastructure. The second was the complete absence of tooling to manage the schema as code. We built [ObsessionDB](https://obsessiondb.com), managed ClickHouse with decoupled storage and compute, to solve the first. **ch-kit** is how we are solving the second, and it is open source. + +This post is about the second wall, and what schema-as-code for ClickHouse actually looks like once you have it. + +## The problem with hand written DDL + +A ClickHouse schema is not just a list of columns. A single `MergeTree` table carries an engine, a sorting key, a partitioning expression, TTL rules, skip indexes, projections, codecs, and table settings. Materialized views point at target tables. Some of those properties can be altered in place. Some cannot, and changing them means a drop and recreate, which on a large table is not a thing you discover by accident. + +When all of that lives in raw SQL files, three failures show up over and over: + +1. **Drift.** Someone runs a manual `ALTER` to fix an incident at 3am. The fix never makes it back into a migration file. Now your repository and your production database disagree, and nothing tells you. +2. **Unsafe changes.** A migration drops a column. The reviewer did not notice. It runs in CI on a Friday. The data is gone. +3. **No source of truth.** The schema is whatever the sum of every migration file happens to produce. To know the current shape of a table, you read the database, not your code. + +Relational tooling solved all three. ch-kit solves them for ClickHouse. + +## Define your schemas in TypeScript + +In ch-kit, tables, views, and materialized views are TypeScript values. Here is a real table definition, with the features you actually use in production: + +```ts +import { schema, table } from '@chkit/core' + +const events = table({ + database: 'analytics', + name: 'events', + columns: [ + { name: 'id', type: 'UInt64' }, + { name: 'org_id', type: 'String' }, + { name: 'source', type: 'LowCardinality(String)' }, + { name: 'payload', type: 'String', nullable: true }, + { name: 'received_at', type: 'DateTime64(3)', default: 'fn:now64(3)' }, + ], + engine: 'MergeTree()', + primaryKey: ['id'], + orderBy: ['org_id', 'received_at', 'id'], + partitionBy: 'toYYYYMM(received_at)', + ttl: 'received_at + INTERVAL 90 DAY', + settings: { index_granularity: 8192 }, + indexes: [ + { name: 'idx_source', expression: 'source', type: 'set', maxRows: 0, granularity: 1 }, + ], +}) + +export default schema(events) +``` + +This is the desired state of your database, expressed as code, type checked, reviewable in a pull request, and split across as many files as you want. Materialized views and refreshable views are first class, including the `to` target table and refresh schedules. Compression codecs are typed too, so a column codec chain like `[{ kind: 'DoubleDelta' }, { kind: 'ZSTD', level: 3 }]` is validated rather than stringly typed. + +You do not write SQL to define this. You write SQL for your queries, because ch-kit is not an ORM and has no opinion about how you read your data. It only owns the schema, the migrations, and the guardrails. + +## Migrations are diffs, not artifacts you maintain + +As we've mentioned already multiple times, with ch-kit you just change the TypeScript, and the rest is handled for you. Migrations are part of it. + +```sh +chkit generate --name add_events_table +``` + +With `generate`, ch-kit loads your TS definitions, compares them against the previous snapshot, computes an ordered plan, and writes a migration SQL file plus an updated snapshot. If nothing changed, no file is created. Every operation in the plan is tagged with a risk level: + +| Risk | Meaning | Examples | +| --- | --- | --- | +| `safe` | No data loss | `CREATE TABLE`, `ADD COLUMN` | +| `caution` | Review recommended | settings changes | +| `danger` | Destructive | `DROP TABLE`, `DROP COLUMN` | + +Here is a detail that matters and that most ad hoc setups get wrong. ch-kit knows which schema properties are structural and which are alterable. Changing columns, indexes, projections, settings, or TTL is an `ALTER` in place. Changing the engine, `primaryKey`, `orderBy`, `partitionBy`, or `uniqueKey` is structural, which means a drop and recreate. ch-kit makes that distinction explicit in the plan instead of letting you find out in production that your "small" change rewrites the whole table. + +Renames are tracked, not guessed. Mark a column or table with `renamedFrom` (or pass `--rename-table` / `--rename-column`) and ch-kit emits a real rename instead of a destructive drop and add: + +```ts +columns: [ + { name: 'user_email', type: 'String', renamedFrom: 'email' }, +] +``` + +## Applying changes without losing data + +Once you have your migrations defined with `generate`, you can preview the impact by running `chkit migrate`. This will dry run and show you the plan. If you like what you see, just add `--apply` at the end for the actual run: + +```sh +chkit migrate # shows the plan +chkit migrate --apply # applies pending migrations +``` + +Three guardrails run on every apply: + +- **Destructive operations are blocked.** Any migration containing a `risk=danger` operation, a `DROP TABLE` or `DROP COLUMN`, requires explicit approval. In an interactive terminal you get a prompt. In CI, the command exits with code 3 and refuses to run unless you pass `--allow-destructive` or set `safety.allowDestructive` in config. The error payload tells you exactly which migration and which operation, with an impact description and a recommendation. Your data does not disappear because a reviewer was tired. +- **Checksums are verified.** Every applied migration is recorded in a `_chkit_migrations` journal table in ClickHouse along with a SHA-256 hash of the file content. If a migration file is edited after it was applied, the next run aborts before touching anything. Migration history is immutable, and ch-kit enforces it. +- **It is built for CI.** The CLI detects non-interactive environments (`CI=true`, no TTY) and never blocks on a prompt. Every command supports `--json` with a stable output envelope, so you can parse results with `jq` and build approval gates. + +## Don't let your project drift! + +ch-kit also implements a `drift` command that introspects the live database and compares it, object by object and column by column, against your snapshot: + +```sh +chkit drift --json +``` + +It reports missing objects, extra objects, changed columns, and mismatches on settings, TTL, indexes, `ORDER BY`, `PARTITION BY`, primary keys, and projections. It is detailed enough that the 3am manual `ALTER` shows up the next morning as a concrete, named difference instead of a vague feeling that something is off. + +In CI you turn that signal into a gate with `chkit check`: + +```sh +chkit check --strict --json +``` + +`check` evaluates three policies, all on by default: fail on pending migrations, fail on checksum mismatch, fail on drift. The `--strict` flag forces them on regardless of config, so a permissive local setting never leaks into your pipeline. A full pull request gate is a few lines: + +```yaml +- name: Check schema consistency + run: npx chkit check --strict --json + +- name: Verify generated types + run: npx chkit codegen --check --json +``` + +That `codegen --check` step is the other half. ch-kit generates TypeScript row types (and optional Zod schemas) from the same definitions, so your application types and your database schema cannot quietly diverge either. + +## Works with any ClickHouse + +ch-kit is not a lock-in play. We run ObsessionDB, a managed ClickHouse offering that competes with ClickHouse Cloud, Altinity, and the rest. But we love ClickHouse, and we believe the tooling around it should be available to everyone using the technology, because that is what strengthens the ecosystem. So ch-kit runs against ObsessionDB, ClickHouse Cloud, Altinity, or any other managed or self-hosted ClickHouse. + +The only managed-specific touch is that `Shared*` engine prefixes (`SharedMergeTree`, `SharedReplacingMergeTree`, and so on) are normalized away during comparison, so managed engines do not show up as false drift. If you run ObsessionDB, the first-party plugin keeps your schema on the right `Shared*` engines automatically, from the exact same TypeScript you use locally. If you do not, those engine variants are stripped for your target. Same schema, different backends. + +It is MIT licensed, written in TypeScript, runs on Node 20+ or Bun, and needs ClickHouse 24.x or newer. It is beta: the CLI surface and the schema DSL are stable and run our own production workloads today, and we may still make small breaking changes before 1.0. + +## Start from where you already are + +Most teams adopting ch-kit are not starting from an empty database. They already have ClickHouse in production, with tables that matter and data they cannot lose. Either way, the first step is the same: get a project scaffolded. + +If you are starting from scratch, `npm create chkit@latest` gives you a working project from a curated example: + +```sh +npm create chkit@latest +``` + +If you are adding ch-kit to an existing TypeScript project, `chkit init` writes the project config (`clickhouse.config.ts`, with the ClickHouse connection block reading from environment variables) and a starter schema file. It is idempotent, so running it on an existing project leaves your files untouched. + +```sh +# before: your existing TypeScript project +# my-app/ +# ├── package.json +# ├── tsconfig.json +# └── src/ +# └── index.ts + +$ chkit init +Created clickhouse.config.ts +Created src/db/schema/example.ts + +# after: chkit added exactly two files, nothing else touched +# my-app/ +# ├── clickhouse.config.ts ← config: ClickHouse connection + plugins +# ├── package.json +# ├── tsconfig.json +# └── src/ +# ├── index.ts +# └── db/ +# └── schema/ +# └── example.ts ← starter schema: an `events` table +``` + +If you are starting fresh, edit the generated example schema to match the tables you want, then move on to `generate`. + +If you already run ClickHouse, the next command is `chkit pull`. It introspects your live database and writes a deterministic TypeScript schema file from what is actually there: + +```sh +# 1) install the pull plugin +npm install -D @chkit/plugin-pull + +# 2) register it in clickhouse.config.ts: +# import { pull } from '@chkit/plugin-pull' +# plugins: [pull({ outFile: './src/db/schema/pulled.ts' })] + +# 3) introspect your live database into TypeScript +chkit pull --out-file ./src/db/schema/pulled.ts +``` + +This is the step that turns an existing production database into version-controlled code. You do not transcribe table definitions by hand and hope you got the `ORDER BY` and the codecs right. ch-kit reads them. The output is deterministic, so it produces clean, reviewable diffs instead of churn, and you can scope it to specific databases with `--database` or preview it with `--dryrun` before writing anything. + +Once you have pulled, prove the result immediately: + +```sh +chkit drift +``` + +If your code matches production, drift reports nothing. That zero-drift result is the moment your database stops being the source of truth and your repository takes over. From here, every future change starts in TypeScript: + +```sh +chkit generate --name init +chkit migrate --apply +chkit drift +``` + +## Want more? Check the rest of the features! + +:::tip +We have only covered the initial bits of what ch-kit can do here. The [docs](https://chkit.obsessiondb.com) go into more detail on getting started no matter your case, and on everything else the tooling can do. +::: + +The relational world stopped hand writing migrations a long time ago. OLAP should not be the exception. If you run ClickHouse and you are still managing schema by hand, we built ch-kit so you do not have to. + +- **Repo:** +- **Docs:** +- **Install:** + +If you do not use TypeScript but Python, do not worry: we will publish a Python port in the coming weeks. And since ch-kit is open source, if you feel something is missing, you are more than welcome to open an issue or a PR. + +Stay tuned! + +--- + +*ClickHouse® is a registered trademark of ClickHouse, Inc.* diff --git a/apps/docs/src/styles/custom.css b/apps/docs/src/styles/custom.css index 97f040c..12aa66d 100644 --- a/apps/docs/src/styles/custom.css +++ b/apps/docs/src/styles/custom.css @@ -1209,9 +1209,11 @@ button[data-open-modal] > kbd kbd { } } -/* The landing has no sidebar/hamburger; show the search trigger only on - non-landing (doc) pages. */ -:root:not([data-has-sidebar]) site-search { +/* Show the search trigger only on documentation pages — hide it on the + landing (no sidebar) and on all blog pages (listing + posts). */ +:root:not([data-has-sidebar]) site-search, +:root:has(.posts) site-search, +:root:has(.post-footer) site-search { display: none; } @@ -1392,6 +1394,134 @@ kbd { color: var(--txt-muted); } +/* ════════════════════════════════════════════════════ + Blog listing — card grid (ObsessionDB-style) + Restyles starlight-blog's .posts / .preview markup from a vertical + list into a bordered card grid. `!important` overrides the plugin's + scoped component styles. The first post is featured full-width. + ════════════════════════════════════════════════════ */ + +.posts { + display: grid !important; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 1.25rem !important; +} + +.posts > .preview:first-child { + grid-column: 1 / -1; +} + +.preview { + gap: 1rem !important; + height: 100%; + padding: 1.5rem; + border: 1px solid var(--line); + background: var(--bg); + transition: border-color 0.15s, background 0.15s; +} + +.preview:hover { + border-color: var(--accent); + background: var(--surface-3); +} + +.preview > header { + display: flex; + flex-direction: column; + gap: 0.6rem; +} + +.preview h2 { + margin-bottom: 0 !important; + font-size: 1.2rem; + letter-spacing: -0.02em; +} + +.posts > .preview:first-child h2 { + font-size: 1.6rem; +} + +.preview h2 a { + color: var(--txt-strong); +} + +.preview h2 a:hover { + color: var(--accent); +} + +/* Date / author / reading-time row — small mono caps. */ +.preview .metadata { + font-family: var(--sl-font-mono); + font-size: 0.6875rem; + letter-spacing: 0.04em; + text-transform: uppercase; + color: var(--txt-muted); +} + +/* Smaller author name (the plugin sizes it at --sl-text-base / 600). */ +.metadata .author .name { + font-size: 0.8125rem; + font-weight: 500; +} + +/* Excerpt grows so the tag footers align across a row. */ +.preview > .sl-markdown-content { + flex: 1; + font-size: 0.9rem; + line-height: 1.55; + color: var(--txt-soft); +} + +.preview > footer { + margin-top: auto; +} + +@media (max-width: 50em) { + .posts { + grid-template-columns: 1fr; + } + + .posts > .preview:first-child h2 { + font-size: 1.3rem; + } +} + +/* starlight-blog resets .main-frame's top padding to just the nav height + (it assumes no breadcrumb bar), which tucks the listing under our fixed + subheader. Restore the full nav + subheader offset on listing pages. + `:root:has()` outranks the plugin's `[data-has-toc] .main-frame` rule. */ +:root:has(.posts) .main-frame { + padding-top: calc(var(--sl-nav-height) + var(--sl-mobile-toc-height, 0px) + var(--chk-subheader-h)); +} + +/* The plugin hides the page-title panel; bring it back so listing pages keep + their "Blog" (or tag/author) heading above the posts. */ +:root:has(.posts) .content-panel:first-of-type { + display: block; +} + +:root:has(.posts) .content-panel:first-of-type h1 { + font-size: 2.5rem; + letter-spacing: -0.03em; +} + +/* Per-page chrome (desktop): listing pages (have `.posts`) drop the right + "On this page" column; post pages (have `.post-footer`) drop the left nav + rail and pull the content back to the shell gutter for a focused read. */ +@media (min-width: 50em) { + :root:has(.posts) .right-sidebar { + display: none; + } + + :root:has(.post-footer) .sidebar-pane { + display: none; + } + + :root:has(.post-footer) .main-frame { + --sl-content-inline-start: var(--chk-gutter); + } +} + /* ════════════════════════════════════════════════════ PackagedCommand & Command components (sharp tungsten) ════════════════════════════════════════════════════ */ diff --git a/bun.lock b/bun.lock index 290bddc..4c346a9 100644 --- a/bun.lock +++ b/bun.lock @@ -32,6 +32,7 @@ "agentation": "^3.0.2", "react": "^19.2.6", "react-dom": "^19.2.6", + "starlight-blog": "0.25.0", "wrangler": "^4.65.0", }, }, @@ -164,6 +165,8 @@ "@astrojs/react": ["@astrojs/react@5.0.5", "", { "dependencies": { "@astrojs/internal-helpers": "0.9.1", "@vitejs/plugin-react": "^5.2.0", "devalue": "^5.6.4", "ultrahtml": "^1.6.0", "vite": "^7.3.2" }, "peerDependencies": { "@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0", "@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0", "react": "^17.0.2 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "sha512-5jSFDqWqLdEyp7CEVD66A7AQEEuwLkCGR25NJ4FR5EjziZQqZTGc7hJOFZ97qb98BiU6vElrS70R8iI+HhufGQ=="], + "@astrojs/rss": ["@astrojs/rss@4.0.18", "", { "dependencies": { "fast-xml-parser": "^5.5.7", "piccolore": "^0.1.3", "zod": "^4.3.6" } }, "sha512-wc5DwKlbTEdgVAWnHy8krFTeQ42t1v/DJqeq5HtulYK3FYHE4krtRGjoyhS3eXXgfdV6Raoz2RU3wrMTFAitRg=="], + "@astrojs/sitemap": ["@astrojs/sitemap@3.7.0", "", { "dependencies": { "sitemap": "^8.0.2", "stream-replace-string": "^2.0.0", "zod": "^3.25.76" } }, "sha512-+qxjUrz6Jcgh+D5VE1gKUJTA3pSthuPHe6Ao5JCxok794Lewx8hBFaWHtOnN0ntb2lfOf7gvOi9TefUswQ/ZVA=="], "@astrojs/starlight": ["@astrojs/starlight@0.37.6", "", { "dependencies": { "@astrojs/markdown-remark": "^6.3.1", "@astrojs/mdx": "^4.2.3", "@astrojs/sitemap": "^3.3.0", "@pagefind/default-ui": "^1.3.0", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", "@types/mdast": "^4.0.4", "astro-expressive-code": "^0.41.1", "bcp-47": "^2.1.0", "hast-util-from-html": "^2.0.1", "hast-util-select": "^6.0.2", "hast-util-to-string": "^3.0.0", "hastscript": "^9.0.0", "i18next": "^23.11.5", "js-yaml": "^4.1.0", "klona": "^2.0.6", "magic-string": "^0.30.17", "mdast-util-directive": "^3.0.0", "mdast-util-to-markdown": "^2.1.0", "mdast-util-to-string": "^4.0.0", "pagefind": "^1.3.0", "rehype": "^13.0.1", "rehype-format": "^5.0.0", "remark-directive": "^3.0.0", "ultrahtml": "^1.6.0", "unified": "^11.0.5", "unist-util-visit": "^5.0.0", "vfile": "^6.0.2" }, "peerDependencies": { "astro": "^5.5.0" } }, "sha512-wQrKwH431q+8FsLBnNQeG+R36TMtEGxTQ2AuiVpcx9APcazvL3n7wVW8mMmYyxX0POjTnxlcWPkdMGR3Yj1L+w=="], @@ -438,6 +441,8 @@ "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="], + "@nodable/entities": ["@nodable/entities@2.2.0", "", {}, "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], @@ -620,6 +625,8 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + "anynum": ["anynum@1.0.1", "", {}, "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A=="], + "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -636,6 +643,8 @@ "astro-expressive-code": ["astro-expressive-code@0.41.6", "", { "dependencies": { "rehype-expressive-code": "^0.41.6" }, "peerDependencies": { "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" } }, "sha512-l47tb1uhmVIebHUkw+HEPtU/av0G4O8Q34g2cbkPvC7/e9ZhANcjUUciKt9Hp6gSVDdIuXBBLwJQn2LkeGMOAw=="], + "astro-remote": ["astro-remote@0.3.4", "", { "dependencies": { "entities": "^4.5.0", "marked": "^12.0.0", "marked-footnote": "^1.2.2", "marked-smartypants": "^1.1.6", "ultrahtml": "^1.5.3" } }, "sha512-jL5skNQLA0YBc1R3bVGXyHew3FqGqsT7AgLzWAVeTLzFkwVMUYvs4/lKJSmS7ygcF1GnHnoKG6++8GL9VtWwGQ=="], + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], @@ -768,7 +777,7 @@ "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], - "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="], @@ -816,6 +825,10 @@ "fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="], + "fast-xml-builder": ["fast-xml-builder@1.2.0", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q=="], + + "fast-xml-parser": ["fast-xml-parser@5.9.3", "", { "dependencies": { "@nodable/entities": "^2.2.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^1.0.1", "path-expression-matcher": "^1.5.0", "strnum": "^2.4.1", "xml-naming": "^0.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-brCNCeScma/kqa54J4PIDriSSSLssRkuYaUCpvHJulGc3HGI/xxKUCTDcYkAdqJsyb//ydpbxecjC3hB9+tb/g=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], @@ -938,6 +951,8 @@ "is-subdir": ["is-subdir@1.2.0", "", { "dependencies": { "better-path-resolve": "1.0.0" } }, "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw=="], + "is-unsafe": ["is-unsafe@1.0.1", "", {}, "sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA=="], + "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], "is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], @@ -976,6 +991,14 @@ "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], + + "marked-footnote": ["marked-footnote@1.4.0", "", { "peerDependencies": { "marked": ">=7.0.0" } }, "sha512-fZTxAhI1TcLEs5UOjCfYfTHpyKGaWQevbxaGTEA68B51l7i87SctPFtHETYqPkEN0ka5opvy4Dy1l/yXVC+hmg=="], + + "marked-plaintify": ["marked-plaintify@1.1.1", "", { "peerDependencies": { "marked": ">=13.0.0" } }, "sha512-r3kMKArhfo2H3lD4ctFq/OJTzM0uNvXHh7FBTI1hMDpf4Ac1djjtq4g8NfTBWMxWLmaEz3KL1jCkLygik3gExA=="], + + "marked-smartypants": ["marked-smartypants@1.1.12", "", { "dependencies": { "smartypants": "^0.2.2" }, "peerDependencies": { "marked": ">=4 <19" } }, "sha512-Z0QL2GpihbSeG5aaCrQxMEoqvngMftF/gq1SrdlCnbecUSrX3HYgPtCZzCW+OyNe2ideQqaFdxfGryqQX1MBDA=="], + "mdast-util-definitions": ["mdast-util-definitions@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ=="], "mdast-util-directive": ["mdast-util-directive@3.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q=="], @@ -1154,6 +1177,8 @@ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + "path-expression-matcher": ["path-expression-matcher@1.6.1", "", {}, "sha512-h7bxdzhHk8Knyc4Tj+jMaa7fEEoUJy7p1qtbVgkYg1Uhpe5Np5VuGXCRZnkZvU+Q42M1vStt0ifa3ueykRJPmQ=="], + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="], @@ -1284,6 +1309,8 @@ "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], + "smartypants": ["smartypants@0.2.2", "", { "bin": { "smartypants": "bin/smartypants.js", "smartypantsu": "bin/smartypantsu.js" } }, "sha512-TzobUYoEft/xBtb2voRPryAUIvYguG0V7Tt3de79I1WfXgCwelqVsGuZSnu3GFGRZhXR90AeEYIM+icuB/S06Q=="], + "smol-toml": ["smol-toml@1.6.0", "", {}, "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="], "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], @@ -1296,6 +1323,8 @@ "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="], + "starlight-blog": ["starlight-blog@0.25.0", "", { "dependencies": { "@astrojs/markdown-remark": "^6.3.1", "@astrojs/mdx": "^4.0.8", "@astrojs/rss": "^4.0.11", "astro-remote": "^0.3.3", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-html": "^9.0.5", "hast-util-to-string": "^3.0.1", "marked": "^15.0.4", "marked-plaintify": "^1.1.1", "mdast-util-mdx-expression": "^2.0.1", "unist-util-is": "^6.0.0", "unist-util-remove": "^4.0.0", "unist-util-visit": "^5.0.0" }, "peerDependencies": { "@astrojs/starlight": ">=0.33.0" } }, "sha512-VbbfwmpENqlhpGe1Ht2y8Q9tnIpMSylw9j6g7AqIBnnndpEbH7+QRqaEFUkdvqo7FKJKTPSH7gtabwpMbgpGwA=="], + "stream-replace-string": ["stream-replace-string@2.0.0", "", {}, "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w=="], "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], @@ -1306,6 +1335,8 @@ "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + "strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="], + "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="], "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], @@ -1366,6 +1397,8 @@ "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], + "unist-util-remove": ["unist-util-remove@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg=="], + "unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="], "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], @@ -1410,6 +1443,8 @@ "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + "xml-naming": ["xml-naming@0.1.0", "", {}, "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw=="], + "xxhash-wasm": ["xxhash-wasm@1.1.0", "", {}, "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA=="], "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], @@ -1438,6 +1473,8 @@ "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.5", "", {}, "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA=="], + "@astrojs/rss/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + "@astrojs/telemetry/ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], "@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], @@ -1524,20 +1561,22 @@ "astro/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], + "astro-remote/marked": ["marked@12.0.2", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q=="], + "boxen/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], "create-chkit/@types/node": ["@types/node@20.19.41", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ECymXOukMnOoVkC2bb1Vc/w/836DXncOg5m8Xj1RH7xSHZJWNYY6Zh7EH477vcnD5egKNNfy2RpNOmuChhFPgQ=="], "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], - "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "p-filter/p-map": ["p-map@2.1.0", "", {}, "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw=="], "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + "read-yaml-file/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], "sitemap/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="],