` and a `')).toBe('#');
+ expect(sanitizeHref('vbscript:msgbox(1)')).toBe('#');
+ });
+
+ it('blocks protocol-relative URLs', () => {
+ expect(sanitizeHref('//evil.com/path')).toBe('#');
+ });
+
+ it('allows http(s) URLs', () => {
+ expect(sanitizeHref('https://tina.io')).toBe('https://tina.io');
+ expect(sanitizeHref('http://tina.io/x')).toBe('http://tina.io/x');
+ });
+
+ it('allows mailto:', () => {
+ expect(sanitizeHref('mailto:hi@tina.io')).toBe('mailto:hi@tina.io');
+ });
+
+ it('allows relative, root-relative, and fragment paths', () => {
+ expect(sanitizeHref('/about')).toBe('/about');
+ expect(sanitizeHref('./relative')).toBe('./relative');
+ expect(sanitizeHref('../up')).toBe('../up');
+ expect(sanitizeHref('#section')).toBe('#section');
+ });
+
+ it('returns fallback for non-strings, empty, or invalid', () => {
+ expect(sanitizeHref(null)).toBe('#');
+ expect(sanitizeHref(undefined)).toBe('#');
+ expect(sanitizeHref('')).toBe('#');
+ expect(sanitizeHref(' ')).toBe('#');
+ expect(sanitizeHref(42)).toBe('#');
+ expect(sanitizeHref('not a url')).toBe('#');
+ });
+
+ it('honours a custom fallback', () => {
+ expect(sanitizeHref('javascript:alert(1)', '/safe')).toBe('/safe');
+ });
+});
+
+describe('sanitizeImageSrc', () => {
+ it('allows http(s) URLs', () => {
+ expect(sanitizeImageSrc('https://cdn.tina.io/x.png')).toBe(
+ 'https://cdn.tina.io/x.png'
+ );
+ });
+
+ it('allows relative paths', () => {
+ expect(sanitizeImageSrc('/uploads/x.png')).toBe('/uploads/x.png');
+ expect(sanitizeImageSrc('./local.png')).toBe('./local.png');
+ expect(sanitizeImageSrc('../up.png')).toBe('../up.png');
+ });
+
+ it('blocks protocol-relative and dangerous schemes', () => {
+ expect(sanitizeImageSrc('//evil.com/x.png')).toBe('');
+ expect(sanitizeImageSrc('javascript:alert(1)')).toBe('');
+ expect(sanitizeImageSrc('data:image/png;base64,xxx')).toBe('');
+ });
+
+ it('returns empty for non-strings, empty, or invalid', () => {
+ expect(sanitizeImageSrc(null)).toBe('');
+ expect(sanitizeImageSrc(undefined)).toBe('');
+ expect(sanitizeImageSrc('')).toBe('');
+ expect(sanitizeImageSrc(42)).toBe('');
+ });
+});
diff --git a/packages/@tinacms/astro/src/bridge-route.ts b/packages/@tinacms/astro/src/bridge-route.ts
new file mode 100644
index 0000000000..1b739fdd78
--- /dev/null
+++ b/packages/@tinacms/astro/src/bridge-route.ts
@@ -0,0 +1,33 @@
+/**
+ * Astro endpoint injected by the `tina()` integration. Serves the bridge
+ * as a single self-contained ESM bundle at `/_tina/bridge.js`. Loaded by
+ * the inline ``
+ );
+}
+
+/**
+ * Read `PUBLIC_TINA_ADMIN_ORIGIN` (comma-separated for multi-origin setups)
+ * from Astro's `import.meta.env`. Returns null when unset so `bridge.init()`
+ * falls back to `window.location.origin` — the common same-host case.
+ *
+ * `import.meta.env` is cast inline because the package ships no `env.d.ts`
+ * to keep the public type surface free of Vite/Astro client-types coupling.
+ */
+function adminOrigins(): string[] | null {
+ const env = (
+ import.meta as ImportMeta & {
+ env?: Record
;
+ }
+ ).env;
+ const raw = env?.PUBLIC_TINA_ADMIN_ORIGIN;
+ if (!raw) return null;
+ const origins = raw
+ .split(',')
+ .map((s) => s.trim())
+ .filter(Boolean);
+ return origins.length > 0 ? origins : null;
+}
diff --git a/packages/@tinacms/astro/src/sanitize.ts b/packages/@tinacms/astro/src/sanitize.ts
new file mode 100644
index 0000000000..b5590b257a
--- /dev/null
+++ b/packages/@tinacms/astro/src/sanitize.ts
@@ -0,0 +1,64 @@
+/**
+ * Sanitizes a CMS-supplied href, returning a safe URL or the fallback.
+ * Blocks dangerous schemes (javascript:, data:, vbscript:) and
+ * protocol-relative URLs (//evil.com). Allows relative paths, http(s),
+ * and mailto:.
+ */
+export function sanitizeHref(value: unknown, fallback = '#'): string {
+ if (typeof value !== 'string') return fallback;
+ const trimmed = value.trim();
+ if (!trimmed) return fallback;
+ const lower = trimmed.toLowerCase();
+ if (
+ lower.startsWith('javascript:') ||
+ lower.startsWith('data:') ||
+ lower.startsWith('vbscript:')
+ ) {
+ return fallback;
+ }
+ if (
+ (trimmed.startsWith('/') && !trimmed.startsWith('//')) ||
+ trimmed.startsWith('./') ||
+ trimmed.startsWith('../') ||
+ trimmed.startsWith('#')
+ ) {
+ return trimmed;
+ }
+ try {
+ const url = new URL(trimmed);
+ if (
+ url.protocol === 'http:' ||
+ url.protocol === 'https:' ||
+ url.protocol === 'mailto:'
+ ) {
+ return trimmed;
+ }
+ } catch {
+ return fallback;
+ }
+ return fallback;
+}
+
+/**
+ * Validates a CMS-supplied image src, returning the src string if safe or ''
+ * if it is empty, not a string, or uses a non-http(s)/relative scheme.
+ */
+export function sanitizeImageSrc(src: unknown): string {
+ if (typeof src !== 'string') return '';
+ const trimmed = src.trim();
+ if (!trimmed) return '';
+ if (
+ trimmed.startsWith('./') ||
+ trimmed.startsWith('../') ||
+ (trimmed.startsWith('/') && !trimmed.startsWith('//'))
+ ) {
+ return trimmed;
+ }
+ try {
+ const url = new URL(trimmed);
+ if (url.protocol === 'http:' || url.protocol === 'https:') return trimmed;
+ } catch {
+ return '';
+ }
+ return '';
+}
diff --git a/packages/@tinacms/astro/src/tina-field.ts b/packages/@tinacms/astro/src/tina-field.ts
new file mode 100644
index 0000000000..435f1b6119
--- /dev/null
+++ b/packages/@tinacms/astro/src/tina-field.ts
@@ -0,0 +1 @@
+export * from '@tinacms/bridge/tina-field';
diff --git a/packages/@tinacms/astro/src/types.ts b/packages/@tinacms/astro/src/types.ts
new file mode 100644
index 0000000000..23a4c5cc0e
--- /dev/null
+++ b/packages/@tinacms/astro/src/types.ts
@@ -0,0 +1,97 @@
+/**
+ * Plate AST node types Tina returns from rich-text fields. Mirrors the shape
+ * documented in `packages/@tinacms/mdx/src/parse/plate.ts` — kept inline so
+ * the Astro renderer can stay framework-free and not pull @tinacms/mdx into
+ * the page bundle.
+ */
+
+/**
+ * Astro doesn't publicly export `AstroComponentFactory`, so we use a
+ * structural placeholder. The consumer's Astro pipeline performs the real
+ * compile-time check that whatever they pass is a valid component.
+ */
+export type AstroComponent = (...args: never[]) => unknown;
+
+export type TinaRichTextRoot = {
+ type: 'root';
+ children: TinaRichTextNode[];
+};
+
+export type TinaRichTextNode =
+ | BlockElement
+ | InlineElement
+ | TextElement
+ | MdxElement;
+
+export type LinkElement = {
+ type: 'a';
+ url: string;
+ title?: string;
+ children: InlineElement[];
+};
+
+export type ImageElement = {
+ type: 'img';
+ url: string;
+ alt?: string;
+ caption?: string;
+};
+
+export type CodeBlockElement = {
+ type: 'code_block';
+ lang?: string;
+ value?: string;
+ children?: { children: TextElement[] }[];
+};
+
+export type BlockElement =
+ | { type: 'p'; children: InlineElement[] }
+ | {
+ type: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
+ children: InlineElement[];
+ }
+ | { type: 'blockquote'; children: TinaRichTextNode[] }
+ | { type: 'ul' | 'ol'; children: TinaRichTextNode[] }
+ | { type: 'li'; children: TinaRichTextNode[] }
+ | { type: 'lic'; children: InlineElement[] }
+ | { type: 'hr' }
+ | { type: 'break' }
+ | ImageElement
+ | CodeBlockElement
+ | { type: 'maybe_mdx' }
+ | { type: 'html'; value: string }
+ | { type: 'invalid_markdown'; value: string };
+
+export type InlineElement =
+ | TextElement
+ | LinkElement
+ | { type: 'html_inline'; value: string }
+ | MdxElement;
+
+export type TextElement = {
+ type: 'text';
+ text: string;
+ bold?: boolean;
+ italic?: boolean;
+ underline?: boolean;
+ strikethrough?: boolean;
+ code?: boolean;
+ highlight?: boolean;
+ highlightColor?: string;
+};
+
+export type MdxElement = {
+ type: 'mdxJsxFlowElement' | 'mdxJsxTextElement';
+ name: string;
+ props: Record;
+ children?: TinaRichTextNode[];
+};
+
+export type TinaRichTextContent =
+ | TinaRichTextRoot
+ | TinaRichTextNode[]
+ | null
+ | undefined;
+
+/** A map of mdxJsx name (or default tag override) → Astro component. */
+export type CustomComponentsMap = Record;
diff --git a/packages/@tinacms/astro/tsconfig.json b/packages/@tinacms/astro/tsconfig.json
new file mode 100644
index 0000000000..b08997b3b2
--- /dev/null
+++ b/packages/@tinacms/astro/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../../base.tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ "strict": true,
+ "skipLibCheck": true,
+ "noImplicitAny": true,
+ "noUncheckedIndexedAccess": true,
+ "noFallthroughCasesInSwitch": true,
+ "moduleResolution": "bundler",
+ "module": "esnext",
+ "target": "esnext",
+ "lib": ["ESNext", "DOM", "DOM.Iterable"]
+ },
+ "exclude": ["node_modules", "dist", "src/**/*.test.ts", "src/__tests__"],
+ "include": ["src"]
+}
diff --git a/packages/@tinacms/astro/vitest.config.ts b/packages/@tinacms/astro/vitest.config.ts
new file mode 100644
index 0000000000..f549931c87
--- /dev/null
+++ b/packages/@tinacms/astro/vitest.config.ts
@@ -0,0 +1,9 @@
+///
+import { getViteConfig } from 'astro/config';
+
+export default getViteConfig({
+ test: {
+ globals: true,
+ include: ['src/**/*.test.ts'],
+ },
+});
diff --git a/packages/@tinacms/bridge/package.json b/packages/@tinacms/bridge/package.json
new file mode 100644
index 0000000000..b1ba065e04
--- /dev/null
+++ b/packages/@tinacms/bridge/package.json
@@ -0,0 +1,64 @@
+{
+ "name": "@tinacms/bridge",
+ "version": "0.1.0",
+ "type": "module",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "package.json",
+ "dist"
+ ],
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "default": "./dist/index.js"
+ },
+ "./tina-field": {
+ "types": "./dist/tina-field.d.ts",
+ "default": "./dist/tina-field.js"
+ },
+ "./preview": {
+ "types": "./dist/preview.d.ts",
+ "default": "./dist/preview.js"
+ },
+ "./metadata": {
+ "types": "./dist/metadata.d.ts",
+ "default": "./dist/metadata.js"
+ },
+ "./quick-edit-css": {
+ "types": "./dist/quick-edit-css.d.ts",
+ "default": "./dist/quick-edit-css.js"
+ }
+ },
+ "license": "Apache-2.0",
+ "buildConfig": {
+ "entryPoints": [
+ "src/index.ts",
+ "src/tina-field.ts",
+ "src/preview.ts",
+ "src/metadata.ts",
+ "src/quick-edit-css.ts"
+ ]
+ },
+ "scripts": {
+ "types": "tsc",
+ "build": "tinacms-scripts build",
+ "test": "vitest run",
+ "test-watch": "vitest"
+ },
+ "devDependencies": {
+ "@tinacms/scripts": "workspace:*",
+ "@types/node": "^22.13.1",
+ "happy-dom": "catalog:",
+ "typescript": "^5.7.3",
+ "vite": "^5.4.14",
+ "vitest": "^2.1.9"
+ },
+ "publishConfig": {
+ "registry": "https://registry.npmjs.org"
+ },
+ "repository": {
+ "url": "https://github.com/tinacms/tinacms.git",
+ "directory": "packages/@tinacms/bridge"
+ }
+}
diff --git a/packages/@tinacms/bridge/src/click-to-focus.ts b/packages/@tinacms/bridge/src/click-to-focus.ts
new file mode 100644
index 0000000000..5ff5e9f310
--- /dev/null
+++ b/packages/@tinacms/bridge/src/click-to-focus.ts
@@ -0,0 +1,90 @@
+/**
+ * Vanilla port of useTina's quick-edit click handler from
+ * packages/tinacms/src/react.tsx. Click capture stays off until the admin
+ * sends `{type:'quickEditEnabled', value:true}`, matching the React hook —
+ * a frame outside the admin can't silently swallow clicks before the
+ * admin opts in.
+ */
+import { getAdminOrigin, isFromAdmin } from './config';
+import { debug } from './debug';
+import {
+ QUICK_EDIT_BODY_CLASS as BODY_CLASS,
+ QUICK_EDIT_CSS,
+ QUICK_EDIT_STYLE_ID as STYLE_ID,
+} from './quick-edit-css';
+
+export function initClickToFocus(): void {
+ let enabled = false;
+
+ document.addEventListener(
+ 'click',
+ (event) => {
+ const target = event.target;
+ const tagName = target instanceof Element ? target.tagName : '?';
+ if (!enabled) {
+ debug('click ignored — quickEdit disabled', tagName);
+ return;
+ }
+ const fieldName = resolveFieldName(target);
+ if (!fieldName) {
+ debug('click ignored — no data-tina-field ancestor for', tagName);
+ return;
+ }
+ debug('click captured →', fieldName, '(target:', tagName, ')');
+ event.preventDefault();
+ event.stopPropagation();
+ window.parent.postMessage(
+ { type: 'field:selected', fieldName },
+ getAdminOrigin()
+ );
+ },
+ true
+ );
+
+ // Optional admin override — the React hook also installs / removes the
+ // visible outline based on this flag, so respect the visual side too.
+ window.addEventListener('message', (event) => {
+ if (!isFromAdmin(event)) return;
+ const message = event.data;
+ if (!message || message.type !== 'quickEditEnabled') return;
+ enabled = !!message.value;
+ if (enabled) installStyle();
+ else removeStyle();
+ });
+}
+
+function resolveFieldName(target: EventTarget | null): string | null {
+ const el = target instanceof Element ? target : null;
+ if (!el) return null;
+
+ const direct = readTinaField(el);
+ if (direct) return direct;
+
+ const ancestor = el.closest('[data-tina-field], [data-tina-field-overlay]');
+ if (!ancestor) return null;
+ return readTinaField(ancestor);
+}
+
+function readTinaField(el: Element): string | null {
+ for (const name of el.getAttributeNames()) {
+ if (name.startsWith('data-tina-field')) {
+ const value = el.getAttribute(name);
+ if (value) return value;
+ }
+ }
+ return null;
+}
+
+function installStyle(): void {
+ if (document.getElementById(STYLE_ID)) return;
+ const style = document.createElement('style');
+ style.id = STYLE_ID;
+ style.textContent = QUICK_EDIT_CSS;
+ document.head.appendChild(style);
+ document.body.classList.add(BODY_CLASS);
+}
+
+function removeStyle(): void {
+ document.getElementById(STYLE_ID)?.remove();
+ document.body.classList.remove(BODY_CLASS);
+}
diff --git a/packages/@tinacms/bridge/src/config.ts b/packages/@tinacms/bridge/src/config.ts
new file mode 100644
index 0000000000..b6c4dd85f5
--- /dev/null
+++ b/packages/@tinacms/bridge/src/config.ts
@@ -0,0 +1,34 @@
+/**
+ * Bridge runtime config. `init()` populates this once before any listener
+ * is wired, so the per-feature modules don't each need to thread the
+ * `adminOrigin` through their constructors.
+ */
+let configuredAdminOrigins: string[] = [];
+
+export function setAdminOrigin(origin: string | string[]): void {
+ configuredAdminOrigins = Array.isArray(origin) ? [...origin] : [origin];
+}
+
+/**
+ * Returns the canonical admin origin used as the `targetOrigin` for outbound
+ * postMessage. When multiple origins are configured the first entry wins —
+ * that's the deployment's primary admin host; the others are accepted for
+ * inbound traffic but the bridge still posts to the canonical one.
+ */
+export function getAdminOrigin(): string {
+ return configuredAdminOrigins[0] ?? '';
+}
+
+/**
+ * Returns true only for postMessage events that originated from the admin
+ * iframe parent — `event.origin` matches one of the configured admin
+ * origins AND `event.source` is the parent window. Both checks are
+ * required: origin alone leaves us open to sibling frames sharing the
+ * same origin, source alone leaves us open to cross-origin parents that
+ * happen to have a handle to our window.
+ */
+export function isFromAdmin(event: MessageEvent): boolean {
+ if (typeof window === 'undefined') return false;
+ if (!configuredAdminOrigins.includes(event.origin)) return false;
+ return event.source === window.parent;
+}
diff --git a/packages/@tinacms/bridge/src/data-store.ts b/packages/@tinacms/bridge/src/data-store.ts
new file mode 100644
index 0000000000..637f9489b8
--- /dev/null
+++ b/packages/@tinacms/bridge/src/data-store.ts
@@ -0,0 +1,35 @@
+import type { DataStore } from './types';
+
+/**
+ * Holds the latest resolved data per form id (keyed by `hashFromQuery`-style
+ * id). `seed()` populates the initial server-rendered payload silently so
+ * the bridge doesn't trigger a refresh on page load. `set()` records edits
+ * from the admin and fires subscribers; `firstUpdate` is true only for the
+ * first admin update per id (used by island-refresh to skip the debounce
+ * on cold-start so newly-created docs reach a populated state ASAP).
+ */
+export function initDataStore(): DataStore {
+ const data = new Map();
+ const updated = new Set();
+ const listeners = new Set<
+ (event: { id: string; firstUpdate: boolean }) => void
+ >();
+
+ return {
+ get: (id) => data.get(id),
+ seed(id, next) {
+ data.set(id, next);
+ },
+ set(id, next) {
+ const firstUpdate = !updated.has(id);
+ updated.add(id);
+ data.set(id, next);
+ for (const listener of listeners) listener({ id, firstUpdate });
+ },
+ ids: () => Array.from(data.keys()),
+ subscribe(listener) {
+ listeners.add(listener);
+ return () => listeners.delete(listener);
+ },
+ };
+}
diff --git a/packages/@tinacms/bridge/src/debug.ts b/packages/@tinacms/bridge/src/debug.ts
new file mode 100644
index 0000000000..dfaa850d72
--- /dev/null
+++ b/packages/@tinacms/bridge/src/debug.ts
@@ -0,0 +1,12 @@
+/**
+ * Lightweight debug logger. Always-on while the bridge stabilises so the
+ * postMessage handshake + island-refresh chain is visible from the iframe
+ * console without flipping a flag. Gate behind a query param later once
+ * the example reaches a steady state.
+ */
+const ENABLED = typeof window !== 'undefined';
+
+export function debug(...args: unknown[]): void {
+ if (!ENABLED) return;
+ console.log('[@tinacms/bridge]', ...args);
+}
diff --git a/packages/@tinacms/bridge/src/forms.ts b/packages/@tinacms/bridge/src/forms.ts
new file mode 100644
index 0000000000..bff126d1ab
--- /dev/null
+++ b/packages/@tinacms/bridge/src/forms.ts
@@ -0,0 +1,204 @@
+import { getAdminOrigin, isFromAdmin } from './config';
+import { debug } from './debug';
+import type { DataStore, FormPayload } from './types';
+
+/**
+ * Reads server-emitted form payloads from `[data-tina-form]` elements (one
+ * per query the page consumes), seeds the data-store, and tells the admin
+ * which forms this page hosts via `{type:'open', ...}`.
+ *
+ * The wire format is a JSON object stamped into the `data-tina-form`
+ * attribute. Astro's normal attribute escaping handles every dangerous
+ * character automatically — no manual encoding step on the server, no
+ * `set:html` foot-gun. The browser unescapes during parsing, so
+ * `el.dataset.tinaForm` returns the original JSON for `JSON.parse`.
+ *
+ * Re-posts each `open` until the admin acknowledges by sending an
+ * `updateData` for that id. The bridge boots faster than React, so the
+ * very first `open` can land before the admin's window-message handler
+ * is registered; without retry it would be silently dropped.
+ *
+ * `initForms` runs once per page load. `refreshForms` re-scans the DOM
+ * after a soft navigation (Astro view transitions, Turbo, htmx, etc.):
+ * it diffs the live payloads against the previously-mounted set, posts
+ * `close` for forms that disappeared, and `open` (with retry) for forms
+ * that appeared.
+ */
+const FORM_SELECTOR = '[data-tina-form]';
+const FORM_ATTR = 'data-tina-form';
+const RETRY_INTERVAL_MS = 250;
+const MAX_ATTEMPTS = 40; // 10s total — plenty for cold-start admins.
+
+interface FormsController {
+ store: DataStore;
+ /** Form ids currently mounted in the DOM. Diffed on each refresh. */
+ active: Map;
+ /** Ids the admin has acknowledged via `updateData`. Survives refreshes. */
+ acknowledged: Set;
+ /** Pending retry timer for the announce loop, if any. */
+ retryTimer: ReturnType | null;
+ /** Attempt counter for the current announce loop. */
+ attempts: number;
+}
+
+let controller: FormsController | null = null;
+
+export function initForms(store: DataStore): void {
+ if (controller) {
+ debug('initForms called twice; ignoring');
+ return;
+ }
+
+ controller = {
+ store,
+ active: new Map(),
+ acknowledged: new Set(),
+ retryTimer: null,
+ attempts: 0,
+ };
+
+ // One-time listeners. The ack handler stays bound for the lifetime of
+ // the iframe so subsequent refreshes share the same `acknowledged`
+ // set. The beforeunload handler closes whatever's mounted right now,
+ // so soft-nav close messages are handled by `refreshForms`'s diff.
+ window.addEventListener('message', onAck);
+ window.addEventListener('beforeunload', onBeforeUnload);
+
+ refreshForms();
+}
+
+/**
+ * Re-scan the DOM for form payloads after a soft navigation. Diff
+ * against the previous mount and post `close` / `open` for the delta.
+ *
+ * Safe to call even if the bridge isn't initialised — used for setups
+ * that wire `astro:page-load` unconditionally. No-op outside an iframe.
+ */
+export function refreshForms(): void {
+ if (!controller) {
+ debug('refreshForms called before initForms; ignoring');
+ return;
+ }
+
+ const next = readPayloads();
+ const nextIds = new Set(next.map((p) => p.id));
+
+ // Forms that left the page.
+ for (const [id] of controller.active) {
+ if (nextIds.has(id)) continue;
+ debug('posting close for', id);
+ window.parent.postMessage({ type: 'close', id }, getAdminOrigin());
+ controller.acknowledged.delete(id);
+ }
+
+ // Forms that arrived (or whose payload changed across a same-id remount).
+ for (const payload of next) {
+ controller.store.seed(payload.id, payload.data ?? {});
+ }
+
+ controller.active = new Map(next.map((p) => [p.id, p]));
+
+ // Restart the announce loop only when there's something unacked to
+ // announce. This is also the path the initial mount takes.
+ if (next.some((p) => !controller!.acknowledged.has(p.id))) {
+ startAnnounceLoop();
+ }
+
+ reportQuickEdit();
+}
+
+function readPayloads(): FormPayload[] {
+ const elements = document.querySelectorAll(FORM_SELECTOR);
+ const payloads: FormPayload[] = [];
+ for (const el of elements) {
+ const raw = el.getAttribute(FORM_ATTR);
+ if (!raw) continue;
+ try {
+ const payload = JSON.parse(raw) as FormPayload;
+ if (!payload.id || !payload.query) continue;
+ payloads.push(payload);
+ } catch (error) {
+ debug('failed to parse form payload', error);
+ }
+ }
+ debug('discovered', payloads.length, 'form(s)');
+ return payloads;
+}
+
+function onAck(event: MessageEvent) {
+ if (!isFromAdmin(event)) return;
+ const msg = event.data;
+ if (!msg || typeof msg !== 'object') return;
+ if (msg.type !== 'updateData' || typeof msg.id !== 'string') return;
+ if (!controller) return;
+ if (!controller.acknowledged.has(msg.id)) {
+ debug('admin acked form', msg.id);
+ controller.acknowledged.add(msg.id);
+ }
+}
+
+function onBeforeUnload() {
+ if (!controller) return;
+ for (const [id] of controller.active) {
+ window.parent.postMessage({ type: 'close', id }, getAdminOrigin());
+ }
+}
+
+function startAnnounceLoop() {
+ if (!controller) return;
+ if (controller.retryTimer) {
+ clearTimeout(controller.retryTimer);
+ controller.retryTimer = null;
+ }
+ controller.attempts = 0;
+ announce();
+}
+
+function announce() {
+ if (!controller) return;
+ controller.attempts++;
+
+ const pending: FormPayload[] = [];
+ for (const [id, payload] of controller.active) {
+ if (!controller.acknowledged.has(id)) pending.push(payload);
+ }
+
+ if (pending.length === 0) {
+ debug('all forms acked after', controller.attempts, 'attempt(s)');
+ controller.retryTimer = null;
+ return;
+ }
+ if (controller.attempts > MAX_ATTEMPTS) {
+ debug(
+ 'giving up after',
+ MAX_ATTEMPTS,
+ 'attempts; pending ids:',
+ pending.map((p) => p.id)
+ );
+ controller.retryTimer = null;
+ return;
+ }
+
+ for (const payload of pending) {
+ debug('posting open for', payload.id, 'attempt', controller.attempts);
+ window.parent.postMessage(
+ {
+ type: 'open',
+ id: payload.id,
+ query: payload.query,
+ variables: payload.variables,
+ data: payload.data,
+ },
+ getAdminOrigin()
+ );
+ }
+ controller.retryTimer = setTimeout(announce, RETRY_INTERVAL_MS);
+}
+
+export function reportQuickEdit(): void {
+ const hasMarkers = !!document.querySelector('[data-tina-field]');
+ window.parent.postMessage(
+ { type: 'quick-edit', value: hasMarkers },
+ getAdminOrigin()
+ );
+}
diff --git a/packages/@tinacms/bridge/src/index.ts b/packages/@tinacms/bridge/src/index.ts
new file mode 100644
index 0000000000..c5ffb5f2f0
--- /dev/null
+++ b/packages/@tinacms/bridge/src/index.ts
@@ -0,0 +1,93 @@
+/**
+ * @tinacms/bridge — vanilla JS bridge between the TinaCMS admin iframe and
+ * a non-React frontend.
+ *
+ * **Astro consumers should import from `@tinacms/astro/bridge` instead** —
+ * this package is the framework-agnostic core, re-exported by `@tinacms/astro`
+ * so Astro projects only install one TinaCMS package. Direct consumption of
+ * `@tinacms/bridge` is intended for Hugo, plain-HTML, Eleventy, and any other
+ * non-Astro / non-React frontend.
+ *
+ * Mirrors the postMessage protocol used by the React `useTina` hook in
+ * tinacms/react, but writes to the DOM by re-fetching opt-in server islands
+ * (`[data-tina-island]`) instead of reconciling React state. Stateless: the
+ * admin pushes already-resolved data via postMessage, and the bridge forwards
+ * it on island refetches via the `X-Tina-Preview` header. The canonical
+ * content store is never touched in edit mode.
+ */
+import { initClickToFocus } from './click-to-focus';
+import { setAdminOrigin } from './config';
+import { initDataStore } from './data-store';
+import { debug } from './debug';
+import { initForms, refreshForms } from './forms';
+import { initIslandRefresh } from './island-refresh';
+
+export interface BridgeOptions {
+ /**
+ * Per-island debounce for refetches triggered by subsequent edits.
+ * The first refetch after page load fires immediately so newly-created
+ * docs reach a populated state ASAP. Default 300ms.
+ */
+ debounceMs?: number;
+ /**
+ * Origin(s) of the TinaCMS admin parent. Inbound postMessage events are
+ * accepted only when `event.origin` matches one of these AND
+ * `event.source` is `window.parent`. Outbound posts use the first entry
+ * (or the single string) as `targetOrigin`.
+ *
+ * Defaults to `window.location.origin` — correct when the admin is
+ * mounted at `/admin` on the same host (the common case). Override when
+ * the admin runs on a different origin (cross-domain self-hosted
+ * deployments, Codespaces, Docker setups). Mirrors the role of
+ * `server.allowedOrigins` in `tina.config` for the dev server's CORS,
+ * but applied to the in-iframe postMessage channel instead of HTTP.
+ */
+ adminOrigin?: string | string[];
+}
+
+let initialized = false;
+
+export function init(options: BridgeOptions = {}): void {
+ if (initialized) return;
+ initialized = true;
+
+ // Outside an iframe (e.g. someone visiting /?tina-edit=1 directly) the
+ // bridge has nobody to talk to — bail without side effects.
+ if (typeof window === 'undefined' || window.parent === window) {
+ debug('not in an iframe; bridge is a no-op');
+ return;
+ }
+ debug('initialising in iframe');
+
+ const { debounceMs = 300, adminOrigin = window.location.origin } = options;
+ setAdminOrigin(adminOrigin);
+
+ const store = initDataStore();
+ initIslandRefresh(store, { debounceMs });
+ initClickToFocus();
+ // Forms register last so listeners are wired up before we announce
+ // ourselves to the admin and start receiving updateData replies.
+ initForms(store);
+}
+
+/**
+ * Re-scan the page for `[data-tina-form]` payloads after a soft
+ * navigation (Astro view transitions, Turbo, htmx, etc.). Posts `close`
+ * for forms that left and `open` for forms that appeared. Safe to call
+ * before `init()` — no-op when the bridge isn't running.
+ *
+ * Astro projects using `@tinacms/astro/integration` get this wired
+ * automatically (the middleware splices the bootstrap script that
+ * listens for `astro:page-load`). Sites consuming `@tinacms/bridge`
+ * directly need:
+ *
+ * ```ts
+ * import { init, refreshForms } from '@tinacms/bridge';
+ * init();
+ * document.addEventListener('astro:page-load', refreshForms);
+ * ```
+ */
+export { refreshForms };
+
+export { tinaField } from './tina-field';
+export type * from './types';
diff --git a/packages/@tinacms/bridge/src/island-refresh.ts b/packages/@tinacms/bridge/src/island-refresh.ts
new file mode 100644
index 0000000000..345a6b8477
--- /dev/null
+++ b/packages/@tinacms/bridge/src/island-refresh.ts
@@ -0,0 +1,125 @@
+import { isFromAdmin } from './config';
+import { debug } from './debug';
+import { reportQuickEdit } from './forms';
+import { PREVIEW_CONTENT_TYPE, type PreviewEnvelope } from './preview';
+import type { DataStore } from './types';
+
+/**
+ * Listens for `{type:'updateData', id, data}` from the admin and re-fetches
+ * every `[data-tina-island]` on the page with the unsaved data attached as
+ * a JSON POST body. The island endpoint reads the body via `readOverlay()`
+ * from `@tinacms/bridge/preview` and renders with overlay data instead of
+ * hitting the canonical content store.
+ *
+ * Why POST: HTTP headers are capped at ~8 KB (server-dependent) — large
+ * posts overflow easily — and are restricted to Latin-1 so UTF-8 content
+ * needs base64 padding. A POST body has neither limit and round-trips
+ * UTF-8 directly.
+ *
+ * The very first updateData fires immediately so newly-created docs leave
+ * the empty-template state ASAP. Subsequent updates collapse into a single
+ * debounced refetch — each refresh re-renders every island anyway, so a
+ * per-id timer would just fire N redundant times for the same DOM scan.
+ */
+export interface IslandRefreshOptions {
+ debounceMs: number;
+}
+
+const ISLAND_SELECTOR = '[data-tina-island]';
+const ENDPOINT_ATTR = 'data-tina-island';
+
+export function initIslandRefresh(
+ store: DataStore,
+ options: IslandRefreshOptions
+): void {
+ let pendingRefresh: ReturnType | null = null;
+
+ const refreshAll = () => {
+ const islands = document.querySelectorAll(ISLAND_SELECTOR);
+ for (const island of islands) {
+ void refreshIsland(island, store);
+ }
+ };
+
+ store.subscribe(({ firstUpdate }) => {
+ if (pendingRefresh) {
+ clearTimeout(pendingRefresh);
+ pendingRefresh = null;
+ }
+
+ if (firstUpdate) {
+ refreshAll();
+ return;
+ }
+
+ pendingRefresh = setTimeout(() => {
+ pendingRefresh = null;
+ refreshAll();
+ }, options.debounceMs);
+ });
+
+ window.addEventListener('message', (event) => {
+ if (!isFromAdmin(event)) return;
+ const message = event.data;
+ if (!message || typeof message !== 'object') return;
+
+ if (message.type === 'updateData' && typeof message.id === 'string') {
+ debug('updateData received for', message.id);
+ store.set(message.id, message.data ?? {});
+ }
+ });
+}
+
+async function refreshIsland(
+ island: HTMLElement,
+ store: DataStore
+): Promise {
+ const endpoint = island.getAttribute(ENDPOINT_ATTR);
+ if (!endpoint) return;
+
+ const overlay: PreviewEnvelope = {};
+ for (const id of store.ids()) {
+ const data = store.get(id);
+ if (data) overlay[id] = data;
+ }
+
+ try {
+ debug('refreshing island', endpoint);
+ const response = await fetch(endpoint, {
+ method: 'POST',
+ headers: { 'Content-Type': PREVIEW_CONTENT_TYPE },
+ body: JSON.stringify(overlay),
+ cache: 'no-store',
+ credentials: 'same-origin',
+ });
+ if (!response.ok) {
+ debug('island refetch failed', endpoint, response.status);
+ return;
+ }
+ const html = await response.text();
+ swapIslandHtml(island, html);
+ reportQuickEdit();
+ } catch (error) {
+ debug('island refetch error', endpoint, error);
+ }
+}
+
+function swapIslandHtml(island: HTMLElement, html: string): void {
+ const template = document.createElement('template');
+ template.innerHTML = html.trim();
+ const fragment = template.content;
+ const replacement = fragment.firstElementChild as HTMLElement | null;
+
+ if (replacement) {
+ for (const attr of Array.from(island.attributes)) {
+ if (attr.name === ENDPOINT_ATTR) continue;
+ island.removeAttribute(attr.name);
+ }
+ for (const attr of Array.from(replacement.attributes)) {
+ island.setAttribute(attr.name, attr.value);
+ }
+ island.innerHTML = replacement.innerHTML;
+ } else {
+ island.innerHTML = html;
+ }
+}
diff --git a/packages/@tinacms/bridge/src/metadata.ts b/packages/@tinacms/bridge/src/metadata.ts
new file mode 100644
index 0000000000..3333942342
--- /dev/null
+++ b/packages/@tinacms/bridge/src/metadata.ts
@@ -0,0 +1,91 @@
+/**
+ * Canonical content-source metadata helpers.
+ *
+ * `addMetadata` walks a query result and stamps every non-system object with
+ * `_content_source: { queryId, path }`. The pair is what `tinaField()` reads
+ * to build the `data-tina-field` markers the admin uses for click-to-focus.
+ *
+ * `hashFromQuery` derives the queryId from `JSON.stringify({ query, variables })`.
+ * Both ends of the wire (page render, admin sidebar) hash the same string so
+ * overlay updates address the same form.
+ *
+ * One source of truth for React (useTina), Astro (server-side overlay), and
+ * any future framework integration. Kept dependency-free so it runs in any
+ * runtime — browser, Node, edge.
+ */
+
+const SYSTEM_KEYS = new Set([
+ '__typename',
+ '_sys',
+ '_internalSys',
+ '_values',
+ '_internalValues',
+ '_content_source',
+ '_tina_metadata',
+]);
+
+export const addMetadata = (
+ id: string,
+ obj: T,
+ path: (string | number)[] = []
+): T => {
+ if (obj === null) return obj;
+ if (isScalarOrUndefined(obj)) return obj;
+ if (obj instanceof String) return obj.valueOf() as unknown as T;
+
+ if (Array.isArray(obj)) {
+ return obj.map((item, index) =>
+ addMetadata(id, item, [...path, index])
+ ) as unknown as T;
+ }
+
+ const next = {} as Record;
+ for (const [key, value] of Object.entries(obj as Record)) {
+ if (SYSTEM_KEYS.has(key)) {
+ next[key] = value;
+ } else {
+ next[key] = addMetadata(id, value, [...path, key]);
+ }
+ }
+
+ // Rich-text root nodes carry their own children traversal; tagging them
+ // with `_content_source` would shadow the field-level marker on the
+ // wrapping element.
+ if (
+ next &&
+ typeof next === 'object' &&
+ 'type' in next &&
+ next.type === 'root'
+ ) {
+ return next as unknown as T;
+ }
+
+ return { ...next, _content_source: { queryId: id, path } } as unknown as T;
+};
+
+function isScalarOrUndefined(value: unknown): boolean {
+ const type = typeof value;
+ if (type === 'string') return true;
+ if (type === 'number') return true;
+ if (type === 'boolean') return true;
+ if (type === 'undefined') return true;
+ if (value == null) return true;
+ if (value instanceof String) return true;
+ if (value instanceof Number) return true;
+ if (value instanceof Boolean) return true;
+ return false;
+}
+
+/**
+ * Rudimentary string hash. Both ends of the wire derive the queryId from
+ * the same JSON.stringify({ query, variables }) — collisions are theoretically
+ * possible but vanishingly rare in practice.
+ */
+export const hashFromQuery = (input: string): string => {
+ let hash = 0;
+ for (let i = 0; i < input.length; i++) {
+ const char = input.charCodeAt(i);
+ hash = ((hash << 5) - hash + char) & 0xffffffff;
+ }
+ return Math.abs(hash).toString(36);
+};
diff --git a/packages/@tinacms/bridge/src/preview.test.ts b/packages/@tinacms/bridge/src/preview.test.ts
new file mode 100644
index 0000000000..bb2ce72020
--- /dev/null
+++ b/packages/@tinacms/bridge/src/preview.test.ts
@@ -0,0 +1,220 @@
+import { describe, expect, it } from 'vitest';
+import {
+ PREVIEW_CONTENT_TYPE,
+ PREVIEW_HEADER,
+ readEnvelope,
+ readOverlay,
+} from './preview';
+
+/**
+ * Build a `Request` carrying an envelope, mirroring what the bridge
+ * sends from `island-refresh.ts`. Kept inline rather than imported so
+ * the test exercises the same wire format the consumer would see — if
+ * island-refresh changes its encoding, these tests will reveal it.
+ */
+function makeRequest(
+ envelope: Record,
+ options: { contentType?: string; body?: string } = {}
+): Request {
+ return new Request('http://example.com/tina-island/page', {
+ method: 'POST',
+ headers: { 'Content-Type': options.contentType ?? PREVIEW_CONTENT_TYPE },
+ body: options.body ?? JSON.stringify(envelope),
+ });
+}
+
+describe('preview transport contract', () => {
+ it('exports a stable header name and content-type', () => {
+ expect(PREVIEW_HEADER).toBe('X-Tina-Preview');
+ expect(PREVIEW_CONTENT_TYPE).toBe('application/x-tina-preview+json');
+ });
+});
+
+describe('readOverlay', () => {
+ it('returns the value for a matching query id', async () => {
+ const req = makeRequest({
+ abc123: { page: { title: 'Hello' } },
+ xyz789: { global: { name: 'Site' } },
+ });
+ expect(await readOverlay(req, 'abc123')).toEqual({
+ page: { title: 'Hello' },
+ });
+ });
+
+ it('returns undefined for an unknown query id', async () => {
+ const req = makeRequest({ abc123: { page: { title: 'Hello' } } });
+ expect(await readOverlay(req, 'missing')).toBeUndefined();
+ });
+
+ it('returns undefined when the content-type does not match', async () => {
+ const req = makeRequest(
+ { abc123: { x: 1 } },
+ { contentType: 'application/json' }
+ );
+ expect(await readOverlay(req, 'abc123')).toBeUndefined();
+ });
+
+ it('returns undefined for an empty body', async () => {
+ const req = makeRequest({}, { body: '' });
+ expect(await readOverlay(req, 'abc123')).toBeUndefined();
+ });
+
+ it('returns undefined for malformed JSON', async () => {
+ const req = makeRequest({}, { body: '{ not valid json' });
+ expect(await readOverlay(req, 'abc123')).toBeUndefined();
+ });
+});
+
+describe('readOverlay UTF-8 round-trip', () => {
+ it('preserves em-dash + smart quotes (the 431 / Latin-1 trigger)', async () => {
+ const value = {
+ title: 'A — B "C" — D',
+ excerpt: "It's a “smart-quote” world",
+ };
+ const req = makeRequest({ id: value });
+ expect(await readOverlay(req, 'id')).toEqual(value);
+ });
+
+ it('preserves accented characters', async () => {
+ const value = { name: 'Renée Müller', city: 'São Paulo' };
+ const req = makeRequest({ id: value });
+ expect(await readOverlay(req, 'id')).toEqual(value);
+ });
+
+ it('preserves emoji (4-byte UTF-8 sequences)', async () => {
+ const value = { reaction: '🚀✨🤖', flag: '🇺🇸' };
+ const req = makeRequest({ id: value });
+ expect(await readOverlay(req, 'id')).toEqual(value);
+ });
+
+ it('preserves CJK + RTL text', async () => {
+ const value = { jp: 'こんにちは', cn: '你好世界', he: 'שלום עולם' };
+ const req = makeRequest({ id: value });
+ expect(await readOverlay(req, 'id')).toEqual(value);
+ });
+});
+
+describe('readOverlay payload size + shape', () => {
+ it('handles bodies larger than the typical 8 KB header limit', async () => {
+ // 50 KB of UTF-8 — would have failed as a header (431) and would
+ // have failed as a non-base64 ISO-8859-1 string (TypeError).
+ const big = '— '.repeat(25_000);
+ const req = makeRequest({ id: { body: big } });
+ const overlay = await readOverlay<{ body: string }>(req, 'id');
+ expect(overlay?.body).toBe(big);
+ expect(overlay?.body.length).toBe(big.length);
+ });
+
+ it('preserves nested objects and arrays', async () => {
+ const value = {
+ page: {
+ blocks: [
+ {
+ __typename: 'Hero',
+ headline: 'A',
+ children: [{ type: 'p', children: [{ type: 'text', text: 'x' }] }],
+ },
+ { __typename: 'Cta', actions: [{ label: 'Go', link: '/x' }] },
+ ],
+ },
+ };
+ const req = makeRequest({ id: value });
+ expect(await readOverlay(req, 'id')).toEqual(value);
+ });
+
+ it('treats null values as present (not "missing")', async () => {
+ const req = makeRequest({ id: null });
+ expect(await readOverlay(req, 'id')).toBeNull();
+ });
+});
+
+describe('readEnvelope', () => {
+ it('returns the full envelope for callers that need every form', async () => {
+ const env = {
+ page_id: { page: { title: 'P' } },
+ global_id: { global: { theme: { color: 'blue' } } },
+ };
+ const req = makeRequest(env);
+ expect(await readEnvelope(req)).toEqual(env);
+ });
+
+ it('returns undefined when no preview content-type is present', async () => {
+ const req = new Request('http://example.com/tina-island/page', {
+ method: 'POST',
+ body: '{}',
+ });
+ expect(await readEnvelope(req)).toBeUndefined();
+ });
+});
+
+describe('content-type matching is permissive about charset', () => {
+ it('accepts content-type with a charset suffix', async () => {
+ const req = makeRequest(
+ { id: { x: 1 } },
+ { contentType: `${PREVIEW_CONTENT_TYPE}; charset=utf-8` }
+ );
+ expect(await readOverlay(req, 'id')).toEqual({ x: 1 });
+ });
+});
+
+/**
+ * The browser side of the protocol lives in island-refresh.ts and uses
+ * `fetch(endpoint, { method:'POST', headers:{'Content-Type': PREVIEW_CONTENT_TYPE},
+ * body: JSON.stringify(envelope) })`. These tests assemble that exact
+ * request shape and run it through `readOverlay` so an accidental change
+ * to either side breaks the contract.
+ */
+describe('full bridge → server round-trip', () => {
+ function bridgeRequest(envelope: Record): Request {
+ return new Request('http://example.com/tina-island/page', {
+ method: 'POST',
+ headers: { 'Content-Type': PREVIEW_CONTENT_TYPE },
+ body: JSON.stringify(envelope),
+ });
+ }
+
+ it('round-trips the multi-form payload the bridge sends', async () => {
+ const envelope = {
+ page_hash: {
+ page: {
+ blocks: [{ __typename: 'Hero', headline: 'Headline — em-dash' }],
+ },
+ },
+ global_hash: { global: { theme: { color: 'blue', font: 'sans' } } },
+ };
+ const req = bridgeRequest(envelope);
+
+ expect(await readOverlay(req.clone(), 'page_hash')).toEqual(
+ envelope.page_hash
+ );
+ expect(await readOverlay(req.clone(), 'global_hash')).toEqual(
+ envelope.global_hash
+ );
+ expect(await readOverlay(req.clone(), 'unknown_hash')).toBeUndefined();
+ });
+
+ it('survives the worst payload encountered in the wild (large UTF-8 post body)', async () => {
+ // Mirrors the shape that triggered HTTP 431 + Latin-1 errors in
+ // earlier transports: long rich-text body with em-dashes.
+ const richText = {
+ type: 'root',
+ children: Array.from({ length: 200 }, (_, i) => ({
+ type: 'p',
+ children: [
+ {
+ type: 'text',
+ text: `Paragraph ${i} — with an em-dash and "smart quotes"`,
+ },
+ ],
+ })),
+ };
+ const envelope = { id: { post: { _body: richText, title: 'Long post' } } };
+ const req = bridgeRequest(envelope);
+ const back = await readOverlay<{ post: { _body: typeof richText } }>(
+ req,
+ 'id'
+ );
+ expect(back?.post._body.children).toHaveLength(200);
+ expect(back?.post._body.children[0]).toEqual(richText.children[0]);
+ });
+});
diff --git a/packages/@tinacms/bridge/src/preview.ts b/packages/@tinacms/bridge/src/preview.ts
new file mode 100644
index 0000000000..ba0a716ff8
--- /dev/null
+++ b/packages/@tinacms/bridge/src/preview.ts
@@ -0,0 +1,62 @@
+/**
+ * Shared preview-protocol helpers for both ends of the X-Tina-Preview
+ * channel. The bridge POSTs island refetches with a JSON body of shape
+ *
+ * { [queryId]: data, ... }
+ *
+ * Server-side island handlers call `readOverlay(request, queryId)` to
+ * fetch the overlay data for their own query without having to know the
+ * transport details (POST body vs header, JSON vs base64-encoded JSON).
+ *
+ * Runs in Node (Astro server endpoints, Hugo plugins, etc.) — no DOM
+ * dependencies. The browser-side encoder lives in island-refresh.ts.
+ */
+
+export const PREVIEW_HEADER = 'X-Tina-Preview';
+export const PREVIEW_CONTENT_TYPE = 'application/x-tina-preview+json';
+/**
+ * Hard cap on overlay envelope size. The bridge POSTs JSON-encoded form
+ * data — a 1 MB envelope already represents a wildly oversized document —
+ * so any larger payload is treated as malformed.
+ */
+const MAX_ENVELOPE_BYTES = 1_000_000;
+
+export interface PreviewEnvelope {
+ [queryId: string]: unknown;
+}
+
+/**
+ * Read the overlay envelope for a given query id from an incoming
+ * request. Returns `undefined` if no overlay is present (production
+ * traffic, or an island refetch with no matching id).
+ */
+export async function readOverlay(
+ request: Request,
+ queryId: string
+): Promise {
+ const envelope = await readEnvelope(request);
+ if (!envelope) return undefined;
+ const value = envelope[queryId];
+ return value === undefined ? undefined : (value as T);
+}
+
+/**
+ * Read and parse the full overlay envelope (every form on the page),
+ * for callers that want to inspect the raw payload.
+ */
+export async function readEnvelope(
+ request: Request
+): Promise {
+ const contentType = request.headers.get('content-type') ?? '';
+ if (!contentType.includes(PREVIEW_CONTENT_TYPE)) return undefined;
+ const declaredLength = Number(request.headers.get('content-length') ?? '0');
+ if (declaredLength > MAX_ENVELOPE_BYTES) return undefined;
+ try {
+ const text = await request.text();
+ if (!text) return undefined;
+ if (text.length > MAX_ENVELOPE_BYTES) return undefined;
+ return JSON.parse(text) as PreviewEnvelope;
+ } catch {
+ return undefined;
+ }
+}
diff --git a/packages/@tinacms/bridge/src/quick-edit-css.ts b/packages/@tinacms/bridge/src/quick-edit-css.ts
new file mode 100644
index 0000000000..707549212c
--- /dev/null
+++ b/packages/@tinacms/bridge/src/quick-edit-css.ts
@@ -0,0 +1,40 @@
+/**
+ * Shared CSS for the quick-edit outline. Used by both the vanilla bridge
+ * (click-to-focus.ts) and the React `useTina` hook (packages/tinacms/src/react.tsx),
+ * so the visible affordance is identical regardless of which integration
+ * the consumer is running.
+ */
+export const QUICK_EDIT_CSS = `
+ [data-tina-field] {
+ outline: 2px dashed rgba(34,150,254,0.5);
+ transition: box-shadow ease-out 150ms;
+ }
+ [data-tina-field]:hover {
+ box-shadow: inset 100vi 100vh rgba(34,150,254,0.3);
+ outline: 2px solid rgba(34,150,254,1);
+ cursor: pointer;
+ }
+ [data-tina-field-overlay] {
+ outline: 2px dashed rgba(34,150,254,0.5);
+ position: relative;
+ }
+ [data-tina-field-overlay]:hover {
+ cursor: pointer;
+ outline: 2px solid rgba(34,150,254,1);
+ }
+ [data-tina-field-overlay]::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ z-index: 20;
+ transition: opacity ease-out 150ms;
+ background-color: rgba(34,150,254,0.3);
+ opacity: 0;
+ }
+ [data-tina-field-overlay]:hover::after {
+ opacity: 1;
+ }
+`;
+
+export const QUICK_EDIT_BODY_CLASS = '__tina-quick-editing-enabled';
+export const QUICK_EDIT_STYLE_ID = '__tina-bridge-quick-edit-style';
diff --git a/packages/@tinacms/bridge/src/tina-field.ts b/packages/@tinacms/bridge/src/tina-field.ts
new file mode 100644
index 0000000000..0d6f3dbf70
--- /dev/null
+++ b/packages/@tinacms/bridge/src/tina-field.ts
@@ -0,0 +1,45 @@
+/**
+ * Generate a field identifier for Tina to associate DOM elements with form fields.
+ * Format: "queryId---path.to.field" or "queryId---path.to.array.index"
+ *
+ * Canonical implementation. The React-side `tinacms/tina-field` and Astro-side
+ * `@tinacms/astro/tina-field` both re-export from here so non-React frontends
+ * can consume it without pulling tinacms (and its React deps) into their bundle.
+ */
+export const tinaField = <
+ T extends
+ | {
+ _content_source?: {
+ queryId: string;
+ path: (number | string)[];
+ };
+ }
+ | Record
+ | null
+ | undefined,
+>(
+ object: T,
+ property?: keyof Omit, '__typename' | '_sys'>,
+ index?: number
+): string => {
+ const contentSource = object?._content_source as
+ | { queryId: string; path: (number | string)[] }
+ | undefined;
+
+ if (!contentSource) {
+ return '';
+ }
+
+ const { queryId, path } = contentSource;
+
+ if (!property) {
+ return `${queryId}---${path.join('.')}`;
+ }
+
+ const fullPath =
+ typeof index === 'number'
+ ? [...path, property, index]
+ : [...path, property];
+
+ return `${queryId}---${fullPath.join('.')}`;
+};
diff --git a/packages/@tinacms/bridge/src/types.ts b/packages/@tinacms/bridge/src/types.ts
new file mode 100644
index 0000000000..66fca203b1
--- /dev/null
+++ b/packages/@tinacms/bridge/src/types.ts
@@ -0,0 +1,40 @@
+/**
+ * postMessage protocol shared between this bridge and the TinaCMS admin
+ * (packages/@tinacms/app). Mirrors the messages emitted by useTina in
+ * packages/tinacms/src/react.tsx so the admin sees identical traffic.
+ */
+export type BridgeOutgoing =
+ | { type: 'isEditMode' }
+ | { type: 'open'; id: string; query: string; variables: object; data: object }
+ | { type: 'close'; id: string }
+ | { type: 'url-changed' }
+ | { type: 'field:selected'; fieldName: string }
+ | { type: 'quick-edit'; value: boolean }
+ | { type: 'user-select-form'; formId: string };
+
+export type BridgeIncoming =
+ | { type: 'tina:editMode' }
+ | { type: 'updateData'; id: string; data: object }
+ | { type: 'quickEditEnabled'; value: boolean };
+
+export interface FormPayload {
+ id: string;
+ query: string;
+ variables: object;
+ data: object;
+}
+
+export interface DataStore {
+ /** Latest resolved data per form id. */
+ get(id: string): object | undefined;
+ /** Populate without notifying subscribers (used for the initial seed). */
+ seed(id: string, data: object): void;
+ /** Replace cached data for a form and notify subscribers. */
+ set(id: string, data: object): void;
+ /** All known form ids. */
+ ids(): string[];
+ /** Subscribe to data updates. Returns unsubscribe. */
+ subscribe(
+ listener: (event: { id: string; firstUpdate: boolean }) => void
+ ): () => void;
+}
diff --git a/packages/@tinacms/bridge/tsconfig.json b/packages/@tinacms/bridge/tsconfig.json
new file mode 100644
index 0000000000..bdbcd66e3a
--- /dev/null
+++ b/packages/@tinacms/bridge/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../../base.tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "rootDir": "src",
+ "strict": true,
+ "skipLibCheck": true,
+ "noImplicitAny": true,
+ "noUncheckedIndexedAccess": true,
+ "noFallthroughCasesInSwitch": true,
+ "moduleResolution": "bundler",
+ "module": "esnext",
+ "target": "esnext",
+ "lib": ["ESNext", "DOM", "DOM.Iterable"]
+ },
+ "exclude": ["node_modules", "dist"],
+ "include": ["src"]
+}
diff --git a/packages/@tinacms/bridge/vitest.config.ts b/packages/@tinacms/bridge/vitest.config.ts
new file mode 100644
index 0000000000..c86cb255ac
--- /dev/null
+++ b/packages/@tinacms/bridge/vitest.config.ts
@@ -0,0 +1,10 @@
+///
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ test: {
+ globals: true,
+ environment: 'happy-dom',
+ include: ['src/**/*.test.ts'],
+ },
+});
diff --git a/packages/@tinacms/mdx/src/next/stringify/to-markdown.ts b/packages/@tinacms/mdx/src/next/stringify/to-markdown.ts
index fd2b6dcff9..7fa77563ed 100644
--- a/packages/@tinacms/mdx/src/next/stringify/to-markdown.ts
+++ b/packages/@tinacms/mdx/src/next/stringify/to-markdown.ts
@@ -9,6 +9,12 @@ import { getFieldPatterns } from '../util';
export const toTinaMarkdown = (tree: Md.Root, field: RichTextField) => {
const patterns = getFieldPatterns(field);
+ // When templates are declared without a `match` pattern, they are JSX-style
+ // components — e.g. `` — and `<` should pass through the
+ // round-trip un-escaped, matching the behaviour of `skipEscaping: 'html'`.
+ const hasJsxTemplates = (field.templates ?? []).some(
+ (t) => typeof t !== 'string' && !t.match
+ );
/**
*
* Escaping elements which we can't accound for (eg. `<`) is usually good. But when the rich-text other tooling
@@ -36,7 +42,7 @@ export const toTinaMarkdown = (tree: Md.Root, field: RichTextField) => {
if (field.parser.skipEscaping === 'all') {
return node.value;
}
- if (field.parser.skipEscaping === 'html') {
+ if (field.parser.skipEscaping === 'html' || hasJsxTemplates) {
// Remove this character from the unsafe list, and then
// proceed with the original text handler
context.unsafe = context.unsafe.filter((unsafeItem) => {
diff --git a/packages/@tinacms/mdx/src/repro-large-file.test.ts b/packages/@tinacms/mdx/src/repro-large-file.test.ts
new file mode 100644
index 0000000000..3bbaeb67c9
--- /dev/null
+++ b/packages/@tinacms/mdx/src/repro-large-file.test.ts
@@ -0,0 +1,117 @@
+import { describe, it, expect } from 'vitest';
+import type { RichTextField } from '@tinacms/schema-tools';
+import { parseMDX } from './parse';
+import { serializeMDX } from './stringify';
+
+const field: RichTextField = {
+ name: '_body',
+ type: 'rich-text',
+ parser: { type: 'mdx' },
+ templates: [
+ {
+ name: 'BlockQuote',
+ label: 'Block Quote',
+ fields: [
+ { name: 'children', label: 'Quote', type: 'rich-text' },
+ { name: 'authorName', label: 'Author', type: 'string' },
+ ],
+ },
+ {
+ name: 'DateTime',
+ label: 'Date & Time',
+ inline: true,
+ fields: [
+ {
+ name: 'format',
+ label: 'Format',
+ type: 'string',
+ options: ['utc', 'iso', 'local'],
+ },
+ ],
+ },
+ {
+ name: 'NewsletterSignup',
+ label: 'Newsletter Sign Up',
+ fields: [
+ { name: 'children', label: 'CTA', type: 'rich-text' },
+ { name: 'placeholder', label: 'Placeholder', type: 'string' },
+ { name: 'buttonText', label: 'Button Text', type: 'string' },
+ { name: 'disclaimer', label: 'Disclaimer', type: 'rich-text' },
+ ],
+ },
+ ],
+};
+
+const SECTION = `
+# Vote For Pedro
+
+Hello, the current date is . Some text after.
+
+***
+
+\`\`\`graphql
+query MyQuery($relativePath: String!) {
+ page(relativePath: $relativePath) {
+ title
+ }
+}
+\`\`\`
+
+> A blockquote.
+
+
+
+Some more text.
+
+
+ We care. Read our [Privacy Policy](http://example.com).
+ >}
+>
+ ## Stay in touch!
+
+ Anim aute id magna aliqua.
+
+
+### A list heading
+
+* item 1
+* item 2
+
+***
+
+
+ How much you wanna bet?
+
+`;
+
+describe('large-file round trip', () => {
+ it('preserves the first DateTime inline embed', () => {
+ const input = SECTION + SECTION; // two sections, like the real file
+ const tree = parseMDX(input, field, (v) => v);
+ const result = serializeMDX(tree, field, (v) => v);
+ const out = typeof result === 'string' ? result : '';
+
+ const datetimeCount = (out.match(/ {
+ const input = SECTION;
+ const tree = parseMDX(input, field, (v) => v);
+ const result = serializeMDX(tree, field, (v) => v);
+ const out = typeof result === 'string' ? result : '';
+
+ expect(out).not.toContain('\\ {
+ const tree = parseMDX(SECTION, field, (v) => v);
+ // print so we can inspect what the parser thinks the first paragraph is
+ // eslint-disable-next-line no-console
+ console.log(JSON.stringify(tree, null, 2));
+ });
+});
diff --git a/packages/tinacms/package.json b/packages/tinacms/package.json
index 414feebbc5..fa83f9b00d 100644
--- a/packages/tinacms/package.json
+++ b/packages/tinacms/package.json
@@ -10,6 +10,8 @@
"./dist/client": "./dist/client.js",
"./react": "./dist/react.js",
"./dist/react": "./dist/react.js",
+ "./tina-field": "./dist/tina-field.js",
+ "./dist/tina-field": "./dist/tina-field.js",
"./dist/rich-text": "./dist/rich-text/index.js",
"./dist/rich-text/static": "./dist/rich-text/static.js",
"./dist/rich-text/prism": "./dist/rich-text/prism.js"
@@ -24,6 +26,7 @@
"src/rich-text/static.tsx",
"src/rich-text/prism.tsx",
"src/react.tsx",
+ "src/tina-field.ts",
{
"name": "src/client.ts",
"target": "node"
@@ -59,6 +62,7 @@
"@radix-ui/react-tooltip": "catalog:",
"@react-hook/window-size": "catalog:",
"@tanstack/react-table": "^8.21.3",
+ "@tinacms/bridge": "workspace:*",
"@tinacms/mdx": "workspace:*",
"@tinacms/schema-tools": "workspace:*",
"@tinacms/search": "workspace:*",
diff --git a/packages/tinacms/src/react.tsx b/packages/tinacms/src/react.tsx
index af65ea0af8..a29ad02922 100644
--- a/packages/tinacms/src/react.tsx
+++ b/packages/tinacms/src/react.tsx
@@ -1,5 +1,9 @@
+import { addMetadata, hashFromQuery } from '@tinacms/bridge/metadata';
+import { QUICK_EDIT_CSS } from '@tinacms/bridge/quick-edit-css';
import React from 'react';
+export { addMetadata, hashFromQuery };
+
export function useTina(props: {
query: string;
variables: object;
@@ -40,37 +44,7 @@ export function useTina(props: {
if (quickEditEnabled) {
const style = document.createElement('style');
style.type = 'text/css';
- style.textContent = `
- [data-tina-field] {
- outline: 2px dashed rgba(34,150,254,0.5);
- transition: box-shadow ease-out 150ms;
- }
- [data-tina-field]:hover {
- box-shadow: inset 100vi 100vh rgba(34,150,254,0.3);
- outline: 2px solid rgba(34,150,254,1);
- cursor: pointer;
- }
- [data-tina-field-overlay] {
- outline: 2px dashed rgba(34,150,254,0.5);
- position: relative;
- }
- [data-tina-field-overlay]:hover {
- cursor: pointer;
- outline: 2px solid rgba(34,150,254,1);
- }
- [data-tina-field-overlay]::after {
- content: '';
- position: absolute;
- inset: 0;
- z-index: 20;
- transition: opacity ease-out 150ms;
- background-color: rgba(34,150,254,0.3);
- opacity: 0;
- }
- [data-tina-field-overlay]:hover::after {
- opacity: 1;
- }
- `;
+ style.textContent = QUICK_EDIT_CSS;
document.head.appendChild(style);
document.body.classList.add('__tina-quick-editing-enabled');
@@ -102,21 +76,11 @@ export function useTina(props: {
}
}
}
- if (fieldName) {
- if (isInTinaIframe) {
- parent.postMessage(
- { type: 'field:selected', fieldName: fieldName },
- window.location.origin
- );
- } else {
- // if (preview?.redirect) {
- // const tinaAdminBasePath = preview.redirect.startsWith('/')
- // ? preview.redirect
- // : `/${preview.redirect}`
- // const tinaAdminPath = `${tinaAdminBasePath}/index.html#/~${window.location.pathname}?active-field=${fieldName}`
- // window.location.assign(tinaAdminPath)
- // }
- }
+ if (fieldName && isInTinaIframe) {
+ parent.postMessage(
+ { type: 'field:selected', fieldName: fieldName },
+ window.location.origin
+ );
}
}
document.addEventListener('click', mouseDownHandler, true);
@@ -194,149 +158,4 @@ export function useEditState(): { edit: boolean } {
return { edit } as any;
}
-/**
- * Grab the field name for the given attribute
- * to signal to Tina which DOM element the field
- * is working with.
- */
-/**
- * Generate a field identifier for Tina to associate DOM elements with form fields.
- * Format: "queryId---path.to.field" or "queryId---path.to.array.index"
- */
-export const tinaField = <
- T extends
- | {
- _content_source?: {
- queryId: string;
- path: (number | string)[];
- };
- }
- | Record
- | null
- | undefined,
->(
- object: T,
- property?: keyof Omit, '__typename' | '_sys'>,
- index?: number
-): string => {
- const contentSource = object?._content_source as
- | { queryId: string; path: (number | string)[] }
- | undefined;
-
- if (!contentSource) {
- return '';
- }
-
- const { queryId, path } = contentSource;
-
- // Base path without property
- if (!property) {
- return `${queryId}---${path.join('.')}`;
- }
-
- // Build full path with property and optional index
- const fullPath =
- typeof index === 'number'
- ? [...path, property, index]
- : [...path, property];
-
- return `${queryId}---${fullPath.join('.')}`;
-};
-
-/**
- * FIX: This function is updated to be more robust. It explicitly checks for
- * `null` and `String` objects to prevent them from being processed as
- * iterable objects, which is the root cause of the "Objects are not valid
- * as a React child" error.
- */
-export const addMetadata = (
- id: string,
- obj: T,
- path: (string | number)[] = []
-): T => {
- // Guard against null values, which have a typeof 'object'
- if (obj === null) {
- return obj;
- }
-
- // Guard against primitive values
- if (isScalarOrUndefined(obj)) {
- return obj;
- }
-
- // Guard against String objects, returning their primitive value.
- if (obj instanceof String) {
- return obj.valueOf() as unknown as T;
- }
-
- if (Array.isArray(obj)) {
- return obj.map((item, index) =>
- addMetadata(id, item, [...path, index])
- ) as unknown as T;
- }
-
- const transformedObj = {} as T;
- for (const [key, value] of Object.entries(obj)) {
- const currentPath = [...path, key];
-
- // Safely skip system keys and copy them over without recursion
- if (
- [
- '__typename',
- '_sys',
- '_internalSys',
- '_values',
- '_internalValues',
- '_content_source',
- '_tina_metadata',
- ].includes(key)
- ) {
- transformedObj[key] = value;
- } else {
- transformedObj[key] = addMetadata(id, value, currentPath);
- }
- }
-
- if (
- transformedObj &&
- typeof transformedObj === 'object' &&
- 'type' in transformedObj &&
- (transformedObj as { type?: unknown }).type === 'root'
- ) {
- return transformedObj;
- }
-
- return { ...transformedObj, _content_source: { queryId: id, path } };
-};
-
-function isScalarOrUndefined(value: unknown) {
- const type = typeof value;
- if (type === 'string') return true;
- if (type === 'number') return true;
- if (type === 'boolean') return true;
- if (type === 'undefined') return true;
-
- if (value == null) return true;
- if (value instanceof String) return true;
- if (value instanceof Number) return true;
- if (value instanceof Boolean) return true;
-
- return false;
-}
-
-/**
- * This is a pretty rudimentary approach to hashing the query and variables to
- * ensure we treat multiple queries on the page uniquely. It's possible
- * that we would have collisions, and I'm not sure of the likeliness but seems
- * like it'd be rare.
- */
-export const hashFromQuery = (input: string) => {
- let hash = 0;
- for (let i = 0; i < input.length; i++) {
- const char = input.charCodeAt(i);
- hash = ((hash << 5) - hash + char) & 0xffffffff; // Apply bitwise AND to ensure non-negative value
- }
- const nonNegativeHash = Math.abs(hash);
- const alphanumericHash = nonNegativeHash.toString(36);
- return alphanumericHash;
-};
+export { tinaField } from './tina-field';
diff --git a/packages/tinacms/src/tina-field.ts b/packages/tinacms/src/tina-field.ts
new file mode 100644
index 0000000000..4877a74542
--- /dev/null
+++ b/packages/tinacms/src/tina-field.ts
@@ -0,0 +1,5 @@
+/**
+ * Re-export of the canonical `tinaField` helper from `@tinacms/bridge`.
+ * Kept here so `tinacms/tina-field` consumers don't need to switch imports.
+ */
+export { tinaField } from '@tinacms/bridge/tina-field';
diff --git a/packages/tinacms/src/toolkit/fields/plugins/mdx-field-plugin/plate/plugins/ui/components.tsx b/packages/tinacms/src/toolkit/fields/plugins/mdx-field-plugin/plate/plugins/ui/components.tsx
index 8fc8b5bcf0..c04ad8f602 100644
--- a/packages/tinacms/src/toolkit/fields/plugins/mdx-field-plugin/plate/plugins/ui/components.tsx
+++ b/packages/tinacms/src/toolkit/fields/plugins/mdx-field-plugin/plate/plugins/ui/components.tsx
@@ -88,120 +88,137 @@ const HighlightLeaf = ({
);
};
-export const Components = () => {
- return {
- [SlashInputPlugin.key]: SlashInputElement,
- [HEADING_KEYS.h1]: ({
- attributes,
- editor,
- element,
+type HeadingComponentProps = {
+ attributes: React.HTMLAttributes;
+ children: React.ReactNode;
+ className?: string;
+};
+
+const Heading1 = ({
+ attributes,
+ children,
+ className,
+}: HeadingComponentProps) => (
+ (
-
- ),
- [HEADING_KEYS.h2]: ({
- attributes,
- editor,
- element,
+ 'text-4xl mb-4 last:mb-0 mt-6 first:mt-0 font-libre-baskerville'
+ )}
+ >
+ {children}
+
+);
+
+const Heading2 = ({
+ attributes,
+ children,
+ className,
+}: HeadingComponentProps) => (
+ (
-
- ),
- [HEADING_KEYS.h3]: ({
- attributes,
- editor,
- element,
+ 'text-3xl mb-4 last:mb-0 mt-6 first:mt-0 font-libre-baskerville'
+ )}
+ >
+ {children}
+
+);
+
+const Heading3 = ({
+ attributes,
+ children,
+ className,
+}: HeadingComponentProps) => (
+ (
-
- ),
- [HEADING_KEYS.h4]: ({
- attributes,
- editor,
- element,
+ 'text-2xl mb-4 last:mb-0 mt-6 first:mt-0 font-libre-baskerville'
+ )}
+ >
+ {children}
+
+);
+
+const Heading4 = ({
+ attributes,
+ children,
+ className,
+}: HeadingComponentProps) => (
+ (
-
- ),
- /** Tailwind prose doesn't style h5 and h6 elements */
- [HEADING_KEYS.h5]: ({
- attributes,
- editor,
- element,
+ 'text-xl mb-4 last:mb-0 mt-6 first:mt-0 font-libre-baskerville'
+ )}
+ >
+ {children}
+
+);
+
+/** Tailwind prose doesn't style h5 and h6 elements */
+const headerSerifStyle: React.CSSProperties = {
+ fontFamily: "'Libre Baskerville', serif",
+ fontWeight: '400',
+};
+
+const Heading5 = ({
+ attributes,
+ children,
+ className,
+}: HeadingComponentProps) => (
+ (
-
- ),
- [HEADING_KEYS.h6]: ({
- attributes,
- editor,
- element,
+ 'text-lg mb-4 last:mb-0 mt-6 first:mt-0'
+ )}
+ style={headerSerifStyle}
+ >
+ {children}
+
+);
+
+const Heading6 = ({
+ attributes,
+ children,
+ className,
+}: HeadingComponentProps) => (
+ (
-
- ),
+ 'text-base mb-4 last:mb-0 mt-6 first:mt-0'
+ )}
+ style={headerSerifStyle}
+ >
+ {children}
+
+);
+
+export const Components = () => {
+ return {
+ [SlashInputPlugin.key]: SlashInputElement,
+ [HEADING_KEYS.h1]: Heading1,
+ [HEADING_KEYS.h2]: Heading2,
+ [HEADING_KEYS.h3]: Heading3,
+ [HEADING_KEYS.h4]: Heading4,
+ [HEADING_KEYS.h5]: Heading5,
+ [HEADING_KEYS.h6]: Heading6,
[ParagraphPlugin.key]: ParagraphElement,
[BlockquotePlugin.key]: BlockquoteElement,
[CodeBlockPlugin.key]: CodeBlockElement,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5be0b34f57..6513834c02 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -691,7 +691,7 @@ importers:
version: 4.0.3
pretty-quick:
specifier: 'catalog:'
- version: 3.3.1(prettier@2.8.8)
+ version: 3.3.1(prettier@3.8.3)
turbo:
specifier: 'catalog:'
version: 2.6.3
@@ -700,19 +700,19 @@ importers:
version: 5.9.3
vite:
specifier: ^4.5.14
- version: 4.5.14(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 4.5.14(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
vitest:
specifier: ^2.1.9
- version: 2.1.9(@types/node@22.19.17)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 2.1.9(@types/node@22.19.17)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
examples/astro/kitchen-sink:
dependencies:
'@astrojs/mdx':
specifier: ^4.3.0
- version: 4.3.14(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))
+ version: 4.3.14(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))
'@astrojs/react':
specifier: ^4.4.0
- version: 4.4.2(@types/node@25.1.0)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(jiti@2.6.1)(lightningcss@1.31.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ version: 4.4.2(@types/node@25.1.0)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(jiti@2.6.1)(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
'@tailwindcss/typography':
specifier: 'catalog:'
version: 0.5.19(tailwindcss@4.2.1)
@@ -721,7 +721,7 @@ importers:
version: link:../../../packages/@tinacms/datalayer
astro:
specifier: ^5.16.0
- version: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
+ version: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
clsx:
specifier: ^2.1.1
version: 2.1.1
@@ -787,6 +787,88 @@ importers:
specifier: ^5.7.3
version: 5.9.3
+ examples/astro/visual-editing:
+ dependencies:
+ '@astrojs/mdx':
+ specifier: ^4.3.0
+ version: 4.3.14(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))
+ '@astrojs/node':
+ specifier: ^9.0.0
+ version: 9.5.5(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))
+ '@tailwindcss/typography':
+ specifier: 'catalog:'
+ version: 0.5.19(tailwindcss@4.2.1)
+ '@tailwindcss/vite':
+ specifier: ^4.2.1
+ version: 4.2.4(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
+ '@tinacms/astro':
+ specifier: workspace:*
+ version: link:../../../packages/@tinacms/astro
+ '@tinacms/datalayer':
+ specifier: workspace:*
+ version: link:../../../packages/@tinacms/datalayer
+ '@tinacms/mdx':
+ specifier: workspace:*
+ version: link:../../../packages/@tinacms/mdx
+ astro:
+ specifier: ^5.16.0
+ version: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
+ clsx:
+ specifier: ^2.1.1
+ version: 2.1.1
+ graphql:
+ specifier: ^15.10.1
+ version: 15.10.1
+ react-icons:
+ specifier: ^4.12.0
+ version: 4.12.0(react@18.3.1)
+ tailwind-merge:
+ specifier: ^2.6.0
+ version: 2.6.0
+ tailwindcss:
+ specifier: ^4.0.0
+ version: 4.2.1
+ devDependencies:
+ '@astrojs/check':
+ specifier: ^0.9.9
+ version: 0.9.9(prettier@3.8.3)(typescript@5.9.3)
+ '@biomejs/biome':
+ specifier: 'catalog:'
+ version: 1.9.4
+ '@playwright/test':
+ specifier: 'catalog:'
+ version: 1.57.0
+ '@tinacms/app':
+ specifier: workspace:*
+ version: link:../../../packages/@tinacms/app
+ '@tinacms/cli':
+ specifier: workspace:*
+ version: link:../../../packages/@tinacms/cli
+ '@tinacms/scripts':
+ specifier: workspace:*
+ version: link:../../../packages/@tinacms/scripts
+ '@types/node':
+ specifier: ^25.1.0
+ version: 25.1.0
+ '@types/react':
+ specifier: ^18.3.0
+ version: 18.3.27
+ cross-env:
+ specifier: ^7.0.3
+ version: 7.0.3
+ react:
+ specifier: ^18.3.1
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.3.1
+ version: 18.3.1(react@18.3.1)
+ tinacms:
+ specifier: workspace:*
+ version: link:../../../packages/tinacms
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+
examples/hugo/kitchen-sink:
dependencies:
'@tailwindcss/typography':
@@ -1080,7 +1162,7 @@ importers:
version: 18.3.7(@types/react@18.3.27)
'@vitejs/plugin-react':
specifier: ^4.3.0
- version: 4.7.0(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
+ version: 4.7.0(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
autoprefixer:
specifier: 'catalog:'
version: 10.4.23(postcss@8.5.6)
@@ -1098,7 +1180,7 @@ importers:
version: 5.9.3
vite:
specifier: ^6.0.0
- version: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ version: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
packages/@tinacms/app:
dependencies:
@@ -1155,6 +1237,31 @@ importers:
specifier: 'catalog:'
version: 18.3.7(@types/react@18.3.27)
+ packages/@tinacms/astro:
+ dependencies:
+ '@tinacms/bridge':
+ specifier: workspace:*
+ version: link:../bridge
+ devDependencies:
+ '@tinacms/scripts':
+ specifier: workspace:*
+ version: link:../scripts
+ '@types/node':
+ specifier: ^22.13.1
+ version: 22.19.17
+ astro:
+ specifier: ^5.16.0
+ version: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vite:
+ specifier: ^6.0.0
+ version: 6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vitest:
+ specifier: ^3.0.0
+ version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@15.10.2)(jiti@2.6.1)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+
packages/@tinacms/auth:
devDependencies:
'@tinacms/scripts':
@@ -1176,6 +1283,27 @@ importers:
specifier: ^5.7.3
version: 5.9.3
+ packages/@tinacms/bridge:
+ devDependencies:
+ '@tinacms/scripts':
+ specifier: workspace:*
+ version: link:../scripts
+ '@types/node':
+ specifier: ^22.13.1
+ version: 22.19.17
+ happy-dom:
+ specifier: 'catalog:'
+ version: 15.10.2
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vite:
+ specifier: ^5.4.14
+ version: 5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
+ vitest:
+ specifier: ^2.1.9
+ version: 2.1.9(@types/node@22.19.17)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
+
packages/@tinacms/cli:
dependencies:
'@graphql-codegen/core':
@@ -1183,7 +1311,7 @@ importers:
version: 2.6.8(graphql@15.8.0)
'@graphql-codegen/plugin-helpers':
specifier: latest
- version: 6.2.1(graphql@15.8.0)
+ version: 7.0.1(graphql@15.8.0)
'@graphql-codegen/typescript':
specifier: 'catalog:'
version: 4.1.6(graphql@15.8.0)
@@ -1234,7 +1362,7 @@ importers:
version: link:../search
'@vitejs/plugin-react':
specifier: 'catalog:'
- version: 3.1.0(vite@4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0))
+ version: 3.1.0(vite@4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))
altair-express-middleware:
specifier: 'catalog:'
version: 7.3.6
@@ -1327,7 +1455,7 @@ importers:
version: 5.9.3
vite:
specifier: ^4.5.9
- version: 4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
yup:
specifier: ^1.6.1
version: 1.7.1
@@ -1519,7 +1647,7 @@ importers:
version: 7.4.7
'@vitest/coverage-v8':
specifier: 0.32.4
- version: 0.32.4(vitest@0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0))
+ version: 0.32.4(vitest@0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0))
jest-file-snapshot:
specifier: ^0.5.0
version: 0.5.0
@@ -1531,10 +1659,10 @@ importers:
version: 5.9.3
vite:
specifier: ^4.5.9
- version: 4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
vitest:
specifier: ^0.32.4
- version: 0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0)
+ version: 0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0)
zod:
specifier: 'catalog:'
version: 3.25.76
@@ -1667,10 +1795,10 @@ importers:
version: 5.9.3
vite:
specifier: ^4.5.9
- version: 4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
vitest:
specifier: ^0.32.4
- version: 0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0)
+ version: 0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0)
packages/@tinacms/metrics:
devDependencies:
@@ -1758,7 +1886,7 @@ importers:
version: 5.9.3
vite:
specifier: ^4.5.9
- version: 4.5.14(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 4.5.14(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
devDependencies:
'@types/fs-extra':
specifier: ^11.0.4
@@ -2112,6 +2240,9 @@ importers:
'@tanstack/react-table':
specifier: ^8.21.3
version: 8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@tinacms/bridge':
+ specifier: workspace:*
+ version: link:../@tinacms/bridge
'@tinacms/mdx':
specifier: workspace:*
version: link:../@tinacms/mdx
@@ -2379,10 +2510,10 @@ importers:
version: 5.9.3
vite:
specifier: ^5.4.14
- version: 5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
vitest:
specifier: ^2.1.9
- version: 2.1.9(@types/node@22.19.3)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ version: 2.1.9(@types/node@22.19.3)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
packages/tinacms-authjs:
dependencies:
@@ -2532,12 +2663,30 @@ packages:
react: ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@astrojs/check@0.9.9':
+ resolution: {integrity: sha512-A5UW8uIuErLWEoRQvzgXpO1gTjUFtK8r7nU2Z7GewAMxUb7bPvpk11qaKKgxqXlHJWlAvaaxy+Xg28A6bmQ1Tg==}
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0 || ^6.0.0
+
'@astrojs/compiler@2.13.1':
resolution: {integrity: sha512-f3FN83d2G/v32ipNClRKgYv30onQlMZX1vCeZMjPsMMPl1mDpmbl0+N5BYo4S/ofzqJyS5hvwacEo0CCVDn/Qg==}
'@astrojs/internal-helpers@0.7.6':
resolution: {integrity: sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q==}
+ '@astrojs/language-server@2.16.8':
+ resolution: {integrity: sha512-yg1pZF6hs9FaKr2fgXMOGbW7pDLgFexFjuhWilPAc8VybTU+WSnbfbhYaUL1exm6dAK4sM3aKXGcfVwss+HXbg==}
+ hasBin: true
+ peerDependencies:
+ prettier: ^3.0.0
+ prettier-plugin-astro: '>=0.11.0'
+ peerDependenciesMeta:
+ prettier:
+ optional: true
+ prettier-plugin-astro:
+ optional: true
+
'@astrojs/markdown-remark@6.3.11':
resolution: {integrity: sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ==}
@@ -2547,6 +2696,11 @@ packages:
peerDependencies:
astro: ^5.0.0
+ '@astrojs/node@9.5.5':
+ resolution: {integrity: sha512-rtU2BGU5u3SfGURpANfMxVzCIoR86MkaN05ncza9rbtuMKJ/XnRJt/BbyVknDbOJ71hoci0SIsJwKcJR8vvi/A==}
+ peerDependencies:
+ astro: ^5.17.3
+
'@astrojs/prism@3.3.0':
resolution: {integrity: sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==}
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
@@ -2564,6 +2718,9 @@ packages:
resolution: {integrity: sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==}
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0}
+ '@astrojs/yaml2ts@0.2.3':
+ resolution: {integrity: sha512-PJzRmgQzUxI2uwpdX2lXSHtP4G8ocp24/t+bZyf5Fy0SZLSF9f9KXZoMlFM/XCGue+B0nH/2IZ7FpBYQATBsCg==}
+
'@aws-crypto/crc32@5.2.0':
resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==}
engines: {node: '>=16.0.0'}
@@ -3676,6 +3833,27 @@ packages:
peerDependencies:
react: '>=16.8.0'
+ '@emmetio/abbreviation@2.3.3':
+ resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==}
+
+ '@emmetio/css-abbreviation@2.1.8':
+ resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==}
+
+ '@emmetio/css-parser@0.4.1':
+ resolution: {integrity: sha512-2bC6m0MV/voF4CTZiAbG5MWKbq5EBmDPKu9Sb7s7nVcEzNQlrZP6mFFFlIaISM8X6514H9shWMme1fCm8cWAfQ==}
+
+ '@emmetio/html-matcher@1.3.0':
+ resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==}
+
+ '@emmetio/scanner@1.0.4':
+ resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==}
+
+ '@emmetio/stream-reader-utils@0.1.0':
+ resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==}
+
+ '@emmetio/stream-reader@2.2.0':
+ resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==}
+
'@emnapi/core@1.7.1':
resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
@@ -4722,8 +4900,8 @@ packages:
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
- '@graphql-codegen/plugin-helpers@6.2.1':
- resolution: {integrity: sha512-shRr26TfVZ6KFBjzRYUj02gLNh6yaECz9gTGgI6riANw5sSH9PONwTsBRYkEgU+6IXiL7VQeCumahvxSGFbRlQ==}
+ '@graphql-codegen/plugin-helpers@7.0.1':
+ resolution: {integrity: sha512-S2X0YT3XQbP2haqhIeku8GOXo2j8QuBu7BrLsOEHz4UeMu78y3rja1Q4ri3oJ0jq4dMgaQlazoVHI/A+FAKMGw==}
engines: {node: '>=16'}
peerDependencies:
graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
@@ -6874,60 +7052,117 @@ packages:
'@tailwindcss/node@4.2.1':
resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==}
+ '@tailwindcss/node@4.2.4':
+ resolution: {integrity: sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==}
+
'@tailwindcss/oxide-android-arm64@4.2.1':
resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [android]
+ '@tailwindcss/oxide-android-arm64@4.2.4':
+ resolution: {integrity: sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [android]
+
'@tailwindcss/oxide-darwin-arm64@4.2.1':
resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [darwin]
+ '@tailwindcss/oxide-darwin-arm64@4.2.4':
+ resolution: {integrity: sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [darwin]
+
'@tailwindcss/oxide-darwin-x64@4.2.1':
resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==}
engines: {node: '>= 20'}
cpu: [x64]
os: [darwin]
+ '@tailwindcss/oxide-darwin-x64@4.2.4':
+ resolution: {integrity: sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [darwin]
+
'@tailwindcss/oxide-freebsd-x64@4.2.1':
resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==}
engines: {node: '>= 20'}
cpu: [x64]
os: [freebsd]
+ '@tailwindcss/oxide-freebsd-x64@4.2.4':
+ resolution: {integrity: sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [freebsd]
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1':
resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==}
engines: {node: '>= 20'}
cpu: [arm]
os: [linux]
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4':
+ resolution: {integrity: sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==}
+ engines: {node: '>= 20'}
+ cpu: [arm]
+ os: [linux]
+
'@tailwindcss/oxide-linux-arm64-gnu@4.2.1':
resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
+ '@tailwindcss/oxide-linux-arm64-gnu@4.2.4':
+ resolution: {integrity: sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+
'@tailwindcss/oxide-linux-arm64-musl@4.2.1':
resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [linux]
+ '@tailwindcss/oxide-linux-arm64-musl@4.2.4':
+ resolution: {integrity: sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [linux]
+
'@tailwindcss/oxide-linux-x64-gnu@4.2.1':
resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
+ '@tailwindcss/oxide-linux-x64-gnu@4.2.4':
+ resolution: {integrity: sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+
'@tailwindcss/oxide-linux-x64-musl@4.2.1':
resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==}
engines: {node: '>= 20'}
cpu: [x64]
os: [linux]
+ '@tailwindcss/oxide-linux-x64-musl@4.2.4':
+ resolution: {integrity: sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [linux]
+
'@tailwindcss/oxide-wasm32-wasi@4.2.1':
resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==}
engines: {node: '>=14.0.0'}
@@ -6940,22 +7175,50 @@ packages:
- '@emnapi/wasi-threads'
- tslib
+ '@tailwindcss/oxide-wasm32-wasi@4.2.4':
+ resolution: {integrity: sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ bundledDependencies:
+ - '@napi-rs/wasm-runtime'
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ - '@tybys/wasm-util'
+ - '@emnapi/wasi-threads'
+ - tslib
+
'@tailwindcss/oxide-win32-arm64-msvc@4.2.1':
resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==}
engines: {node: '>= 20'}
cpu: [arm64]
os: [win32]
+ '@tailwindcss/oxide-win32-arm64-msvc@4.2.4':
+ resolution: {integrity: sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==}
+ engines: {node: '>= 20'}
+ cpu: [arm64]
+ os: [win32]
+
'@tailwindcss/oxide-win32-x64-msvc@4.2.1':
resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==}
engines: {node: '>= 20'}
cpu: [x64]
os: [win32]
+ '@tailwindcss/oxide-win32-x64-msvc@4.2.4':
+ resolution: {integrity: sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==}
+ engines: {node: '>= 20'}
+ cpu: [x64]
+ os: [win32]
+
'@tailwindcss/oxide@4.2.1':
resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==}
engines: {node: '>= 20'}
+ '@tailwindcss/oxide@4.2.4':
+ resolution: {integrity: sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==}
+ engines: {node: '>= 20'}
+
'@tailwindcss/postcss@4.2.1':
resolution: {integrity: sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw==}
@@ -6964,6 +7227,11 @@ packages:
peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
+ '@tailwindcss/vite@4.2.4':
+ resolution: {integrity: sha512-pCvohwOCspk3ZFn6eJzrrX3g4n2JY73H6MmYC87XfGPyTty4YsCjYTMArRZm/zOI8dIt3+EcrLHAFPe5A4bgtw==}
+ peerDependencies:
+ vite: ^5.2.0 || ^6 || ^7 || ^8
+
'@tanstack/react-table@8.21.3':
resolution: {integrity: sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww==}
engines: {node: '>=12'}
@@ -7076,6 +7344,9 @@ packages:
'@types/chai@4.3.20':
resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==}
+ '@types/chai@5.2.3':
+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
'@types/clear@0.1.0':
resolution: {integrity: sha512-b2VgNzu3BxxM2nGhZSMzkiaTaCClevKkBCtgpV2Al0eGaEeQgTk5qHedzNxi/SgsvmDbqxWKDAIrxZNVKyDCXw==}
@@ -7205,6 +7476,9 @@ packages:
'@types/debug@4.1.12':
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
'@types/encoding-down@5.0.5':
resolution: {integrity: sha512-HXlcVUJm2ITDgH34S1BjLMJhpfkXvEOEv+HS9KZweRl0LKlWNzVwFAj+N6pGExsRGsofhgqZP4ArQZJlWvBFDQ==}
@@ -7879,6 +8153,9 @@ packages:
'@vitest/expect@2.1.9':
resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
+
'@vitest/mocker@2.1.9':
resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==}
peerDependencies:
@@ -7890,33 +8167,85 @@ packages:
vite:
optional: true
+ '@vitest/mocker@3.2.4':
+ resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
'@vitest/pretty-format@2.1.9':
resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
+
'@vitest/runner@0.32.4':
resolution: {integrity: sha512-cHOVCkiRazobgdKLnczmz2oaKK9GJOw6ZyRcaPdssO1ej+wzHVIkWiCiNacb3TTYPdzMddYkCgMjZ4r8C0JFCw==}
'@vitest/runner@2.1.9':
resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==}
+ '@vitest/runner@3.2.4':
+ resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
+
'@vitest/snapshot@0.32.4':
resolution: {integrity: sha512-IRpyqn9t14uqsFlVI2d7DFMImGMs1Q9218of40bdQQgMePwVdmix33yMNnebXcTzDU5eiV3eUsoxxH5v0x/IQA==}
'@vitest/snapshot@2.1.9':
resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==}
+ '@vitest/snapshot@3.2.4':
+ resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
+
'@vitest/spy@0.32.4':
resolution: {integrity: sha512-oA7rCOqVOOpE6rEoXuCOADX7Lla1LIa4hljI2MSccbpec54q+oifhziZIJXxlE/CvI2E+ElhBHzVu0VEvJGQKQ==}
'@vitest/spy@2.1.9':
resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==}
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
+
'@vitest/utils@0.32.4':
resolution: {integrity: sha512-Gwnl8dhd1uJ+HXrYyV0eRqfmk9ek1ASE/LWfTCuWMw+d07ogHqp4hEAV28NiecimK6UY9DpSEPh+pXBA5gtTBg==}
'@vitest/utils@2.1.9':
resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
+
+ '@volar/kit@2.4.28':
+ resolution: {integrity: sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg==}
+ peerDependencies:
+ typescript: '*'
+
+ '@volar/language-core@2.4.28':
+ resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==}
+
+ '@volar/language-server@2.4.28':
+ resolution: {integrity: sha512-NqcLnE5gERKuS4PUFwlhMxf6vqYo7hXtbMFbViXcbVkbZ905AIVWhnSo0ZNBC2V127H1/2zP7RvVOVnyITFfBw==}
+
+ '@volar/language-service@2.4.28':
+ resolution: {integrity: sha512-Rh/wYCZJrI5vCwMk9xyw/Z+MsWxlJY1rmMZPsxUoJKfzIRjS/NF1NmnuEcrMbEVGja00aVpCsInJfixQTMdvLw==}
+
+ '@volar/source-map@2.4.28':
+ resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==}
+
+ '@volar/typescript@2.4.28':
+ resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==}
+
+ '@vscode/emmet-helper@2.11.0':
+ resolution: {integrity: sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==}
+
+ '@vscode/l10n@0.0.18':
+ resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==}
+
'@vweevers/length-prefixed-stream@1.0.0':
resolution: {integrity: sha512-0LRYNcKW2t/bWJmiKYhPIUVwz4iMNpC3aPh3UdvfUS8B+68kHpdht7pPcuawb08057rXuyuxZXavcVpoVL01AA==}
engines: {node: '>=12'}
@@ -7997,6 +8326,14 @@ packages:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
+ ajv-draft-04@1.0.0:
+ resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
+ peerDependencies:
+ ajv: ^8.5.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
@@ -8498,9 +8835,15 @@ packages:
change-case-all@1.0.15:
resolution: {integrity: sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==}
+ change-case-all@2.1.0:
+ resolution: {integrity: sha512-v6b0WWWkZUMHVuYk82l+WROgkUm4qEN2w5hKRNWtEOYwWqUGoi8C6xH0l1RLF1EoWqDFK6MFclmN3od6ws3/uw==}
+
change-case@4.1.2:
resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==}
+ 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'}
@@ -9387,6 +9730,9 @@ packages:
resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
engines: {node: '>=12'}
+ emmet@2.4.11:
+ resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==}
+
emoji-regex-xs@1.0.0:
resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==}
@@ -9983,6 +10329,10 @@ packages:
resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
engines: {node: '>= 0.6'}
+ fresh@2.0.0:
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
+ engines: {node: '>= 0.8'}
+
front-matter@4.0.2:
resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==}
@@ -11084,6 +11434,9 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+
js-yaml@3.14.2:
resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==}
hasBin: true
@@ -11147,6 +11500,12 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jsonc-parser@2.3.1:
+ resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==}
+
+ jsonc-parser@3.3.1:
+ resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
+
jsonfile@4.0.0:
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
@@ -11249,58 +11608,118 @@ packages:
cpu: [arm64]
os: [android]
+ lightningcss-android-arm64@1.32.0:
+ resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
lightningcss-darwin-arm64@1.31.1:
resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
+ lightningcss-darwin-arm64@1.32.0:
+ resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
lightningcss-darwin-x64@1.31.1:
resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
+ lightningcss-darwin-x64@1.32.0:
+ resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
lightningcss-freebsd-x64@1.31.1:
resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
+ lightningcss-freebsd-x64@1.32.0:
+ resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
lightningcss-linux-arm-gnueabihf@1.31.1:
resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
+ lightningcss-linux-arm-gnueabihf@1.32.0:
+ resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
lightningcss-linux-arm64-gnu@1.31.1:
resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ lightningcss-linux-arm64-gnu@1.32.0:
+ resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
+ lightningcss-linux-arm64-musl@1.32.0:
+ resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+
lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
+ lightningcss-linux-x64-gnu@1.32.0:
+ resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+
lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
- lightningcss-win32-arm64-msvc@1.31.1:
- resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
+ lightningcss-linux-x64-musl@1.32.0:
+ resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
engines: {node: '>= 12.0.0'}
- cpu: [arm64]
+ cpu: [x64]
+ os: [linux]
+
+ lightningcss-win32-arm64-msvc@1.31.1:
+ resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ lightningcss-win32-arm64-msvc@1.32.0:
+ resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.31.1:
@@ -11309,10 +11728,20 @@ packages:
cpu: [x64]
os: [win32]
+ lightningcss-win32-x64-msvc@1.32.0:
+ resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
lightningcss@1.31.1:
resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
engines: {node: '>= 12.0.0'}
+ lightningcss@1.32.0:
+ resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
+ engines: {node: '>= 12.0.0'}
+
lilconfig@3.1.3:
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
engines: {node: '>=14'}
@@ -11945,10 +12374,18 @@ packages:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
+ mime-db@1.54.0:
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
+ engines: {node: '>= 0.6'}
+
mime-types@2.1.35:
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mime-types@3.0.2:
+ resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
+ engines: {node: '>=18'}
+
mime@1.6.0:
resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
engines: {node: '>=4'}
@@ -12065,6 +12502,9 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ muggle-string@0.4.1:
+ resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
+
multer@1.4.5-lts.1:
resolution: {integrity: sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==}
engines: {node: '>= 6.0.0'}
@@ -12485,6 +12925,9 @@ packages:
pascal-case@3.1.2:
resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
+ path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+
path-case@3.0.4:
resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==}
@@ -12563,6 +13006,10 @@ packages:
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
engines: {node: '>=12'}
+ picomatch@4.0.4:
+ resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
+ engines: {node: '>=12'}
+
pify@2.3.0:
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
engines: {node: '>=0.10.0'}
@@ -12741,6 +13188,11 @@ packages:
engines: {node: '>=10.13.0'}
hasBin: true
+ prettier@3.8.3:
+ resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==}
+ engines: {node: '>=14'}
+ hasBin: true
+
pretty-format@25.5.0:
resolution: {integrity: sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==}
engines: {node: '>= 8.3'}
@@ -13271,6 +13723,12 @@ packages:
resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==}
engines: {node: '>=0.10'}
+ request-light@0.5.8:
+ resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==}
+
+ request-light@0.7.0:
+ resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==}
+
request-promise-core@1.1.4:
resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==}
engines: {node: '>=0.10.0'}
@@ -13461,6 +13919,10 @@ packages:
resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==}
engines: {node: '>= 0.8.0'}
+ send@1.2.1:
+ resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
+ engines: {node: '>= 18'}
+
sentence-case@3.0.4:
resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==}
@@ -13468,6 +13930,9 @@ packages:
resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
engines: {node: '>= 0.8.0'}
+ server-destroy@1.0.1:
+ resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==}
+
set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
@@ -13678,6 +14143,9 @@ packages:
sponge-case@1.0.1:
resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==}
+ sponge-case@2.0.3:
+ resolution: {integrity: sha512-i4h9ZGRfxV6Xw3mpZSFOfbXjf0cQcYmssGWutgNIfFZ2VM+YIWfD71N/kjjwK6X/AAHzBr+rciEcn/L34S8TGw==}
+
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
@@ -13826,6 +14294,9 @@ packages:
strip-literal@1.3.0:
resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==}
+ strip-literal@3.1.0:
+ resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
+
strip-outer@1.0.1:
resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==}
engines: {node: '>=0.10.0'}
@@ -13917,6 +14388,9 @@ packages:
swap-case@2.0.2:
resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==}
+ swap-case@3.0.3:
+ resolution: {integrity: sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA==}
+
swr@2.2.0:
resolution: {integrity: sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==}
peerDependencies:
@@ -13956,6 +14430,9 @@ packages:
tailwindcss@4.2.1:
resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==}
+ tailwindcss@4.2.4:
+ resolution: {integrity: sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==}
+
tapable@2.3.0:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
@@ -14036,6 +14513,10 @@ packages:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
+ tinyglobby@0.2.16:
+ resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==}
+ engines: {node: '>=12.0.0'}
+
tinypool@0.5.0:
resolution: {integrity: sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==}
engines: {node: '>=14.0.0'}
@@ -14048,6 +14529,10 @@ packages:
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
engines: {node: '>=14.0.0'}
+ tinyrainbow@2.0.0:
+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
+ engines: {node: '>=14.0.0'}
+
tinyspy@2.2.1:
resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==}
engines: {node: '>=14.0.0'}
@@ -14056,6 +14541,10 @@ packages:
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
engines: {node: '>=14.0.0'}
+ tinyspy@4.0.4:
+ resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
+ engines: {node: '>=14.0.0'}
+
title-case@3.0.3:
resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==}
@@ -14372,6 +14861,12 @@ packages:
peerDependencies:
typescript: 4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x
+ typesafe-path@0.2.2:
+ resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==}
+
+ typescript-auto-import-cache@0.3.6:
+ resolution: {integrity: sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==}
+
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -14676,11 +15171,12 @@ packages:
uuid@3.4.0:
resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
- deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
+ deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
uuid@8.3.2:
resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
+ deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
uvu@0.5.6:
@@ -14753,6 +15249,11 @@ packages:
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+
vite@4.5.14:
resolution: {integrity: sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==}
engines: {node: ^14.18.0 || >=16.0.0}
@@ -14916,6 +15417,103 @@ packages:
jsdom:
optional: true
+ vitest@3.2.4:
+ resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/debug': ^4.1.12
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/debug':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ volar-service-css@0.0.70:
+ resolution: {integrity: sha512-K1qyOvBpE3rzdAv3e4/6Rv5yizrYPy5R/ne3IWCAzLBuMO4qBMV3kSqWzj6KUVe6S0AnN6wxF7cRkiaKfYMYJw==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-emmet@0.0.70:
+ resolution: {integrity: sha512-xi5bC4m/VyE3zy/n2CXspKeDZs3qA41tHLTw275/7dNWM/RqE2z3BnDICQybHIVp/6G1iOQj5c1qXMgQC08TNg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-html@0.0.70:
+ resolution: {integrity: sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-prettier@0.0.70:
+ resolution: {integrity: sha512-Z6BCFSpGVCd8BPAsZ785Kce1BGlWd5ODqmqZGVuB14MJvrR4+CYz6cDy4F+igmE1gMifqfvMhdgT8Aud4M5ngg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ prettier: ^2.2 || ^3.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+ prettier:
+ optional: true
+
+ volar-service-typescript-twoslash-queries@0.0.70:
+ resolution: {integrity: sha512-IdD13Z9N2Bu8EM6CM0fDV1E69olEYGHDU25X51YXmq8Y0CmJ2LNj6gOiBJgpS5JGUqFzECVhMNBW7R0sPdRTMQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-typescript@0.0.70:
+ resolution: {integrity: sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ volar-service-yaml@0.0.70:
+ resolution: {integrity: sha512-0c8bXDBeoATF9F6iPIlOuYTuZAC4c+yi0siQo920u7eiBJk8oQmUmg9cDUbR4+Gl++bvGP4plj3fErbJuPqdcQ==}
+ peerDependencies:
+ '@volar/language-service': ~2.4.0
+ peerDependenciesMeta:
+ '@volar/language-service':
+ optional: true
+
+ vscode-css-languageservice@6.3.10:
+ resolution: {integrity: sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA==}
+
+ vscode-html-languageservice@5.6.2:
+ resolution: {integrity: sha512-ulCrSnFnfQ16YzvwnYUgEbUEl/ZG7u2eV27YhvLObSHKkb8fw1Z9cgsnUwjTEeDIdJDoTDTDpxuhQwoenoLNMg==}
+
+ vscode-json-languageservice@4.1.8:
+ resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==}
+ engines: {npm: '>=7.0.0'}
+
vscode-jsonrpc@8.2.0:
resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
engines: {node: '>=14.0.0'}
@@ -14933,9 +15531,15 @@ packages:
resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
hasBin: true
+ vscode-nls@5.2.0:
+ resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==}
+
vscode-uri@3.0.8:
resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==}
+ vscode-uri@3.1.0:
+ resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+
w3c-hr-time@1.0.2:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
deprecated: Use your platform's native performance.now() and performance.timeOrigin.
@@ -15102,10 +15706,19 @@ packages:
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
engines: {node: '>=18'}
+ yaml-language-server@1.20.0:
+ resolution: {integrity: sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA==}
+ hasBin: true
+
yaml@1.10.2:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'}
+ yaml@2.7.1:
+ resolution: {integrity: sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==}
+ engines: {node: '>= 14'}
+ hasBin: true
+
yaml@2.8.2:
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
engines: {node: '>= 14.6'}
@@ -15241,10 +15854,46 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
+ '@astrojs/check@0.9.9(prettier@3.8.3)(typescript@5.9.3)':
+ dependencies:
+ '@astrojs/language-server': 2.16.8(prettier@3.8.3)(typescript@5.9.3)
+ chokidar: 4.0.3
+ kleur: 4.1.5
+ typescript: 5.9.3
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - prettier
+ - prettier-plugin-astro
+
'@astrojs/compiler@2.13.1': {}
'@astrojs/internal-helpers@0.7.6': {}
+ '@astrojs/language-server@2.16.8(prettier@3.8.3)(typescript@5.9.3)':
+ dependencies:
+ '@astrojs/compiler': 2.13.1
+ '@astrojs/yaml2ts': 0.2.3
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@volar/kit': 2.4.28(typescript@5.9.3)
+ '@volar/language-core': 2.4.28
+ '@volar/language-server': 2.4.28
+ '@volar/language-service': 2.4.28
+ muggle-string: 0.4.1
+ tinyglobby: 0.2.16
+ volar-service-css: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-emmet: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-html: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-prettier: 0.0.70(@volar/language-service@2.4.28)(prettier@3.8.3)
+ volar-service-typescript: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-typescript-twoslash-queries: 0.0.70(@volar/language-service@2.4.28)
+ volar-service-yaml: 0.0.70(@volar/language-service@2.4.28)
+ vscode-html-languageservice: 5.6.2
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ prettier: 3.8.3
+ transitivePeerDependencies:
+ - typescript
+
'@astrojs/markdown-remark@6.3.11':
dependencies:
'@astrojs/internal-helpers': 0.7.6
@@ -15271,12 +15920,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@astrojs/mdx@4.3.14(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))':
+ '@astrojs/mdx@4.3.14(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))':
dependencies:
'@astrojs/markdown-remark': 6.3.11
'@mdx-js/mdx': 3.1.1
acorn: 8.15.0
- astro: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
+ astro: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
es-module-lexer: 1.7.0
estree-util-visit: 2.0.0
hast-util-to-html: 9.0.5
@@ -15290,19 +15939,28 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@astrojs/node@9.5.5(astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2))':
+ dependencies:
+ '@astrojs/internal-helpers': 0.7.6
+ astro: 5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2)
+ send: 1.2.1
+ server-destroy: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+
'@astrojs/prism@3.3.0':
dependencies:
prismjs: 1.30.0
- '@astrojs/react@4.4.2(@types/node@25.1.0)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(jiti@2.6.1)(lightningcss@1.31.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)':
+ '@astrojs/react@4.4.2(@types/node@25.1.0)(@types/react-dom@18.3.7(@types/react@18.3.27))(@types/react@18.3.27)(jiti@2.6.1)(lightningcss@1.32.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)':
dependencies:
'@types/react': 18.3.27
'@types/react-dom': 18.3.7(@types/react@18.3.27)
- '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
+ '@vitejs/plugin-react': 4.7.0(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
ultrahtml: 1.6.0
- vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
transitivePeerDependencies:
- '@types/node'
- jiti
@@ -15329,6 +15987,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@astrojs/yaml2ts@0.2.3':
+ dependencies:
+ yaml: 2.8.2
+
'@aws-crypto/crc32@5.2.0':
dependencies:
'@aws-crypto/util': 5.2.0
@@ -17196,6 +17858,29 @@ snapshots:
react: 18.3.1
tslib: 2.8.1
+ '@emmetio/abbreviation@2.3.3':
+ dependencies:
+ '@emmetio/scanner': 1.0.4
+
+ '@emmetio/css-abbreviation@2.1.8':
+ dependencies:
+ '@emmetio/scanner': 1.0.4
+
+ '@emmetio/css-parser@0.4.1':
+ dependencies:
+ '@emmetio/stream-reader': 2.2.0
+ '@emmetio/stream-reader-utils': 0.1.0
+
+ '@emmetio/html-matcher@1.3.0':
+ dependencies:
+ '@emmetio/scanner': 1.0.4
+
+ '@emmetio/scanner@1.0.4': {}
+
+ '@emmetio/stream-reader-utils@0.1.0': {}
+
+ '@emmetio/stream-reader@2.2.0': {}
+
'@emnapi/core@1.7.1':
dependencies:
'@emnapi/wasi-threads': 1.1.0
@@ -17881,14 +18566,14 @@ snapshots:
lodash: 4.17.21
tslib: 2.6.3
- '@graphql-codegen/plugin-helpers@6.2.1(graphql@15.8.0)':
+ '@graphql-codegen/plugin-helpers@7.0.1(graphql@15.8.0)':
dependencies:
'@graphql-tools/utils': 11.0.0(graphql@15.8.0)
- change-case-all: 1.0.15
+ change-case-all: 2.1.0
common-tags: 1.8.2
graphql: 15.8.0
import-from: 4.0.0
- tslib: 2.6.3
+ tslib: 2.8.1
'@graphql-codegen/schema-ast@4.1.0(graphql@15.8.0)':
dependencies:
@@ -19161,7 +19846,7 @@ snapshots:
detect-libc: 2.1.2
is-glob: 4.0.3
node-addon-api: 7.1.1
- picomatch: 4.0.3
+ picomatch: 4.0.4
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.4
'@parcel/watcher-darwin-arm64': 2.5.4
@@ -20397,42 +21082,88 @@ snapshots:
source-map-js: 1.2.1
tailwindcss: 4.2.1
+ '@tailwindcss/node@4.2.4':
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ enhanced-resolve: 5.19.0
+ jiti: 2.6.1
+ lightningcss: 1.32.0
+ magic-string: 0.30.21
+ source-map-js: 1.2.1
+ tailwindcss: 4.2.4
+
'@tailwindcss/oxide-android-arm64@4.2.1':
optional: true
+ '@tailwindcss/oxide-android-arm64@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-darwin-arm64@4.2.1':
optional: true
+ '@tailwindcss/oxide-darwin-arm64@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-darwin-x64@4.2.1':
optional: true
+ '@tailwindcss/oxide-darwin-x64@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-freebsd-x64@4.2.1':
optional: true
+ '@tailwindcss/oxide-freebsd-x64@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1':
optional: true
+ '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-linux-arm64-gnu@4.2.1':
optional: true
+ '@tailwindcss/oxide-linux-arm64-gnu@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-linux-arm64-musl@4.2.1':
optional: true
+ '@tailwindcss/oxide-linux-arm64-musl@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-linux-x64-gnu@4.2.1':
optional: true
+ '@tailwindcss/oxide-linux-x64-gnu@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-linux-x64-musl@4.2.1':
optional: true
+ '@tailwindcss/oxide-linux-x64-musl@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-wasm32-wasi@4.2.1':
optional: true
+ '@tailwindcss/oxide-wasm32-wasi@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-win32-arm64-msvc@4.2.1':
optional: true
+ '@tailwindcss/oxide-win32-arm64-msvc@4.2.4':
+ optional: true
+
'@tailwindcss/oxide-win32-x64-msvc@4.2.1':
optional: true
+ '@tailwindcss/oxide-win32-x64-msvc@4.2.4':
+ optional: true
+
'@tailwindcss/oxide@4.2.1':
optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.2.1
@@ -20448,6 +21179,21 @@ snapshots:
'@tailwindcss/oxide-win32-arm64-msvc': 4.2.1
'@tailwindcss/oxide-win32-x64-msvc': 4.2.1
+ '@tailwindcss/oxide@4.2.4':
+ optionalDependencies:
+ '@tailwindcss/oxide-android-arm64': 4.2.4
+ '@tailwindcss/oxide-darwin-arm64': 4.2.4
+ '@tailwindcss/oxide-darwin-x64': 4.2.4
+ '@tailwindcss/oxide-freebsd-x64': 4.2.4
+ '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.4
+ '@tailwindcss/oxide-linux-arm64-gnu': 4.2.4
+ '@tailwindcss/oxide-linux-arm64-musl': 4.2.4
+ '@tailwindcss/oxide-linux-x64-gnu': 4.2.4
+ '@tailwindcss/oxide-linux-x64-musl': 4.2.4
+ '@tailwindcss/oxide-wasm32-wasi': 4.2.4
+ '@tailwindcss/oxide-win32-arm64-msvc': 4.2.4
+ '@tailwindcss/oxide-win32-x64-msvc': 4.2.4
+
'@tailwindcss/postcss@4.2.1':
dependencies:
'@alloc/quick-lru': 5.2.0
@@ -20471,6 +21217,13 @@ snapshots:
postcss-selector-parser: 6.0.10
tailwindcss: 4.2.1
+ '@tailwindcss/vite@4.2.4(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))':
+ dependencies:
+ '@tailwindcss/node': 4.2.4
+ '@tailwindcss/oxide': 4.2.4
+ tailwindcss: 4.2.4
+ vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+
'@tanstack/react-table@8.21.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@tanstack/table-core': 8.21.3
@@ -20596,6 +21349,11 @@ snapshots:
'@types/chai@4.3.20': {}
+ '@types/chai@5.2.3':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+ assertion-error: 2.0.1
+
'@types/clear@0.1.0': {}
'@types/cli-spinner@0.2.3':
@@ -20753,6 +21511,8 @@ snapshots:
dependencies:
'@types/ms': 2.1.0
+ '@types/deep-eql@4.0.2': {}
+
'@types/encoding-down@5.0.5':
dependencies:
'@types/abstract-leveldown': 7.2.5
@@ -21492,18 +22252,18 @@ snapshots:
'@vercel/stega@0.0.5': {}
- '@vitejs/plugin-react@3.1.0(vite@4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0))':
+ '@vitejs/plugin-react@3.1.0(vite@4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))':
dependencies:
'@babel/core': 7.28.5
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
'@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.5)
magic-string: 0.27.0
react-refresh: 0.14.2
- vite: 4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
transitivePeerDependencies:
- supports-color
- '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))':
+ '@vitejs/plugin-react@4.7.0(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))':
dependencies:
'@babel/core': 7.28.5
'@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5)
@@ -21511,11 +22271,11 @@ snapshots:
'@rolldown/pluginutils': 1.0.0-beta.27
'@types/babel__core': 7.20.5
react-refresh: 0.17.0
- vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
transitivePeerDependencies:
- supports-color
- '@vitest/coverage-v8@0.32.4(vitest@0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0))':
+ '@vitest/coverage-v8@0.32.4(vitest@0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0))':
dependencies:
'@ampproject/remapping': 2.3.0
'@bcoe/v8-coverage': 0.2.3
@@ -21528,7 +22288,7 @@ snapshots:
std-env: 3.10.0
test-exclude: 6.0.0
v8-to-istanbul: 9.3.0
- vitest: 0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0)
+ vitest: 0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0)
transitivePeerDependencies:
- supports-color
@@ -21545,26 +22305,46 @@ snapshots:
chai: 5.3.3
tinyrainbow: 1.2.0
- '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0))':
+ '@vitest/expect@3.2.4':
+ dependencies:
+ '@types/chai': 5.2.3
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ tinyrainbow: 2.0.0
+
+ '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))':
dependencies:
'@vitest/spy': 2.1.9
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 5.4.21(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
- '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0))':
+ '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))':
dependencies:
'@vitest/spy': 2.1.9
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
+
+ '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))':
+ dependencies:
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
'@vitest/pretty-format@2.1.9':
dependencies:
tinyrainbow: 1.2.0
+ '@vitest/pretty-format@3.2.4':
+ dependencies:
+ tinyrainbow: 2.0.0
+
'@vitest/runner@0.32.4':
dependencies:
'@vitest/utils': 0.32.4
@@ -21576,6 +22356,12 @@ snapshots:
'@vitest/utils': 2.1.9
pathe: 1.1.2
+ '@vitest/runner@3.2.4':
+ dependencies:
+ '@vitest/utils': 3.2.4
+ pathe: 2.0.3
+ strip-literal: 3.1.0
+
'@vitest/snapshot@0.32.4':
dependencies:
magic-string: 0.30.21
@@ -21588,6 +22374,12 @@ snapshots:
magic-string: 0.30.21
pathe: 1.1.2
+ '@vitest/snapshot@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ magic-string: 0.30.21
+ pathe: 2.0.3
+
'@vitest/spy@0.32.4':
dependencies:
tinyspy: 2.2.1
@@ -21596,6 +22388,10 @@ snapshots:
dependencies:
tinyspy: 3.0.2
+ '@vitest/spy@3.2.4':
+ dependencies:
+ tinyspy: 4.0.4
+
'@vitest/utils@0.32.4':
dependencies:
diff-sequences: 29.6.3
@@ -21608,6 +22404,62 @@ snapshots:
loupe: 3.2.1
tinyrainbow: 1.2.0
+ '@vitest/utils@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.2.1
+ tinyrainbow: 2.0.0
+
+ '@volar/kit@2.4.28(typescript@5.9.3)':
+ dependencies:
+ '@volar/language-service': 2.4.28
+ '@volar/typescript': 2.4.28
+ typesafe-path: 0.2.2
+ typescript: 5.9.3
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/language-core@2.4.28':
+ dependencies:
+ '@volar/source-map': 2.4.28
+
+ '@volar/language-server@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ '@volar/language-service': 2.4.28
+ '@volar/typescript': 2.4.28
+ path-browserify: 1.0.1
+ request-light: 0.7.0
+ vscode-languageserver: 9.0.1
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/language-service@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ vscode-languageserver-protocol: 3.17.5
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ '@volar/source-map@2.4.28': {}
+
+ '@volar/typescript@2.4.28':
+ dependencies:
+ '@volar/language-core': 2.4.28
+ path-browserify: 1.0.1
+ vscode-uri: 3.1.0
+
+ '@vscode/emmet-helper@2.11.0':
+ dependencies:
+ emmet: 2.4.11
+ jsonc-parser: 2.3.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ '@vscode/l10n@0.0.18': {}
+
'@vweevers/length-prefixed-stream@1.0.0':
dependencies:
inherits: 2.0.4
@@ -21684,6 +22536,10 @@ snapshots:
agent-base@7.1.4: {}
+ ajv-draft-04@1.0.0(ajv@8.17.1):
+ optionalDependencies:
+ ajv: 8.17.1
+
ajv@6.12.6:
dependencies:
fast-deep-equal: 3.1.3
@@ -21870,7 +22726,7 @@ snapshots:
astring@1.9.0: {}
- astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2):
+ astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2):
dependencies:
'@astrojs/compiler': 2.13.1
'@astrojs/internal-helpers': 0.7.6
@@ -21927,8 +22783,8 @@ snapshots:
unist-util-visit: 5.0.0
unstorage: 1.17.4(@azure/storage-blob@12.29.1)
vfile: 6.0.3
- vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
- vitefu: 1.1.2(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
+ vite: 6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vitefu: 1.1.2(vite@6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
xxhash-wasm: 1.1.0
yargs-parser: 21.1.1
yocto-spinner: 0.2.3
@@ -21972,29 +22828,131 @@ snapshots:
- uploadthing
- yaml
- async-function@1.0.0: {}
-
- async-lock@1.4.1: {}
-
- asynckit@0.4.0: {}
-
- attr-accept@2.2.5: {}
-
- auto-bind@4.0.0: {}
-
- autoprefixer@10.4.23(postcss@8.5.6):
- dependencies:
- browserslist: 4.28.1
- caniuse-lite: 1.0.30001760
- fraction.js: 5.3.4
- picocolors: 1.1.1
- postcss: 8.5.6
- postcss-value-parser: 4.2.0
-
- available-typed-arrays@1.0.7:
+ astro@5.18.1(@azure/storage-blob@12.29.1)(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(rollup@4.53.4)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(yaml@2.8.2):
dependencies:
- possible-typed-array-names: 1.1.0
-
+ '@astrojs/compiler': 2.13.1
+ '@astrojs/internal-helpers': 0.7.6
+ '@astrojs/markdown-remark': 6.3.11
+ '@astrojs/telemetry': 3.3.0
+ '@capsizecss/unpack': 4.0.0
+ '@oslojs/encoding': 1.1.0
+ '@rollup/pluginutils': 5.3.0(rollup@4.53.4)
+ acorn: 8.15.0
+ aria-query: 5.3.2
+ axobject-query: 4.1.0
+ boxen: 8.0.1
+ ci-info: 4.3.1
+ clsx: 2.1.1
+ common-ancestor-path: 1.0.1
+ cookie: 1.1.1
+ cssesc: 3.0.0
+ debug: 4.4.3
+ deterministic-object-hash: 2.0.2
+ devalue: 5.6.4
+ diff: 8.0.3
+ dlv: 1.1.3
+ dset: 3.1.4
+ es-module-lexer: 1.7.0
+ esbuild: 0.27.4
+ estree-walker: 3.0.3
+ flattie: 1.1.1
+ fontace: 0.4.1
+ github-slugger: 2.0.0
+ html-escaper: 3.0.3
+ http-cache-semantics: 4.2.0
+ import-meta-resolve: 4.2.0
+ js-yaml: 4.1.1
+ magic-string: 0.30.21
+ magicast: 0.5.2
+ mrmime: 2.0.1
+ neotraverse: 0.6.18
+ p-limit: 6.2.0
+ p-queue: 8.1.1
+ package-manager-detector: 1.6.0
+ piccolore: 0.1.3
+ picomatch: 4.0.3
+ prompts: 2.4.2
+ rehype: 13.0.2
+ semver: 7.7.3
+ shiki: 3.23.0
+ smol-toml: 1.6.0
+ svgo: 4.0.1
+ tinyexec: 1.0.2
+ tinyglobby: 0.2.15
+ tsconfck: 3.1.6(typescript@5.9.3)
+ ultrahtml: 1.6.0
+ unifont: 0.7.4
+ unist-util-visit: 5.0.0
+ unstorage: 1.17.4(@azure/storage-blob@12.29.1)
+ vfile: 6.0.3
+ vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vitefu: 1.1.2(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
+ xxhash-wasm: 1.1.0
+ yargs-parser: 21.1.1
+ yocto-spinner: 0.2.3
+ zod: 3.25.76
+ zod-to-json-schema: 3.25.1(zod@3.25.76)
+ zod-to-ts: 1.2.0(typescript@5.9.3)(zod@3.25.76)
+ optionalDependencies:
+ sharp: 0.34.5
+ transitivePeerDependencies:
+ - '@azure/app-configuration'
+ - '@azure/cosmos'
+ - '@azure/data-tables'
+ - '@azure/identity'
+ - '@azure/keyvault-secrets'
+ - '@azure/storage-blob'
+ - '@capacitor/preferences'
+ - '@deno/kv'
+ - '@netlify/blobs'
+ - '@planetscale/database'
+ - '@types/node'
+ - '@upstash/redis'
+ - '@vercel/blob'
+ - '@vercel/functions'
+ - '@vercel/kv'
+ - aws4fetch
+ - db0
+ - idb-keyval
+ - ioredis
+ - jiti
+ - less
+ - lightningcss
+ - rollup
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - typescript
+ - uploadthing
+ - yaml
+
+ async-function@1.0.0: {}
+
+ async-lock@1.4.1: {}
+
+ asynckit@0.4.0: {}
+
+ attr-accept@2.2.5: {}
+
+ auto-bind@4.0.0: {}
+
+ autoprefixer@10.4.23(postcss@8.5.6):
+ dependencies:
+ browserslist: 4.28.1
+ caniuse-lite: 1.0.30001760
+ fraction.js: 5.3.4
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+
+ available-typed-arrays@1.0.7:
+ dependencies:
+ possible-typed-array-names: 1.1.0
+
aws-sign2@0.7.0:
optional: true
@@ -22401,6 +23359,13 @@ snapshots:
upper-case: 2.0.2
upper-case-first: 2.0.2
+ change-case-all@2.1.0:
+ dependencies:
+ change-case: 5.4.4
+ sponge-case: 2.0.3
+ swap-case: 3.0.3
+ title-case: 3.0.3
+
change-case@4.1.2:
dependencies:
camel-case: 4.1.2
@@ -22416,6 +23381,8 @@ snapshots:
snake-case: 3.0.4
tslib: 2.8.1
+ change-case@5.4.4: {}
+
char-regex@1.0.2: {}
character-entities-html4@2.1.0: {}
@@ -23311,6 +24278,11 @@ snapshots:
emittery@0.13.1: {}
+ emmet@2.4.11:
+ dependencies:
+ '@emmetio/abbreviation': 2.3.3
+ '@emmetio/css-abbreviation': 2.1.8
+
emoji-regex-xs@1.0.0: {}
emoji-regex@10.1.0: {}
@@ -24142,6 +25114,10 @@ snapshots:
optionalDependencies:
picomatch: 4.0.3
+ fdir@6.5.0(picomatch@4.0.4):
+ optionalDependencies:
+ picomatch: 4.0.4
+
fergies-inverted-index@12.0.0(abstract-level@1.0.4):
dependencies:
browser-level: 1.0.1
@@ -24295,6 +25271,8 @@ snapshots:
fresh@0.5.2: {}
+ fresh@2.0.0: {}
+
front-matter@4.0.2:
dependencies:
js-yaml: 3.14.2
@@ -26054,6 +27032,8 @@ snapshots:
js-tokens@4.0.0: {}
+ js-tokens@9.0.1: {}
+
js-yaml@3.14.2:
dependencies:
argparse: 1.0.10
@@ -26131,6 +27111,10 @@ snapshots:
json5@2.2.3: {}
+ jsonc-parser@2.3.1: {}
+
+ jsonc-parser@3.3.1: {}
+
jsonfile@4.0.0:
optionalDependencies:
graceful-fs: 4.2.11
@@ -26231,36 +27215,69 @@ snapshots:
lightningcss-android-arm64@1.31.1:
optional: true
+ lightningcss-android-arm64@1.32.0:
+ optional: true
+
lightningcss-darwin-arm64@1.31.1:
optional: true
+ lightningcss-darwin-arm64@1.32.0:
+ optional: true
+
lightningcss-darwin-x64@1.31.1:
optional: true
+ lightningcss-darwin-x64@1.32.0:
+ optional: true
+
lightningcss-freebsd-x64@1.31.1:
optional: true
+ lightningcss-freebsd-x64@1.32.0:
+ optional: true
+
lightningcss-linux-arm-gnueabihf@1.31.1:
optional: true
+ lightningcss-linux-arm-gnueabihf@1.32.0:
+ optional: true
+
lightningcss-linux-arm64-gnu@1.31.1:
optional: true
+ lightningcss-linux-arm64-gnu@1.32.0:
+ optional: true
+
lightningcss-linux-arm64-musl@1.31.1:
optional: true
+ lightningcss-linux-arm64-musl@1.32.0:
+ optional: true
+
lightningcss-linux-x64-gnu@1.31.1:
optional: true
+ lightningcss-linux-x64-gnu@1.32.0:
+ optional: true
+
lightningcss-linux-x64-musl@1.31.1:
optional: true
+ lightningcss-linux-x64-musl@1.32.0:
+ optional: true
+
lightningcss-win32-arm64-msvc@1.31.1:
optional: true
+ lightningcss-win32-arm64-msvc@1.32.0:
+ optional: true
+
lightningcss-win32-x64-msvc@1.31.1:
optional: true
+ lightningcss-win32-x64-msvc@1.32.0:
+ optional: true
+
lightningcss@1.31.1:
dependencies:
detect-libc: 2.1.2
@@ -26277,6 +27294,22 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.31.1
lightningcss-win32-x64-msvc: 1.31.1
+ lightningcss@1.32.0:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.32.0
+ lightningcss-darwin-arm64: 1.32.0
+ lightningcss-darwin-x64: 1.32.0
+ lightningcss-freebsd-x64: 1.32.0
+ lightningcss-linux-arm-gnueabihf: 1.32.0
+ lightningcss-linux-arm64-gnu: 1.32.0
+ lightningcss-linux-arm64-musl: 1.32.0
+ lightningcss-linux-x64-gnu: 1.32.0
+ lightningcss-linux-x64-musl: 1.32.0
+ lightningcss-win32-arm64-msvc: 1.32.0
+ lightningcss-win32-x64-msvc: 1.32.0
+
lilconfig@3.1.3: {}
lines-and-columns@1.2.4: {}
@@ -27524,10 +28557,16 @@ snapshots:
mime-db@1.52.0: {}
+ mime-db@1.54.0: {}
+
mime-types@2.1.35:
dependencies:
mime-db: 1.52.0
+ mime-types@3.0.2:
+ dependencies:
+ mime-db: 1.54.0
+
mime@1.6.0: {}
mimic-fn@2.1.0: {}
@@ -27635,6 +28674,8 @@ snapshots:
ms@2.1.3: {}
+ muggle-string@0.4.1: {}
+
multer@1.4.5-lts.1:
dependencies:
append-field: 1.0.0
@@ -28186,6 +29227,8 @@ snapshots:
no-case: 3.0.4
tslib: 2.8.1
+ path-browserify@1.0.1: {}
+
path-case@3.0.4:
dependencies:
dot-case: 3.0.4
@@ -28238,6 +29281,8 @@ snapshots:
picomatch@4.0.3: {}
+ picomatch@4.0.4: {}
+
pify@2.3.0: {}
pify@4.0.1: {}
@@ -28436,6 +29481,8 @@ snapshots:
prettier@2.8.8: {}
+ prettier@3.8.3: {}
+
pretty-format@25.5.0:
dependencies:
'@jest/types': 25.5.0
@@ -28472,7 +29519,7 @@ snapshots:
pretty-hrtime@1.0.3: {}
- pretty-quick@3.3.1(prettier@2.8.8):
+ pretty-quick@3.3.1(prettier@3.8.3):
dependencies:
execa: 4.1.0
find-up: 4.1.0
@@ -28480,7 +29527,7 @@ snapshots:
mri: 1.2.0
picocolors: 1.1.1
picomatch: 3.0.1
- prettier: 2.8.8
+ prettier: 3.8.3
tslib: 2.8.1
prism-react-renderer@2.4.1(react@18.3.1):
@@ -29122,6 +30169,10 @@ snapshots:
repeat-string@1.6.1: {}
+ request-light@0.5.8: {}
+
+ request-light@0.7.0: {}
+
request-promise-core@1.1.4(request@2.88.2):
dependencies:
lodash: 4.17.21
@@ -29385,6 +30436,22 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ send@1.2.1:
+ dependencies:
+ debug: 4.4.3
+ encodeurl: 2.0.0
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 2.0.0
+ http-errors: 2.0.1
+ mime-types: 3.0.2
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ statuses: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
sentence-case@3.0.4:
dependencies:
no-case: 3.0.4
@@ -29400,6 +30467,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ server-destroy@1.0.1: {}
+
set-function-length@1.2.2:
dependencies:
define-data-property: 1.1.4
@@ -29707,6 +30776,8 @@ snapshots:
dependencies:
tslib: 2.8.1
+ sponge-case@2.0.3: {}
+
sprintf-js@1.0.3: {}
sqlite-level@1.2.1(sucrase@3.35.1):
@@ -29886,6 +30957,10 @@ snapshots:
dependencies:
acorn: 8.15.0
+ strip-literal@3.1.0:
+ dependencies:
+ js-tokens: 9.0.1
+
strip-outer@1.0.1:
dependencies:
escape-string-regexp: 1.0.5
@@ -29988,6 +31063,8 @@ snapshots:
dependencies:
tslib: 2.8.1
+ swap-case@3.0.3: {}
+
swr@2.2.0(react@19.2.3):
dependencies:
react: 19.2.3
@@ -30046,6 +31123,8 @@ snapshots:
tailwindcss@4.2.1: {}
+ tailwindcss@4.2.4: {}
+
tapable@2.3.0: {}
tar-fs@2.1.4:
@@ -30131,16 +31210,25 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.3)
picomatch: 4.0.3
+ tinyglobby@0.2.16:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.4)
+ picomatch: 4.0.4
+
tinypool@0.5.0: {}
tinypool@1.1.1: {}
tinyrainbow@1.2.0: {}
+ tinyrainbow@2.0.0: {}
+
tinyspy@2.2.1: {}
tinyspy@3.0.2: {}
+ tinyspy@4.0.4: {}
+
title-case@3.0.3:
dependencies:
tslib: 2.8.1
@@ -30511,6 +31599,12 @@ snapshots:
typescript: 5.9.3
yaml: 2.8.2
+ typesafe-path@0.2.2: {}
+
+ typescript-auto-import-cache@0.3.6:
+ dependencies:
+ semver: 7.7.3
+
typescript@5.9.3: {}
ua-parser-js@1.0.41: {}
@@ -30885,14 +31979,14 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
- vite-node@0.32.4(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite-node@0.32.4(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
cac: 6.7.14
debug: 4.4.3
mlly: 1.8.0
pathe: 1.1.2
picocolors: 1.1.1
- vite: 4.5.14(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 4.5.14(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -30903,13 +31997,13 @@ snapshots:
- supports-color
- terser
- vite-node@2.1.9(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite-node@2.1.9(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 1.1.2
- vite: 5.4.21(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -30921,13 +32015,13 @@ snapshots:
- supports-color
- terser
- vite-node@2.1.9(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite-node@2.1.9(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
cac: 6.7.14
debug: 4.4.3
es-module-lexer: 1.7.0
pathe: 1.1.2
- vite: 5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
transitivePeerDependencies:
- '@types/node'
- less
@@ -30939,7 +32033,28 @@ snapshots:
- supports-color
- terser
- vite@4.5.14(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite-node@3.2.4(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vite@4.5.14(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
esbuild: 0.18.20
postcss: 8.5.6
@@ -30947,11 +32062,11 @@ snapshots:
optionalDependencies:
'@types/node': 22.19.17
fsevents: 2.3.3
- lightningcss: 1.31.1
+ lightningcss: 1.32.0
sass: 1.97.3
terser: 5.46.0
- vite@4.5.14(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite@4.5.14(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
esbuild: 0.18.20
postcss: 8.5.6
@@ -30959,11 +32074,11 @@ snapshots:
optionalDependencies:
'@types/node': 22.19.3
fsevents: 2.3.3
- lightningcss: 1.31.1
+ lightningcss: 1.32.0
sass: 1.97.3
terser: 5.46.0
- vite@5.4.21(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite@5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
esbuild: 0.21.5
postcss: 8.5.6
@@ -30971,11 +32086,11 @@ snapshots:
optionalDependencies:
'@types/node': 22.19.17
fsevents: 2.3.3
- lightningcss: 1.31.1
+ lightningcss: 1.32.0
sass: 1.97.3
terser: 5.46.0
- vite@5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vite@5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
esbuild: 0.21.5
postcss: 8.5.6
@@ -30983,11 +32098,28 @@ snapshots:
optionalDependencies:
'@types/node': 22.19.3
fsevents: 2.3.3
- lightningcss: 1.31.1
+ lightningcss: 1.32.0
sass: 1.97.3
terser: 5.46.0
- vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2):
+ vite@6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2):
+ dependencies:
+ esbuild: 0.25.12
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.53.4
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 22.19.17
+ fsevents: 2.3.3
+ jiti: 2.6.1
+ lightningcss: 1.32.0
+ sass: 1.97.3
+ terser: 5.46.0
+ yaml: 2.8.2
+
+ vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2):
dependencies:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.3)
@@ -30999,16 +32131,20 @@ snapshots:
'@types/node': 25.1.0
fsevents: 2.3.3
jiti: 2.6.1
- lightningcss: 1.31.1
+ lightningcss: 1.32.0
sass: 1.97.3
terser: 5.46.0
yaml: 2.8.2
- vitefu@1.1.2(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)):
+ vitefu@1.1.2(vite@6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)):
+ optionalDependencies:
+ vite: 6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+
+ vitefu@1.1.2(vite@6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)):
optionalDependencies:
- vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vite: 6.4.1(@types/node@25.1.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
- vitest@0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0):
+ vitest@0.32.4(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(playwright@1.57.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
'@types/chai': 4.3.20
'@types/chai-subset': 1.3.6(@types/chai@4.3.20)
@@ -31031,8 +32167,8 @@ snapshots:
strip-literal: 1.3.0
tinybench: 2.9.0
tinypool: 0.5.0
- vite: 4.5.14(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
- vite-node: 0.32.4(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 4.5.14(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
+ vite-node: 0.32.4(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
why-is-node-running: 2.3.0
optionalDependencies:
happy-dom: 15.10.2
@@ -31047,10 +32183,10 @@ snapshots:
- supports-color
- terser
- vitest@2.1.9(@types/node@22.19.17)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vitest@2.1.9(@types/node@22.19.17)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
'@vitest/expect': 2.1.9
- '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0))
+ '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))
'@vitest/pretty-format': 2.1.9
'@vitest/runner': 2.1.9
'@vitest/snapshot': 2.1.9
@@ -31066,8 +32202,8 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.1.1
tinyrainbow: 1.2.0
- vite: 5.4.21(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
- vite-node: 2.1.9(@types/node@22.19.17)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 5.4.21(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
+ vite-node: 2.1.9(@types/node@22.19.17)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 22.19.17
@@ -31084,10 +32220,10 @@ snapshots:
- supports-color
- terser
- vitest@2.1.9(@types/node@22.19.3)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0):
+ vitest@2.1.9(@types/node@22.19.3)(happy-dom@15.10.2)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0):
dependencies:
'@vitest/expect': 2.1.9
- '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0))
+ '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))
'@vitest/pretty-format': 2.1.9
'@vitest/runner': 2.1.9
'@vitest/snapshot': 2.1.9
@@ -31103,8 +32239,8 @@ snapshots:
tinyexec: 0.3.2
tinypool: 1.1.1
tinyrainbow: 1.2.0
- vite: 5.4.21(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
- vite-node: 2.1.9(@types/node@22.19.3)(lightningcss@1.31.1)(sass@1.97.3)(terser@5.46.0)
+ vite: 5.4.21(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
+ vite-node: 2.1.9(@types/node@22.19.3)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 22.19.3
@@ -31121,6 +32257,128 @@ snapshots:
- supports-color
- terser
+ vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@15.10.2)(jiti@2.6.1)(jsdom@15.2.1(bufferutil@4.1.0))(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2):
+ dependencies:
+ '@types/chai': 5.2.3
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.3.0
+ magic-string: 0.30.21
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 6.4.1(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ vite-node: 3.2.4(@types/node@22.19.17)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/debug': 4.1.12
+ '@types/node': 22.19.17
+ happy-dom: 15.10.2
+ jsdom: 15.2.1(bufferutil@4.1.0)
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ volar-service-css@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-css-languageservice: 6.3.10
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-emmet@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ '@emmetio/css-parser': 0.4.1
+ '@emmetio/html-matcher': 1.3.0
+ '@vscode/emmet-helper': 2.11.0
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-html@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-html-languageservice: 5.6.2
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-prettier@0.0.70(@volar/language-service@2.4.28)(prettier@3.8.3):
+ dependencies:
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+ prettier: 3.8.3
+
+ volar-service-typescript-twoslash-queries@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-typescript@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ path-browserify: 1.0.1
+ semver: 7.7.3
+ typescript-auto-import-cache: 0.3.6
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-nls: 5.2.0
+ vscode-uri: 3.1.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ volar-service-yaml@0.0.70(@volar/language-service@2.4.28):
+ dependencies:
+ vscode-uri: 3.1.0
+ yaml-language-server: 1.20.0
+ optionalDependencies:
+ '@volar/language-service': 2.4.28
+
+ vscode-css-languageservice@6.3.10:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ vscode-html-languageservice@5.6.2:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+
+ vscode-json-languageservice@4.1.8:
+ dependencies:
+ jsonc-parser: 3.3.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-nls: 5.2.0
+ vscode-uri: 3.1.0
+
vscode-jsonrpc@8.2.0: {}
vscode-languageserver-protocol@3.17.5:
@@ -31136,8 +32394,12 @@ snapshots:
dependencies:
vscode-languageserver-protocol: 3.17.5
+ vscode-nls@5.2.0: {}
+
vscode-uri@3.0.8: {}
+ vscode-uri@3.1.0: {}
+
w3c-hr-time@1.0.2:
dependencies:
browser-process-hrtime: 1.0.0
@@ -31323,8 +32585,24 @@ snapshots:
yallist@5.0.0: {}
+ yaml-language-server@1.20.0:
+ dependencies:
+ '@vscode/l10n': 0.0.18
+ ajv: 8.17.1
+ ajv-draft-04: 1.0.0(ajv@8.17.1)
+ prettier: 3.8.3
+ request-light: 0.5.8
+ vscode-json-languageservice: 4.1.8
+ vscode-languageserver: 9.0.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-languageserver-types: 3.17.5
+ vscode-uri: 3.1.0
+ yaml: 2.7.1
+
yaml@1.10.2: {}
+ yaml@2.7.1: {}
+
yaml@2.8.2: {}
yargs-parser@20.2.9: {}