diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..f2ffbce --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,36 @@ +name: Test + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + node: ['20.19.0', '22'] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: npm + cache-dependency-path: npm-shrinkwrap.json + - run: npm ci + - run: npm run test:unit + - run: npm run check:contrast + - run: npx playwright install --with-deps chromium + - run: npm run test:e2e -- --workers=2 + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: test-results-node-${{ matrix.node }} + path: test-results/ + retention-days: 7 diff --git a/README.md b/README.md index 3c0ef71..bac94d6 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ docview ./docs --no-open ## Custom CSS -Place a `.docview.css` file in the directory you are viewing (or any parent directory). DocView will automatically load it and apply your styles on top of the default theme. +Place a `.docview.css` file in the directory you are viewing. DocView will automatically load it and apply your styles on top of the default theme. Symlinks must resolve inside the served directory. Set `--font-size-base` to customize the document size used at the 100% Text size setting. @@ -179,6 +179,22 @@ fixtures/** # everything under fixtures/ `.gitignore` is intentionally **not** honored automatically, because files like `.env` are commonly git-ignored yet you usually want to view them here. +## Development and verification + +Use `npm ci` to reproduce the dependencies in `npm-shrinkwrap.json`. Installation +also builds the frontend. Run `npm run test:unit`, `npm run check:contrast`, and, +after `npx playwright install chromium`, `npm run test:e2e` to verify changes. + +To run the CLI using this checkout's fixed dependency tree, use +`node bin/mdv.mjs /path/to/documents` after `npm ci`. In the npm 11.9 environment +used for the audit, installing DocView as a dependency from GitHub or a tarball +re-resolved upstream-pinned dependencies instead of using the bundled shrinkwrap; +see [the audit record](docs/audit-2026-09-13.md) for the remaining dependency issue. + +The C2PA native module is optional. If it cannot be installed, normal document +viewing and byte-based provenance detection remain available; cryptographic +C2PA verification is unavailable in that environment. + ## Tech Stack - **[Vite](https://vitejs.dev/)** — build tooling and dev server diff --git a/bin/mdv.mjs b/bin/mdv.mjs index df14033..6e1f8b0 100755 --- a/bin/mdv.mjs +++ b/bin/mdv.mjs @@ -73,16 +73,25 @@ const child = fork(serverPath, filteredArgs, { stdio: ['inherit', 'pipe', 'inher child.stdout.on('data', (data) => { process.stdout.write(data); - const match = data.toString().match(/localhost:(\d+)/); - if (match && !noOpen) { - const actualPort = match[1]; - const url = `http://localhost:${actualPort}/`; - const platform = process.platform; - const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open'; - execFile(cmd, [url], () => {}); - } }); +// The server already reports readiness over IPC. Parsing stdout can match a +// document directory containing "localhost:1234", or miss a split log chunk. +let opened = false; +child.on('message', (message) => { + if (message?.type !== 'listening' || noOpen || opened) return; + opened = true; + const url = message.url || `http://localhost:${message.port}/`; + const platform = process.platform; + // `start` is a cmd.exe builtin, not an executable accepted by execFile. + const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'explorer.exe' : 'xdg-open'; + execFile(cmd, [url], () => {}); +}); + +for (const signal of ['SIGINT', 'SIGTERM']) { + process.on(signal, () => child.kill(signal)); +} + child.on('error', (err) => { process.stderr.write(`Failed to start DocView server: ${err.message}\n`); process.exit(1); diff --git a/docs/audit-2026-09-13.md b/docs/audit-2026-09-13.md new file mode 100644 index 0000000..c507ab0 --- /dev/null +++ b/docs/audit-2026-09-13.md @@ -0,0 +1,121 @@ +# DocView 不具合監査・修正記録 + +対象: `main` の `563094060805aa542075a25c9e857a5a6e611689`。 +サーバー、CLI、全フロントエンドモジュール、画像解析、既存テスト、テーマ、依存関係、配布設定をレビューした。 +以下は今回確認・修正した問題の一覧であり、未知の不具合が存在しないことを保証するものではない。 + +## サーバー・CLI + +| 問題 | 対応 | +|---|---| +| 不正なパーセントエンコードの raw URL でサーバーが終了 | 400 応答に変換 | +| diagram API の `null`・不正な source 型でサーバーが終了 | JSON 形状・文字列型を検証 | +| 外部描画 CLI の stdin エラー・stderr 詰まり | エラーハンドラーと出力処理を追加 | +| 検索・backlinks・tree・gallery・custom CSS の外部 symlink 漏洩 | 公開ルート内への realpath 解決を検証 | +| IPv6 URL の角括弧によりリモート取得失敗 | 接続ホストを正規化 | +| IPv4-mapped IPv6 と link-local 範囲の private 判定漏れ | 対象表現と範囲を修正 | +| OS opener 不在でプロセスが終了 | 非同期起動失敗を API エラーへ変換 | +| TCP チャンク境界で日本語 JSON が破損 | バイト列結合後に UTF-8 復号 | +| JSON 本文のサイズ上限が文字数依存 | バイト数で制限 | +| ZIP の生成連番と実ファイル名が衝突 | 全エントリーを一意化 | +| `.docviewignore` の `?` による不正な正規表現 | 1 文字ワイルドカードへ変換 | +| `.env` の変更がライブ更新されない | 対象の隠しファイルを監視 | +| 巨大な remote サイズ指定が上限を無効化 | 安全な整数を検証 | +| stdout 内の URL による誤ったブラウザー起動・重複起動 | IPC の ready 通知を使用 | +| Windows の `start` を実行可能ファイルとして起動 | `explorer.exe` を使用 | +| CLI 終了時の子プロセス残存 | SIGINT / SIGTERM を伝搬 | +| 病的な正規表現が HTTP イベントループを停止 | Worker へ隔離し 1 ファイル 1 秒で打ち切り | + +主な回帰テスト: `tests/server-audit.test.mjs`。 + +## ナビゲーション・検索 + +| 問題 | 対応 | +|---|---| +| 古い file / SVG / PDF / Office / remote 応答が新画面を上書き | 読み込み世代を検証 | +| 閉じた分割ペインの応答が左ペインへ描画 | 世代・元 DOM・ペイン状態を検証 | +| 検索を閉じる・消す・モード変更後に旧結果が復活 | 入力変更時点で検索を失効 | +| 遅いファイル一覧取得後に現在の検索が更新されない | 現在の入力を再評価 | +| URL バーで後から作成されたファイルを開けない | 送信時に存在確認を再実行 | +| キャンセルした URL バーの存在確認完了後に遷移 | 入力・表示状態を検証 | +| 遅延 import 失敗が永続キャッシュされる | 失敗時に Promise キャッシュを解放 | +| 相対 URI・`..`・remote 文書内の画像やリンクが誤解決 | 文書の実 URL / パスを基準に解決 | +| 巨大な `line=1-999999999999` でブラウザーが停止 | 実在する DOM 行だけを走査 | +| ゼロ・安全な整数を超える行指定 | 不正な行指定を除外 | +| TOC の ID 内 `&` が実体参照へ変換 | 属性値を適切にエスケープ | +| 破損した recent localStorage で起動失敗 | 配列・文字列の型を検証 | +| 比較終了後のスケルトン・タイトルの不整合 | 元ファイルを再描画 | +| 分割表示・File 入力で動画をテキスト扱い | 動画プレーヤーへ接続 | +| ファイル選択の accept が新形式を含まない | 対応拡張子と整合 | +| Marp 遅延生成・重複・相対画像の不整合 | 世代、オーバーレイ、画像 URL を補正 | + +主な回帰テスト: `tests/navigation-audit.spec.ts`。 + +## 文書・データ表示 + +| 問題 | 対応 | +|---|---| +| HTML の画像保存時にスクリプトが親 DOM / storage へ到達 | 通常プレビューから DOM を受け取り、スクリプト禁止 iframe で撮影 | +| scripts off の HTML でも保存時にスクリプトが実行 | 撮影側では常に scripts を禁止 | +| HTML リソース URL の `%20` / `%25` 二重エンコード | 一度デコードし正規化後に再エンコード | +| Marp のコメント付き true を見落とし、nested true を誤認 | YAML ルートの boolean を検証 | +| Wiki link の fragment / 親ディレクトリのドットを誤処理 | ファイル名だけで拡張子を判定 | +| Mermaid 構文エラーの一時 SVG が画面に残る | 内部エラー描画を無効化 | +| 空 CSV のパスが HTML として挿入 | エスケープ | +| CSV の `00123`・ISO 日時・指数表記が変形 | 原文の文字列を保持 | +| 空欄・指数表記のある数値列のソート不正 | 数値判定と比較を補正 | +| JSONL の空行・不正行後の行番号ずれ | 元の行番号を保持 | +| JSONL の欠落キーから継承プロパティが表示 | own property のみ使用 | +| JSON / YAML の空文字キーが消える | ルート判定と分離 | +| 循環 YAML で表示失敗 | 循環参照を明示 | +| Secret Safe の短い値・引用値・複合キー・コンテナ漏れ | キーと値全体を検証してマスク | +| CSV / YAML の非表示 Source DOM に機密値が残る | 形式別に Source もマスク | +| 大きな表・未知拡張子・title 属性でマスク欠落 | 全表示経路へ適用 | +| chunk 検索で HTML 実体参照が壊れる | 生文字列で一致位置を求め、各部分をエスケープ | +| 古い chunk 検索・ページ応答で表示上書き | 世代と画面の所有状態を検証 | +| chunk 通信失敗で Loading が残る | エラーと移動ボタン状態を更新 | +| 推定行数が少ない大きな JSONL の深いリンクがずれる | 実測件数で調整 | +| CSV / TSV の引用符内改行がページ境界で壊れる | `records=1` で論理レコード単位の range / search | +| CSV 検索でヘッダーがデータ行に混ざる | ヘッダーを別メタデータとして保持 | +| Laravel CRLF ログを形式判定できない | CR を除去 | +| cron コマンド内の空白が潰れる | 本文を保持 | +| コマンドなし・実行不能日の cron を有効扱い | 構文と実行可能性を検証 | +| cron 衝突時刻のタイムゾーン不整合・検査範囲の誤表示 | JST に統一し 35 日 / 1,500 回の上限を明示 | + +主な回帰テスト: `tests/rendering-audit.spec.ts`、`tests/data-audit.spec.ts`。 + +## 画像・アルバム + +| 問題 | 対応 | +|---|---| +| SVG の megapixels `N/A` に数値メソッドを呼び表示失敗 | 型を検証 | +| lossy WebP の寸法が 1 px 大きい | VP8 の値をそのまま使用 | +| 短い VP8L ヘッダーを読めない | 形式別の最小サイズを検証 | +| SVG の `%` 指定を px と誤認 | viewBox にフォールバック | +| 不完全 PNG の寸法・テキストを採用 | チャンク型・長さ・範囲を検証 | +| 非有限寸法で GCD が終了しない | 正で有限の値だけを採用 | +| metadata パネルの再生成で DOM が重複 | 所有要素を削除 | +| クリップボード失敗でも成功表示 | 結果を待ち、失敗を表示 | +| 古い album 応答が現在の画像・キーボード状態を上書き | AbortController と世代・DOM を検証 | +| メディア待機中にライトボックスを閉じられない | 待機前に閉じる操作を登録 | +| 遅い SVG が次の画像を上書き | 移動・終了時に中断 | +| 終了後の動画再生・ズームイベント残存 | メディアとリスナーを解放 | + +主な回帰テスト: `tests/image-meta-audit.test.mjs`、`tests/media-audit.spec.ts`。 + +## テーマ・依存関係・検証 + +- 既存コントラスト検査の 11 失敗を修正。半透明色を背景と合成して検査し、30 テーマ × 10 項目を確認する。 +- DOMPurify、markdown-it、Mermaid、Vite と推移依存を互換範囲で更新。固定依存環境の `npm audit` は 14 件から 0 件。 +- C2PA を任意依存にし、ネイティブ導入失敗時も閲覧とバイト走査を利用可能にした。 +- npm の固定依存を `npm-shrinkwrap.json` で管理する。 +- Node の単体テストと Playwright のテスト探索を分離する。 +- GitHub Actions に Node 20.19.0 / 22 のインストール・ビルド・単体・コントラスト・E2E 検証を追加する。 + +## 検証上の制約と残件 + +- ローカル環境では Chromium が起動時に SIGTRAP で終了し、接続済みブラウザーから localhost へのアクセスも拒否された。ブラウザー E2E の結果は PR の GitHub Actions 結果を参照する。テスト登録・型チェックの成功だけを E2E 成功として扱わない。 +- Windows / macOS の OS アプリ起動は実機未検証。 +- HTML 撮影では読み取り可能な Canvas を画像として保持する。CORS で読み取り不能な Canvas、closed Shadow DOM、属性に反映されないフォーム状態は完全には保持できない。CSP 等で応答を得られない場合は元 HTML の安全な描画へフォールバックする。 +- この検証環境の npm 11.9 では、最終コミットを GitHub または tarball から別プロジェクトの依存として導入すると、同梱 shrinkwrap の修正版解決が適用されず、sharp 0.34.3 / xmldom 0.9.10 が再導入された。ソース・tarball・導入後の shrinkwrap の一致と、実際の node_modules の版を確認した。audit 0 件はリポジトリの `npm ci` 環境に限定される。固定依存を使うにはチェックアウトで `npm ci` 後に `node bin/mdv.mjs /path/to/documents` を実行する。上流固定依存の解消は残件。 +- C2PA native が利用できない環境では暗号署名の検証は行えない。縮退経路は単体テストで確認した。 diff --git a/index.html b/index.html index a2a1168..09aa613 100644 --- a/index.html +++ b/index.html @@ -161,7 +161,7 @@

- + diff --git a/lib/image-meta.mjs b/lib/image-meta.mjs index bada889..13f6edd 100644 --- a/lib/image-meta.mjs +++ b/lib/image-meta.mjs @@ -47,8 +47,9 @@ function classifyC2paValidation(validationStatus) { function parsePngDimensions(buf) { // PNG シグネチャ(8) + IHDR チャンク長(4) + 'IHDR'(4) + width(4) + height(4) - if (buf.length < 24) return null; + if (buf.length < 26) return null; if (buf.readUInt32BE(0) !== 0x89504e47 || buf.readUInt32BE(4) !== 0x0d0a1a0a) return null; + if (buf.readUInt32BE(8) !== 13 || buf.toString('ascii', 12, 16) !== 'IHDR') return null; const width = buf.readUInt32BE(16); const height = buf.readUInt32BE(20); const bitDepth = buf[24]; @@ -91,13 +92,13 @@ function parseGifDimensions(buf) { } function parseWebpDimensions(buf) { - if (buf.length < 30) return null; + if (buf.length < 16) return null; if (buf.slice(0, 4).toString('ascii') !== 'RIFF') return null; if (buf.slice(8, 12).toString('ascii') !== 'WEBP') return null; const chunkType = buf.slice(12, 16).toString('ascii'); if (chunkType === 'VP8 ' && buf.length >= 30) { - const width = (buf.readUInt16LE(26) & 0x3fff) + 1; - const height = (buf.readUInt16LE(28) & 0x3fff) + 1; + const width = buf.readUInt16LE(26) & 0x3fff; + const height = buf.readUInt16LE(28) & 0x3fff; return { width, height }; } if (chunkType === 'VP8L' && buf.length >= 25) { @@ -128,12 +129,15 @@ function parseSvgDimensions(buf) { const svgMatch = text.match(/]*>/i); if (!svgMatch) return null; const tag = svgMatch[0]; - const wMatch = tag.match(/\bwidth=["']([0-9.]+)/i); - const hMatch = tag.match(/\bheight=["']([0-9.]+)/i); + // Percent/relative lengths are viewport-dependent, not pixel dimensions. + // Only use unitless/px lengths here; otherwise use the intrinsic viewBox. + const number = '[+]?(?:[0-9]+(?:\\.[0-9]*)?|\\.[0-9]+)(?:e[+-]?[0-9]+)?'; + const wMatch = tag.match(new RegExp(`\\swidth\\s*=\\s*["']\\s*(${number})(?:px)?\\s*["']`, 'i')); + const hMatch = tag.match(new RegExp(`\\sheight\\s*=\\s*["']\\s*(${number})(?:px)?\\s*["']`, 'i')); if (wMatch && hMatch) { return { width: parseFloat(wMatch[1]), height: parseFloat(hMatch[1]), isSvg: true }; } - const vbMatch = tag.match(/viewBox=["']([0-9.\s,-]+)/i); + const vbMatch = tag.match(/\sviewBox\s*=\s*["']([^"']+)["']/i); if (vbMatch) { const parts = vbMatch[1].trim().split(/[\s,]+/); if (parts.length >= 4) { @@ -163,7 +167,8 @@ export function parseDimensions(buf, ext) { function gcd(a, b) { return b === 0 ? a : gcd(b, a % b); } export function buildDimensions(raw, ext) { - if (!raw || !raw.width || !raw.height) return null; + if (!raw || !Number.isFinite(raw.width) || !Number.isFinite(raw.height) || + raw.width <= 0 || raw.height <= 0) return null; const { width, height } = raw; const g = gcd(width, height); const aspectRatio = `${width / g}:${height / g}`; @@ -209,8 +214,11 @@ export function parsePngTextChunks(buf) { const length = buf.readUInt32BE(pos); const type = buf.slice(pos + 4, pos + 8).toString('ascii'); if (type === 'IEND') break; - const data = buf.slice(pos + 8, pos + 8 + length); - decodePngTextChunk(type, data, chunks); + if (pos + 12 + length > buf.length) break; + if (length <= MAX_TEXT_CHUNK) { + const data = buf.slice(pos + 8, pos + 8 + length); + decodePngTextChunk(type, data, chunks); + } pos += 12 + length; } return chunks; diff --git a/lib/server-regex.mjs b/lib/server-regex.mjs new file mode 100644 index 0000000..e3c22ff --- /dev/null +++ b/lib/server-regex.mjs @@ -0,0 +1,46 @@ +import { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads'; + +// Keep user-supplied regular expressions off the HTTP event loop. Pattern +// heuristics cannot reliably identify every exponential or polynomial case. +if (!isMainThread && workerData?.docviewRegex) { + const regex = new RegExp(workerData.pattern, 'i'); + parentPort.on('message', ({ lines, limit }) => { + const matches = []; + for (let i = 0; i < lines.length && matches.length < limit; i++) { + if (regex.test(lines[i])) matches.push(i); + } + parentPort.postMessage(matches); + }); +} + +export function createRegexSearch(pattern, timeoutMs = 1000) { + const worker = new Worker(new URL(import.meta.url), { + workerData: { docviewRegex: true, pattern }, + }); + let pending; + function finish(error, matches) { + if (!pending) return; + const { resolve, reject, timer } = pending; + pending = undefined; + clearTimeout(timer); + if (error) reject(Object.assign(error, { regexSearch: true })); + else resolve(matches); + } + worker.on('message', (matches) => finish(null, matches)); + worker.on('error', (error) => finish(error)); + worker.on('exit', () => finish(new Error('Regex search worker stopped'))); + + return { + findMatches(lines, limit) { + return new Promise((resolve, reject) => { + const timer = setTimeout(() => { + finish(Object.assign(new Error('Regex search took too long'), { status: 400 })); + void worker.terminate(); + }, timeoutMs); + pending = { resolve, reject, timer }; + worker.postMessage({ lines, limit }); + }); + }, + close() { return worker.terminate(); }, + }; +} diff --git a/package-lock.json b/npm-shrinkwrap.json similarity index 88% rename from package-lock.json rename to npm-shrinkwrap.json index e66c5a5..2713fb0 100644 --- a/package-lock.json +++ b/npm-shrinkwrap.json @@ -10,16 +10,15 @@ "license": "MIT", "dependencies": { "@marp-team/marp-core": "^4.3.0", - "c2pa-node": "^0.5.26", "chokidar": "^5.0.0", "cron-parser": "^5.5.0", "cronstrue": "^3.14.0", - "dompurify": "^3.3.3", + "dompurify": "^3.4.15", "exifr": "^7.1.3", "highlight.js": "^11.11.1", "jschardet": "^3.1.4", "katex": "^0.16.45", - "markdown-it": "^14.1.1", + "markdown-it": "^14.3.2", "markdown-it-anchor": "^9.2.0", "markdown-it-container": "^4.0.0", "markdown-it-deflist": "^3.0.0", @@ -31,7 +30,7 @@ "markdown-it-sub": "^2.0.0", "markdown-it-sup": "^2.0.0", "markdown-it-texmath": "^1.0.0", - "mermaid": "^11.14.0", + "mermaid": "^11.17.2", "modern-screenshot": "^4.6.8", "papaparse": "^5.5.3", "yaml": "^2.8.3" @@ -46,10 +45,13 @@ "@types/markdown-it": "^14.1.2", "@types/papaparse": "^5.5.2", "typescript": "~6.0.2", - "vite": "^8.0.4" + "vite": "^8.3.0" }, "engines": { "node": ">=20.19.0" + }, + "optionalDependencies": { + "c2pa-node": "^0.5.26" } }, "node_modules/@antfu/install-pkg": { @@ -70,6 +72,7 @@ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", "license": "MIT", + "optional": true, "engines": { "node": ">=6.9.0" } @@ -85,6 +88,7 @@ "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.1.1.tgz", "integrity": "sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/config": "^3.1.4", "@changesets/get-version-range-type": "^0.4.0", @@ -106,6 +110,7 @@ "resolved": "https://registry.npmjs.org/@changesets/assemble-release-plan/-/assemble-release-plan-6.0.10.tgz", "integrity": "sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.4", @@ -120,6 +125,7 @@ "resolved": "https://registry.npmjs.org/@changesets/changelog-git/-/changelog-git-0.2.1.tgz", "integrity": "sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/types": "^6.1.0" } @@ -129,6 +135,7 @@ "resolved": "https://registry.npmjs.org/@changesets/cli/-/cli-2.31.0.tgz", "integrity": "sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/apply-release-plan": "^7.1.1", "@changesets/assemble-release-plan": "^6.0.10", @@ -166,6 +173,7 @@ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.11.tgz", "integrity": "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==", "license": "MIT", + "optional": true, "dependencies": { "quansync": "^0.2.7" } @@ -175,6 +183,7 @@ "resolved": "https://registry.npmjs.org/@changesets/config/-/config-3.1.4.tgz", "integrity": "sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/get-dependents-graph": "^2.1.4", @@ -191,6 +200,7 @@ "resolved": "https://registry.npmjs.org/@changesets/errors/-/errors-0.2.0.tgz", "integrity": "sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==", "license": "MIT", + "optional": true, "dependencies": { "extendable-error": "^0.1.5" } @@ -200,6 +210,7 @@ "resolved": "https://registry.npmjs.org/@changesets/get-dependents-graph/-/get-dependents-graph-2.1.4.tgz", "integrity": "sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3", @@ -212,6 +223,7 @@ "resolved": "https://registry.npmjs.org/@changesets/get-release-plan/-/get-release-plan-4.0.16.tgz", "integrity": "sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/assemble-release-plan": "^6.0.10", "@changesets/config": "^3.1.4", @@ -225,13 +237,15 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/@changesets/get-version-range-type/-/get-version-range-type-0.4.0.tgz", "integrity": "sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/@changesets/git": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@changesets/git/-/git-3.0.4.tgz", "integrity": "sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/errors": "^0.2.0", "@manypkg/get-packages": "^1.1.3", @@ -245,6 +259,7 @@ "resolved": "https://registry.npmjs.org/@changesets/logger/-/logger-0.1.1.tgz", "integrity": "sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==", "license": "MIT", + "optional": true, "dependencies": { "picocolors": "^1.1.0" } @@ -254,6 +269,7 @@ "resolved": "https://registry.npmjs.org/@changesets/parse/-/parse-0.4.3.tgz", "integrity": "sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/types": "^6.1.0", "js-yaml": "^4.1.1" @@ -264,6 +280,7 @@ "resolved": "https://registry.npmjs.org/@changesets/pre/-/pre-2.0.2.tgz", "integrity": "sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/errors": "^0.2.0", "@changesets/types": "^6.1.0", @@ -276,6 +293,7 @@ "resolved": "https://registry.npmjs.org/@changesets/read/-/read-0.6.7.tgz", "integrity": "sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/git": "^3.0.4", "@changesets/logger": "^0.1.1", @@ -291,6 +309,7 @@ "resolved": "https://registry.npmjs.org/@changesets/should-skip-package/-/should-skip-package-0.1.2.tgz", "integrity": "sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/types": "^6.1.0", "@manypkg/get-packages": "^1.1.3" @@ -300,13 +319,15 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/@changesets/types/-/types-6.1.0.tgz", "integrity": "sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/@changesets/write": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@changesets/write/-/write-0.4.0.tgz", "integrity": "sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==", "license": "MIT", + "optional": true, "dependencies": { "@changesets/types": "^6.1.0", "fs-extra": "^7.0.1", @@ -314,41 +335,10 @@ "prettier": "^2.7.1" } }, - "node_modules/@chevrotain/cst-dts-gen": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-12.0.0.tgz", - "integrity": "sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg==", - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/gast": "12.0.0", - "@chevrotain/types": "12.0.0" - } - }, - "node_modules/@chevrotain/gast": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-12.0.0.tgz", - "integrity": "sha512-1ne/m3XsIT8aEdrvT33so0GUC+wkctpUPK6zU9IlOyJLUbR0rg4G7ZiApiJbggpgPir9ERy3FRjT6T7lpgetnQ==", - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/types": "12.0.0" - } - }, - "node_modules/@chevrotain/regexp-to-ast": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-12.0.0.tgz", - "integrity": "sha512-p+EW9MaJwgaHguhoqwOtx/FwuGr+DnNn857sXWOi/mClXIkPGl3rn7hGNWvo31HA3vyeQxjqe+H36yZJwYU8cA==", - "license": "Apache-2.0" - }, "node_modules/@chevrotain/types": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-12.0.0.tgz", - "integrity": "sha512-S+04vjFQKeuYw0/eW3U52LkAHQsB1ASxsPGsLPUyQgrZ2iNNibQrsidruDzjEX2JYfespXMG0eZmXlhA6z7nWA==", - "license": "Apache-2.0" - }, - "node_modules/@chevrotain/utils": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-12.0.0.tgz", - "integrity": "sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz", + "integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==", "license": "Apache-2.0" }, "node_modules/@csstools/postcss-is-pseudo-class": { @@ -421,33 +411,10 @@ "postcss-selector-parser": "^7.0.0" } }, - "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", "license": "MIT", "optional": true, "dependencies": { @@ -471,10 +438,20 @@ "mlly": "^1.8.0" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.3.tgz", - "integrity": "sha512-ryFMfvxxpQRsgZJqBd4wsttYQbCxsJksrv9Lw/v798JcQ8+w84mBWuXwl+TT0WJ/WrYOLaYpwQXi3sA9nTIaIg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", "cpu": [ "arm64" ], @@ -484,19 +461,19 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.0" + "@img/sharp-libvips-darwin-arm64": "1.3.3" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.3.tgz", - "integrity": "sha512-yHpJYynROAj12TA6qil58hmPmAwxKKC7reUqtGLzsOHfP7/rniNGTL8tjWX6L3CTV4+5P4ypcS7Pp+7OB+8ihA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", "cpu": [ "x64" ], @@ -506,19 +483,38 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.0" + "@img/sharp-libvips-darwin-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.0.tgz", - "integrity": "sha512-sBZmpwmxqwlqG9ueWFXtockhsxefaV6O84BMOrhtg/YqbTaRdqDE7hxraVE3y6gVM4eExmfzW4a8el9ArLeEiQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", "cpu": [ "arm64" ], @@ -532,9 +528,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.0.tgz", - "integrity": "sha512-M64XVuL94OgiNHa5/m2YvEQI5q2cl9d/wk0qFTDVXcYzi43lxuiFTftMR1tOnFQovVXNZJ5TURSDK2pNe9Yzqg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", "cpu": [ "x64" ], @@ -548,9 +544,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.0.tgz", - "integrity": "sha512-mWd2uWvDtL/nvIzThLq3fr2nnGfyr/XMXlq8ZJ9WMR6PXijHlC3ksp0IpuhK6bougvQrchUAfzRLnbsen0Cqvw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", "cpu": [ "arm" ], @@ -564,9 +560,9 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.0.tgz", - "integrity": "sha512-RXwd0CgG+uPRX5YYrkzKyalt2OJYRiJQ8ED/fi1tq9WQW2jsQIn0tqrlR5l5dr/rjqq6AHAxURhj2DVjyQWSOA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", "cpu": [ "arm64" ], @@ -580,9 +576,9 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.0.tgz", - "integrity": "sha512-Xod/7KaDDHkYu2phxxfeEPXfVXFKx70EAFZ0qyUdOjCcxbjqyJOEUpDe6RIyaunGxT34Anf9ue/wuWOqBW2WcQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", "cpu": [ "ppc64" ], @@ -595,10 +591,26 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.0.tgz", - "integrity": "sha512-eMKfzDxLGT8mnmPJTNMcjfO33fLiTDsrMlUVcp6b96ETbnJmd4uvZxVJSKPQfS+odwfVaGifhsB07J1LynFehw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", "cpu": [ "s390x" ], @@ -612,9 +624,9 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.0.tgz", - "integrity": "sha512-ZW3FPWIc7K1sH9E3nxIGB3y3dZkpJlMnkk7z5tu1nSkBoCgw2nSRTFHI5pB/3CQaJM0pdzMF3paf9ckKMSE9Tg==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", "cpu": [ "x64" ], @@ -628,9 +640,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.0.tgz", - "integrity": "sha512-UG+LqQJbf5VJ8NWJ5Z3tdIe/HXjuIdo4JeVNADXBFuG7z9zjoegpzzGIyV5zQKi4zaJjnAd2+g2nna8TZvuW9Q==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", "cpu": [ "arm64" ], @@ -644,9 +656,9 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.0.tgz", - "integrity": "sha512-SRYOLR7CXPgNze8akZwjoGBoN1ThNZoqpOgfnOxmWsklTGVfJiGJoC/Lod7aNMGA1jSsKWM1+HRX43OP6p9+6Q==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", "cpu": [ "x64" ], @@ -660,9 +672,9 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.3.tgz", - "integrity": "sha512-oBK9l+h6KBN0i3dC8rYntLiVfW8D8wH+NPNT3O/WBHeW0OQWCjfWksLUaPidsrDKpJgXp3G3/hkmhptAW0I3+A==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", "cpu": [ "arm" ], @@ -672,19 +684,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.0" + "@img/sharp-libvips-linux-arm": "1.3.3" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.3.tgz", - "integrity": "sha512-QdrKe3EvQrqwkDrtuTIjI0bu6YEJHTgEeqdzI3uWJOH6G1O8Nl1iEeVYRGdj1h5I21CqxSvQp1Yv7xeU3ZewbA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", "cpu": [ "arm64" ], @@ -694,19 +706,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.0" + "@img/sharp-libvips-linux-arm64": "1.3.3" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.3.tgz", - "integrity": "sha512-GLtbLQMCNC5nxuImPR2+RgrviwKwVql28FWZIW1zWruy6zLgA5/x2ZXk3mxj58X/tszVF69KK0Is83V8YgWhLA==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", "cpu": [ "ppc64" ], @@ -716,19 +728,41 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.0" + "@img/sharp-libvips-linux-riscv64": "1.3.3" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.3.tgz", - "integrity": "sha512-3gahT+A6c4cdc2edhsLHmIOXMb17ltffJlxR0aC2VPZfwKoTGZec6u5GrFgdR7ciJSsHT27BD3TIuGcuRT0KmQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", "cpu": [ "s390x" ], @@ -738,19 +772,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.0" + "@img/sharp-libvips-linux-s390x": "1.3.3" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.3.tgz", - "integrity": "sha512-8kYso8d806ypnSq3/Ly0QEw90V5ZoHh10yH0HnrzOCr6DKAPI6QVHvwleqMkVQ0m+fc7EH8ah0BB0QPuWY6zJQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", "cpu": [ "x64" ], @@ -760,19 +794,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.0" + "@img/sharp-libvips-linux-x64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.3.tgz", - "integrity": "sha512-vAjbHDlr4izEiXM1OTggpCcPg9tn4YriK5vAjowJsHwdBIdx0fYRsURkxLG2RLm9gyBq66gwtWI8Gx0/ov+JKQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", "cpu": [ "arm64" ], @@ -782,19 +816,19 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.0" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.3.tgz", - "integrity": "sha512-gCWUn9547K5bwvOn9l5XGAEjVTTRji4aPTqLzGXHvIr6bIDZKNTA34seMPgM0WmSf+RYBH411VavCejp3PkOeQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", "cpu": [ "x64" ], @@ -804,38 +838,54 @@ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.0" + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.3.tgz", - "integrity": "sha512-+CyRcpagHMGteySaWos8IbnXcHgfDn7pO2fiC2slJxvNq9gDipYBN42/RagzctVRKgxATmfqOSulgZv5e1RdMg==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", "cpu": [ "wasm32" ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "license": "Apache-2.0", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.4.4" + "@img/sharp-wasm32": "0.35.4" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.3.tgz", - "integrity": "sha512-MjnHPnbqMXNC2UgeLJtX4XqoVHHlZNd+nPt1kRPmj63wURegwBhZlApELdtxM2OIZDRv/DFtLcNhVbd1z8GYXQ==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", "cpu": [ "arm64" ], @@ -845,16 +895,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.3.tgz", - "integrity": "sha512-xuCdhH44WxuXgOM714hn4amodJMZl3OEvf0GVTm0BEyMeA2to+8HEdRPShH0SLYptJY1uBw+SCFP9WVQi1Q/cw==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", "cpu": [ "ia32" ], @@ -864,16 +914,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": "^20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.3.tgz", - "integrity": "sha512-OWwz05d++TxzLEv4VnsTz5CmZ6mI6S05sfQGEMrNrQcOEERbX46332IvE7pO/EUiw7jUrrS40z/M7kPyjfl04g==", + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", "cpu": [ "x64" ], @@ -883,7 +933,7 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" @@ -894,6 +944,7 @@ "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz", "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==", "license": "MIT", + "optional": true, "dependencies": { "chardet": "^2.1.1", "iconv-lite": "^0.7.0" @@ -915,6 +966,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "license": "MIT", + "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -931,6 +983,7 @@ "resolved": "https://registry.npmjs.org/@manypkg/find-root/-/find-root-1.1.0.tgz", "integrity": "sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==", "license": "MIT", + "optional": true, "dependencies": { "@babel/runtime": "^7.5.5", "@types/node": "^12.7.1", @@ -942,13 +995,15 @@ "version": "12.20.55", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/@manypkg/find-root/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "license": "MIT", + "optional": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -963,6 +1018,7 @@ "resolved": "https://registry.npmjs.org/@manypkg/get-packages/-/get-packages-1.1.3.tgz", "integrity": "sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==", "license": "MIT", + "optional": true, "dependencies": { "@babel/runtime": "^7.5.5", "@changesets/types": "^4.0.1", @@ -976,13 +1032,15 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@changesets/types/-/types-4.1.0.tgz", "integrity": "sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/@manypkg/get-packages/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "license": "MIT", + "optional": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -1047,31 +1105,12 @@ } }, "node_modules/@mermaid-js/parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.0.tgz", - "integrity": "sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==", - "license": "MIT", - "dependencies": { - "langium": "^4.0.0" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz", - "integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==", - "dev": true, + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.2.1.tgz", + "integrity": "sha512-n12NohV3mrUyUL2o93IgG/ifeW9FTyeJn3zDxkhwa8MJ9Fxg3HQMlA3RiGmD/3UnJvheztkjjQAjA2T4LmUcpw==", "license": "MIT", - "optional": true, "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" + "@chevrotain/types": "~11.1.2" } }, "node_modules/@nodelib/fs.scandir": { @@ -1079,6 +1118,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "license": "MIT", + "optional": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1092,6 +1132,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "license": "MIT", + "optional": true, "engines": { "node": ">= 8" } @@ -1101,6 +1142,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "license": "MIT", + "optional": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1110,13 +1152,13 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.124.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz", - "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==", + "version": "0.149.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.149.0.tgz", + "integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==", "dev": true, "license": "MIT", "funding": { - "url": "https://github.com/sponsors/Boshen" + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/@playwright/test": { @@ -1135,10 +1177,27 @@ "node": ">=18" } }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz", + "integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz", + "integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==", "cpu": [ "arm64" ], @@ -1153,9 +1212,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz", + "integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==", "cpu": [ "arm64" ], @@ -1170,9 +1229,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz", - "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz", + "integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==", "cpu": [ "x64" ], @@ -1187,9 +1246,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz", - "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz", + "integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==", "cpu": [ "x64" ], @@ -1204,9 +1263,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz", - "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz", + "integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==", "cpu": [ "arm" ], @@ -1221,9 +1280,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz", + "integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==", "cpu": [ "arm64" ], @@ -1238,9 +1297,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz", - "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz", + "integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==", "cpu": [ "arm64" ], @@ -1255,9 +1314,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz", + "integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==", "cpu": [ "ppc64" ], @@ -1272,9 +1331,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz", + "integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==", "cpu": [ "s390x" ], @@ -1289,9 +1348,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz", - "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz", + "integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==", "cpu": [ "x64" ], @@ -1306,9 +1365,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz", - "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz", + "integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==", "cpu": [ "x64" ], @@ -1323,9 +1382,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz", - "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz", + "integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==", "cpu": [ "arm64" ], @@ -1339,29 +1398,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz", - "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.9.2", - "@emnapi/runtime": "1.9.2", - "@napi-rs/wasm-runtime": "^1.1.3" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz", - "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz", + "integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==", "cpu": [ "arm64" ], @@ -1376,9 +1416,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz", - "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz", + "integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==", "cpu": [ "x64" ], @@ -1393,23 +1433,12 @@ } }, "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz", - "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, "license": "MIT" }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/d3": { "version": "7.4.3", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", @@ -1739,9 +1768,9 @@ } }, "node_modules/@xmldom/xmldom": { - "version": "0.9.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", - "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "version": "0.9.12", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.12.tgz", + "integrity": "sha512-5AXjrcMClTryPe9LgZrygpB1lj7s0S9E0+W+AHaVKAVyHanafK86iPSvG5xHVSp/jC+VH1UXu0TAEmY279xH7A==", "license": "MIT", "engines": { "node": ">=14.6" @@ -1764,6 +1793,7 @@ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "license": "MIT", + "optional": true, "engines": { "node": ">=6" } @@ -1773,6 +1803,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -1782,6 +1813,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", + "optional": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -1803,6 +1835,7 @@ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" @@ -1819,6 +1852,7 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -1828,6 +1862,7 @@ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "license": "MIT", + "optional": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", @@ -1849,6 +1884,7 @@ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -1858,6 +1894,7 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "license": "MIT", + "optional": true, "dependencies": { "possible-typed-array-names": "^1.0.0" }, @@ -1872,13 +1909,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/better-path-resolve": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/better-path-resolve/-/better-path-resolve-1.0.0.tgz", "integrity": "sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==", "license": "MIT", + "optional": true, "dependencies": { "is-windows": "^1.0.0" }, @@ -1891,6 +1930,7 @@ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", "license": "Unlicense", + "optional": true, "engines": { "node": ">=0.6" } @@ -1900,6 +1940,7 @@ "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", "license": "MIT", + "optional": true, "dependencies": { "buffers": "~0.1.1", "chainsaw": "~0.1.0" @@ -1912,13 +1953,15 @@ "version": "3.4.7", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "license": "MIT", + "optional": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1929,6 +1972,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "license": "MIT", + "optional": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -1941,6 +1985,7 @@ "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.10" } @@ -1949,6 +1994,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "optional": true, "engines": { "node": ">=0.2.0" } @@ -1959,6 +2005,7 @@ "integrity": "sha512-O/L2lJaojO7NjvWspBieiam7YFvWhKCYZyZUW5pmcUsBVhkrmMOYaQNdK8F3iR22bdBoW3no412DwB9RCvmemA==", "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { "@changesets/cli": "^2.27.8", "cargo-cp-artifact": "^0.1.9", @@ -1981,6 +2028,7 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -1999,6 +2047,7 @@ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -2012,6 +2061,7 @@ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "license": "MIT", + "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" @@ -2028,6 +2078,7 @@ "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.9.tgz", "integrity": "sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==", "license": "MIT", + "optional": true, "bin": { "cargo-cp-artifact": "bin/cargo-cp-artifact.js" } @@ -2037,6 +2088,7 @@ "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", "license": "MIT/X11", + "optional": true, "dependencies": { "traverse": ">=0.3.0 <0.4" }, @@ -2049,6 +2101,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "license": "MIT", + "optional": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2064,35 +2117,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.2.0.tgz", "integrity": "sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==", - "license": "MIT" - }, - "node_modules/chevrotain": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-12.0.0.tgz", - "integrity": "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==", - "license": "Apache-2.0", - "dependencies": { - "@chevrotain/cst-dts-gen": "12.0.0", - "@chevrotain/gast": "12.0.0", - "@chevrotain/regexp-to-ast": "12.0.0", - "@chevrotain/types": "12.0.0", - "@chevrotain/utils": "12.0.0" - }, - "engines": { - "node": ">=22.0.0" - } - }, - "node_modules/chevrotain-allstar": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.4.1.tgz", - "integrity": "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA==", "license": "MIT", - "dependencies": { - "lodash-es": "^4.17.21" - }, - "peerDependencies": { - "chevrotain": "^12.0.0" - } + "optional": true }, "node_modules/chokidar": { "version": "5.0.0", @@ -2114,6 +2140,7 @@ "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", "license": "MIT", + "optional": true, "dependencies": { "string-width": "^4.2.3" }, @@ -2121,24 +2148,12 @@ "node": ">=4" } }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", + "optional": true, "dependencies": { "color-name": "~1.1.4" }, @@ -2150,17 +2165,8 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } + "optional": true }, "node_modules/commander": { "version": "7.2.0", @@ -2175,7 +2181,8 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/confbox": { "version": "0.1.8", @@ -2187,7 +2194,8 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/cose-base": { "version": "1.0.3", @@ -2224,6 +2232,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "license": "MIT", + "optional": true, "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -2240,6 +2249,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "license": "ISC", + "optional": true, "bin": { "semver": "bin/semver" } @@ -2263,9 +2273,9 @@ "license": "MIT" }, "node_modules/cytoscape": { - "version": "3.33.2", - "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.2.tgz", - "integrity": "sha512-sj4HXd3DokGhzZAdjDejGvTPLqlt84vNFN8m7bGsOzDY5DyVcxIb2ejIXat2Iy7HxWhdT/N1oKyheJ5YdpsGuw==", + "version": "3.34.3", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.34.3.tgz", + "integrity": "sha512-yfYGhRcGAntq6YBD583j4n0Eg3jIxvWmZtz/5uz9UYkeIStSlMxuUja+ec5j3iBD8nv1rwaOAYMW09tBdkSeaQ==", "license": "MIT", "engines": { "node": ">=0.10" @@ -2766,6 +2776,7 @@ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -2783,6 +2794,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -2800,6 +2812,7 @@ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -2813,9 +2826,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.20", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", - "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "version": "1.11.23", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.23.tgz", + "integrity": "sha512-QDTCU0M0MxR3hQfnlDJfwekQiaanm1ubOD231u73WBckQ/fsamwRLiE2GBz6D3a/xF1NgfiDLJjXBa1hYOYTtQ==", "license": "MIT" }, "node_modules/define-data-property": { @@ -2823,6 +2836,7 @@ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "license": "MIT", + "optional": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2840,6 +2854,7 @@ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "license": "MIT", + "optional": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -2866,6 +2881,7 @@ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -2874,6 +2890,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -2884,6 +2901,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "license": "MIT", + "optional": true, "dependencies": { "path-type": "^4.0.0" }, @@ -2892,9 +2910,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.0.tgz", - "integrity": "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.15.tgz", + "integrity": "sha512-EUBjM+B+lkDE41iE82DDSCfkoPGfXx8IxFxPMjNzm/Uk4xDet77rTN9wqlxlVg71kK7XGuUMv6wUxJUwwv+Xyw==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -2905,6 +2923,7 @@ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", + "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -2919,6 +2938,7 @@ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", "license": "BSD-3-Clause", + "optional": true, "dependencies": { "readable-stream": "^2.0.2" } @@ -2927,13 +2947,15 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "license": "MIT", + "optional": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -2959,6 +2981,7 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "license": "MIT", + "optional": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -2968,6 +2991,7 @@ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", "license": "MIT", + "optional": true, "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", @@ -3036,6 +3060,7 @@ "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "es-object-atoms": "^1.1.2", @@ -3054,6 +3079,7 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -3063,6 +3089,7 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -3072,6 +3099,7 @@ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -3084,6 +3112,7 @@ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -3099,6 +3128,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", "license": "MIT", + "optional": true, "dependencies": { "es-abstract-get": "^1.0.0", "es-define-property": "^1.0.1", @@ -3114,11 +3144,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-toolkit": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.52.0.tgz", + "integrity": "sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks", + "tests/types", + "tests/browser-compat" + ] + }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.8.0" } @@ -3137,6 +3180,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "license": "BSD-2-Clause", + "optional": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -3155,13 +3199,15 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/extendable-error/-/extendable-error-0.1.7.tgz", "integrity": "sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/fast-glob": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "license": "MIT", + "optional": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3173,11 +3219,21 @@ "node": ">=8.6.0" } }, + "node_modules/fastdom": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastdom/-/fastdom-1.0.12.tgz", + "integrity": "sha512-LB+xjSTEbjHE1cWsxu+tN2Xqr1kpi+V9aADI7sVM5ZMaXyYGPHULQMzpJMYqOTULK/73pUkWVzzObFRBkPr+hg==", + "license": "MIT", + "dependencies": { + "strictdom": "^1.0.1" + } + }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "license": "ISC", + "optional": true, "dependencies": { "reusify": "^1.0.4" } @@ -3205,6 +3261,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "license": "MIT", + "optional": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3217,6 +3274,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "license": "MIT", + "optional": true, "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3230,6 +3288,7 @@ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "license": "MIT", + "optional": true, "dependencies": { "is-callable": "^1.2.7" }, @@ -3245,6 +3304,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "license": "MIT", + "optional": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -3258,7 +3318,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/fsevents": { "version": "2.3.3", @@ -3281,6 +3342,7 @@ "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "deprecated": "This package is no longer supported.", "license": "ISC", + "optional": true, "dependencies": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -3296,6 +3358,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "license": "MIT", + "optional": true, "dependencies": { "minimist": "^1.2.6" }, @@ -3308,6 +3371,7 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", + "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3317,6 +3381,7 @@ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", @@ -3340,6 +3405,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "license": "MIT", + "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3349,6 +3415,7 @@ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -3358,6 +3425,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -3382,6 +3450,7 @@ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", + "optional": true, "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -3395,6 +3464,7 @@ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -3413,6 +3483,7 @@ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "license": "ISC", + "optional": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3433,6 +3504,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "license": "ISC", + "optional": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -3445,6 +3517,7 @@ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "license": "MIT", + "optional": true, "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -3461,6 +3534,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "license": "MIT", + "optional": true, "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -3481,6 +3555,7 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3492,7 +3567,8 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/hachure-fill": { "version": "0.5.2", @@ -3505,6 +3581,7 @@ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3517,6 +3594,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -3526,6 +3604,7 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "license": "MIT", + "optional": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -3538,6 +3617,7 @@ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "license": "MIT", + "optional": true, "dependencies": { "dunder-proto": "^1.0.0" }, @@ -3553,6 +3633,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3565,6 +3646,7 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", + "optional": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -3580,6 +3662,7 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", + "optional": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -3600,13 +3683,15 @@ "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/human-id": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/human-id/-/human-id-4.2.0.tgz", "integrity": "sha512-K3GbkIWqyvvlpfhBPlbEvD97TtqBpAYA4kt+cn2lD2x2HuohzZCibcA2nOlnJT6exqvJLggoB5nv2dNf192nEA==", "license": "MIT", + "optional": true, "bin": { "human-id": "dist/cli.js" } @@ -3628,6 +3713,7 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "license": "MIT", + "optional": true, "engines": { "node": ">= 4" } @@ -3638,6 +3724,7 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "license": "ISC", + "optional": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3647,13 +3734,15 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", @@ -3677,6 +3766,7 @@ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -3693,13 +3783,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "license": "MIT", + "optional": true, "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", @@ -3719,6 +3811,7 @@ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "license": "MIT", + "optional": true, "dependencies": { "has-bigints": "^1.0.2" }, @@ -3734,6 +3827,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -3750,6 +3844,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3762,6 +3857,7 @@ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "license": "MIT", + "optional": true, "dependencies": { "hasown": "^2.0.3" }, @@ -3777,6 +3873,7 @@ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", @@ -3794,6 +3891,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" @@ -3810,6 +3908,7 @@ "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.4" }, @@ -3825,6 +3924,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -3834,6 +3934,7 @@ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3" }, @@ -3849,6 +3950,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -3858,6 +3960,7 @@ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", @@ -3877,6 +3980,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", + "optional": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -3889,6 +3993,7 @@ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3901,6 +4006,7 @@ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3913,6 +4019,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.12.0" } @@ -3922,6 +4029,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -3938,6 +4046,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", @@ -3956,6 +4065,7 @@ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -3968,6 +4078,7 @@ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3" }, @@ -3983,6 +4094,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" @@ -3999,6 +4111,7 @@ "resolved": "https://registry.npmjs.org/is-subdir/-/is-subdir-1.2.0.tgz", "integrity": "sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==", "license": "MIT", + "optional": true, "dependencies": { "better-path-resolve": "1.0.0" }, @@ -4011,6 +4124,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", @@ -4028,6 +4142,7 @@ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "license": "MIT", + "optional": true, "dependencies": { "which-typed-array": "^1.1.16" }, @@ -4043,6 +4158,7 @@ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -4055,6 +4171,7 @@ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3" }, @@ -4070,6 +4187,7 @@ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" @@ -4086,6 +4204,7 @@ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -4094,18 +4213,20 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "funding": [ { "type": "github", @@ -4137,21 +4258,23 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "license": "MIT", + "optional": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/katex": { - "version": "0.16.45", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz", - "integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==", + "version": "0.16.47", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.47.tgz", + "integrity": "sha512-Eeo8Ys1doU1z+x8AZsPpQu+p/QcZBI5PeOo7QGQdy2x2m0MU/hYagBbGOmXwr5KVbEfVuWv9LpnQWeehogurjg==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -4178,24 +4301,6 @@ "resolved": "https://registry.npmjs.org/khroma/-/khroma-2.1.0.tgz", "integrity": "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==" }, - "node_modules/langium": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/langium/-/langium-4.2.2.tgz", - "integrity": "sha512-JUshTRAfHI4/MF9dH2WupvjSXyn8JBuUEWazB8ZVJUtXutT0doDlAv1XKbZ1Pb5sMexa8FF4CFBc0iiul7gbUQ==", - "license": "MIT", - "dependencies": { - "@chevrotain/regexp-to-ast": "~12.0.0", - "chevrotain": "~12.0.0", - "chevrotain-allstar": "~0.4.1", - "vscode-languageserver": "~9.0.1", - "vscode-languageserver-textdocument": "~1.0.11", - "vscode-uri": "~3.1.0" - }, - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" - } - }, "node_modules/layout-base": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz", @@ -4203,9 +4308,9 @@ "license": "MIT" }, "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -4219,23 +4324,23 @@ "url": "https://opencollective.com/parcel" }, "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" + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", "cpu": [ "arm64" ], @@ -4254,9 +4359,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", "cpu": [ "arm64" ], @@ -4275,9 +4380,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", "cpu": [ "x64" ], @@ -4296,9 +4401,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", "cpu": [ "x64" ], @@ -4317,9 +4422,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", "cpu": [ "arm" ], @@ -4338,9 +4443,9 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", "cpu": [ "arm64" ], @@ -4359,9 +4464,9 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", "cpu": [ "arm64" ], @@ -4380,9 +4485,9 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", "cpu": [ "x64" ], @@ -4401,9 +4506,9 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", "cpu": [ "x64" ], @@ -4422,9 +4527,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", "cpu": [ "arm64" ], @@ -4443,9 +4548,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", "cpu": [ "x64" ], @@ -4464,9 +4569,19 @@ } }, "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" @@ -4476,13 +4591,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "license": "MIT", + "optional": true, "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^4.0.0", @@ -4498,6 +4615,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "license": "MIT", + "optional": true, "dependencies": { "p-locate": "^4.1.0" }, @@ -4521,7 +4639,8 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/luxon": { "version": "3.7.2", @@ -4533,14 +4652,24 @@ } }, "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "version": "14.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.2.tgz", + "integrity": "sha512-sHHjZ5fJKlgrG4qns2YwVcdNep35h5fERrfkD2YNsb9UFk0UIHarbiTaHKVMlPuWAoiilyK8Fv/jAm11slsY7Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -4642,6 +4771,7 @@ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -4669,6 +4799,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "optional": true, "engines": { "node": ">= 0.10.0" } @@ -4678,37 +4809,39 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 8" } }, "node_modules/mermaid": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.14.0.tgz", - "integrity": "sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g==", + "version": "11.17.2", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.17.2.tgz", + "integrity": "sha512-V6K3C8EBdEsPFZXSKMJe6ppQOENxuHARr9GvHX4hh47lAbhMRD9qf4oEK7LoaRQxULMa80/qt5gHO73aCleBBg==", "license": "MIT", "dependencies": { - "@braintree/sanitize-url": "^7.1.1", + "@braintree/sanitize-url": "^7.1.2", "@iconify/utils": "^3.0.2", - "@mermaid-js/parser": "^1.1.0", + "@mermaid-js/parser": "^1.2.1", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", - "cytoscape": "^3.33.1", + "cytoscape": "^3.34.0", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", - "dayjs": "^1.11.19", - "dompurify": "^3.3.1", - "katex": "^0.16.25", + "dayjs": "^1.11.21", + "dompurify": "^3.3.3", + "es-toolkit": "^1.45.1", + "fastdom": "1.0.12", + "katex": "^0.16.47", "khroma": "^2.1.0", - "lodash-es": "^4.17.23", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", - "uuid": "^11.1.0" + "uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0" } }, "node_modules/mhchemparser": { @@ -4722,6 +4855,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "license": "MIT", + "optional": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -4735,6 +4869,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", + "optional": true, "engines": { "node": ">=8.6" }, @@ -4747,6 +4882,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "license": "ISC", + "optional": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -4759,6 +4895,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "license": "MIT", + "optional": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4774,6 +4911,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "license": "MIT", + "optional": true, "bin": { "mkdirp": "dist/cjs/src/bin.js" }, @@ -4807,14 +4945,15 @@ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "license": "MIT", + "optional": true, "engines": { "node": ">=4" } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", "funding": [ { "type": "github", @@ -4833,13 +4972,15 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", + "optional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -4860,6 +5001,7 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "license": "BSD-2-Clause", + "optional": true, "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -4872,6 +5014,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "license": "ISC", + "optional": true, "bin": { "semver": "bin/semver" } @@ -4881,6 +5024,7 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "license": "MIT", + "optional": true, "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", @@ -4906,6 +5050,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "license": "MIT", + "optional": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -4918,6 +5063,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "license": "MIT", + "optional": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4932,6 +5078,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "license": "MIT", + "optional": true, "dependencies": { "color-name": "1.1.3" } @@ -4940,13 +5087,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/npm-run-all/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "license": "MIT", + "optional": true, "engines": { "node": ">=4" } @@ -4956,6 +5105,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "license": "MIT", + "optional": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -4968,6 +5118,7 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -4980,6 +5131,7 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -4989,6 +5141,7 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", @@ -5009,6 +5162,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "license": "ISC", + "optional": true, "dependencies": { "wrappy": "1" } @@ -5017,13 +5171,15 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/outdent/-/outdent-0.5.0.tgz", "integrity": "sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/own-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", "license": "MIT", + "optional": true, "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", @@ -5041,6 +5197,7 @@ "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", "license": "MIT", + "optional": true, "dependencies": { "p-map": "^2.0.0" }, @@ -5053,6 +5210,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "license": "MIT", + "optional": true, "dependencies": { "p-try": "^2.0.0" }, @@ -5068,6 +5226,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "license": "MIT", + "optional": true, "dependencies": { "p-limit": "^2.2.0" }, @@ -5080,6 +5239,7 @@ "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", "license": "MIT", + "optional": true, "engines": { "node": ">=6" } @@ -5089,6 +5249,7 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=6" } @@ -5110,6 +5271,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "license": "MIT", + "optional": true, "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" @@ -5129,6 +5291,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -5138,6 +5301,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -5147,6 +5311,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "license": "MIT", + "optional": true, "engines": { "node": ">=4" } @@ -5155,13 +5320,15 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -5179,9 +5346,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", "engines": { @@ -5196,6 +5363,7 @@ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "license": "MIT", + "optional": true, "bin": { "pidtree": "bin/pidtree.js" }, @@ -5208,6 +5376,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "license": "MIT", + "optional": true, "engines": { "node": ">=4" } @@ -5217,6 +5386,7 @@ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", "license": "MIT", + "optional": true, "dependencies": { "find-up": "^5.0.0" }, @@ -5229,6 +5399,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "license": "MIT", + "optional": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -5245,6 +5416,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "license": "MIT", + "optional": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -5260,6 +5432,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "license": "MIT", + "optional": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -5275,6 +5448,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "license": "MIT", + "optional": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -5364,14 +5538,15 @@ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.5.9", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", - "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", "funding": [ { "type": "opencollective", @@ -5388,7 +5563,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.18", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5441,6 +5616,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "license": "MIT", + "optional": true, "bin": { "prettier": "bin-prettier.js" }, @@ -5456,6 +5632,7 @@ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "license": "MIT", + "optional": true, "engines": { "node": ">=6" }, @@ -5467,7 +5644,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/punycode.js": { "version": "2.3.1", @@ -5492,7 +5670,8 @@ "url": "https://github.com/sponsors/sxzz" } ], - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -5512,13 +5691,15 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "license": "MIT", + "optional": true, "dependencies": { "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", @@ -5533,6 +5714,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "license": "MIT", + "optional": true, "dependencies": { "pify": "^3.0.0" }, @@ -5545,6 +5727,7 @@ "resolved": "https://registry.npmjs.org/read-yaml-file/-/read-yaml-file-1.1.0.tgz", "integrity": "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==", "license": "MIT", + "optional": true, "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", @@ -5560,15 +5743,17 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "license": "MIT", + "optional": true, "dependencies": { "sprintf-js": "~1.0.2" } }, "node_modules/read-yaml-file/node_modules/js-yaml": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.0.tgz", - "integrity": "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", + "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", "license": "MIT", + "optional": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -5582,6 +5767,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "license": "MIT", + "optional": true, "engines": { "node": ">=6" } @@ -5591,6 +5777,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", + "optional": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5605,7 +5792,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/readdirp": { "version": "5.0.0", @@ -5625,6 +5813,7 @@ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -5647,6 +5836,7 @@ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", @@ -5667,6 +5857,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", @@ -5688,6 +5879,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -5697,6 +5889,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "license": "MIT", + "optional": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -5708,6 +5901,7 @@ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "license": "ISC", + "optional": true, "dependencies": { "glob": "^7.1.3" }, @@ -5722,14 +5916,14 @@ "license": "Unlicense" }, "node_modules/rolldown": { - "version": "1.0.0-rc.15", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz", - "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.8.tgz", + "integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.124.0", - "@rolldown/pluginutils": "1.0.0-rc.15" + "@oxc-project/types": "=0.149.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { "rolldown": "bin/cli.mjs" @@ -5738,21 +5932,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.15", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.15", - "@rolldown/binding-darwin-x64": "1.0.0-rc.15", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.15", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15" + "@rolldown/binding-android-arm-eabi": "1.2.8", + "@rolldown/binding-android-arm64": "1.2.8", + "@rolldown/binding-darwin-arm64": "1.2.8", + "@rolldown/binding-darwin-x64": "1.2.8", + "@rolldown/binding-freebsd-x64": "1.2.8", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", + "@rolldown/binding-linux-arm64-gnu": "1.2.8", + "@rolldown/binding-linux-arm64-musl": "1.2.8", + "@rolldown/binding-linux-ppc64-gnu": "1.2.8", + "@rolldown/binding-linux-s390x-gnu": "1.2.8", + "@rolldown/binding-linux-x64-gnu": "1.2.8", + "@rolldown/binding-linux-x64-musl": "1.2.8", + "@rolldown/binding-openharmony-arm64": "1.2.8", + "@rolldown/binding-win32-arm64-msvc": "1.2.8", + "@rolldown/binding-win32-x64-msvc": "1.2.8" } }, "node_modules/roughjs": { @@ -5786,6 +5980,7 @@ } ], "license": "MIT", + "optional": true, "dependencies": { "queue-microtask": "^1.2.2" } @@ -5801,6 +5996,7 @@ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", @@ -5819,13 +6015,15 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" @@ -5842,6 +6040,7 @@ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5865,6 +6064,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", "license": "ISC", + "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -5877,6 +6077,7 @@ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "license": "MIT", + "optional": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -5894,6 +6095,7 @@ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "license": "MIT", + "optional": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -5909,6 +6111,7 @@ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "license": "MIT", + "optional": true, "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", @@ -5922,48 +6125,57 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/sharp": { - "version": "0.34.3", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.3.tgz", - "integrity": "sha512-eX2IQ6nFohW4DbvHIOLRB3MHFpYqaqvXd3Tp5e/T/dSH83fxaNJQRvDMhASmkNTsNTVF2/OOopzRCt7xokgPfg==", - "hasInstallScript": true, + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", "license": "Apache-2.0", + "optional": true, "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.4", - "semver": "^7.7.2" + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.3", - "@img/sharp-darwin-x64": "0.34.3", - "@img/sharp-libvips-darwin-arm64": "1.2.0", - "@img/sharp-libvips-darwin-x64": "1.2.0", - "@img/sharp-libvips-linux-arm": "1.2.0", - "@img/sharp-libvips-linux-arm64": "1.2.0", - "@img/sharp-libvips-linux-ppc64": "1.2.0", - "@img/sharp-libvips-linux-s390x": "1.2.0", - "@img/sharp-libvips-linux-x64": "1.2.0", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.0", - "@img/sharp-libvips-linuxmusl-x64": "1.2.0", - "@img/sharp-linux-arm": "0.34.3", - "@img/sharp-linux-arm64": "0.34.3", - "@img/sharp-linux-ppc64": "0.34.3", - "@img/sharp-linux-s390x": "0.34.3", - "@img/sharp-linux-x64": "0.34.3", - "@img/sharp-linuxmusl-arm64": "0.34.3", - "@img/sharp-linuxmusl-x64": "0.34.3", - "@img/sharp-wasm32": "0.34.3", - "@img/sharp-win32-arm64": "0.34.3", - "@img/sharp-win32-ia32": "0.34.3", - "@img/sharp-win32-x64": "0.34.3" + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/shebang-command": { @@ -5971,6 +6183,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "license": "MIT", + "optional": true, "dependencies": { "shebang-regex": "^1.0.0" }, @@ -5983,6 +6196,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.10.0" } @@ -5992,6 +6206,7 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.9.0.tgz", "integrity": "sha512-Iov+JwFv/2HcTpcwNMKd8+IWNb8tboQJNQTkAY/LLVK7gGH9jy+LGkVqPxfekHl+yMmiqXszdGWXgkfml7hjqA==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -6004,6 +6219,7 @@ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", @@ -6023,6 +6239,7 @@ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" @@ -6039,6 +6256,7 @@ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -6057,6 +6275,7 @@ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -6076,6 +6295,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "license": "ISC", + "optional": true, "engines": { "node": ">=14" }, @@ -6083,26 +6303,12 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "license": "MIT" - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -6121,6 +6327,7 @@ "resolved": "https://registry.npmjs.org/spawndamnit/-/spawndamnit-3.0.1.tgz", "integrity": "sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==", "license": "SEE LICENSE IN LICENSE", + "optional": true, "dependencies": { "cross-spawn": "^7.0.5", "signal-exit": "^4.0.1" @@ -6131,6 +6338,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", + "optional": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -6145,6 +6353,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -6154,6 +6363,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "license": "MIT", + "optional": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -6166,6 +6376,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -6175,6 +6386,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "license": "ISC", + "optional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6190,6 +6402,7 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "license": "Apache-2.0", + "optional": true, "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -6199,13 +6412,15 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "license": "CC-BY-3.0" + "license": "CC-BY-3.0", + "optional": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "license": "MIT", + "optional": true, "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -6215,7 +6430,8 @@ "version": "3.0.23", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", - "license": "CC0-1.0" + "license": "CC0-1.0", + "optional": true }, "node_modules/speech-rule-engine": { "version": "4.1.4", @@ -6244,13 +6460,15 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "optional": true }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" @@ -6259,11 +6477,18 @@ "node": ">= 0.4" } }, + "node_modules/strictdom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strictdom/-/strictdom-1.0.1.tgz", + "integrity": "sha512-cEmp9QeXXRmjj/rVp9oyiqcvyocWab/HaoN4+bwFeZ7QzykJD6L3yD4v12K1x0tHpqRqVpJevN3gW7kyM39Bqg==", + "license": "MIT" + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "license": "MIT", + "optional": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -6273,6 +6498,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "license": "MIT", + "optional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6287,6 +6513,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -6305,6 +6532,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", @@ -6327,6 +6555,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", @@ -6345,6 +6574,7 @@ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", @@ -6362,6 +6592,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", + "optional": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6374,6 +6605,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "license": "MIT", + "optional": true, "engines": { "node": ">=4" } @@ -6389,6 +6621,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "license": "MIT", + "optional": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6401,6 +6634,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -6413,6 +6647,7 @@ "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", "license": "MIT", + "optional": true, "engines": { "node": ">=8" }, @@ -6430,9 +6665,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -6451,6 +6686,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "license": "MIT", + "optional": true, "dependencies": { "is-number": "^7.0.0" }, @@ -6462,13 +6698,15 @@ "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/traverse": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", "license": "MIT/X11", + "optional": true, "engines": { "node": "*" } @@ -6494,6 +6732,7 @@ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", @@ -6508,6 +6747,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", @@ -6527,6 +6767,7 @@ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "license": "MIT", + "optional": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", @@ -6548,6 +6789,7 @@ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", "license": "MIT", + "optional": true, "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", @@ -6594,6 +6836,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", @@ -6619,6 +6862,7 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 4.0.0" } @@ -6628,6 +6872,7 @@ "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", "license": "MIT", + "optional": true, "dependencies": { "big-integer": "^1.6.17", "binary": "~0.3.0", @@ -6648,16 +6893,16 @@ "license": "MIT" }, "node_modules/uuid": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", - "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.2.tgz", + "integrity": "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/esm/bin/uuid" + "uuid": "dist-node/bin/uuid" } }, "node_modules/validate-npm-package-license": { @@ -6665,23 +6910,24 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "license": "Apache-2.0", + "optional": true, "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "node_modules/vite": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz", - "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.0.tgz", + "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==", "dev": true, "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.8", - "rolldown": "1.0.0-rc.15", - "tinyglobby": "^0.2.15" + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.28", + "rolldown": "~1.2.6", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" @@ -6697,7 +6943,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.0", + "@vitejs/devtools": "^0.7.1", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -6748,66 +6994,19 @@ } } }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", - "license": "MIT" - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "optional": true }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", + "optional": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -6818,6 +7017,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "license": "ISC", + "optional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6830,6 +7030,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "license": "MIT", + "optional": true, "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", @@ -6849,6 +7050,7 @@ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "license": "MIT", + "optional": true, "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", @@ -6876,6 +7078,7 @@ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "license": "MIT", + "optional": true, "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", @@ -6894,6 +7097,7 @@ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", "license": "MIT", + "optional": true, "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", @@ -6920,7 +7124,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" + "license": "ISC", + "optional": true }, "node_modules/xss": { "version": "1.0.15", @@ -6964,6 +7169,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "license": "MIT", + "optional": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 733111e..e4d8cd6 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,8 @@ "dist/", "lib/", "server.mjs", - "package.json" + "package.json", + "npm-shrinkwrap.json" ], "scripts": { "dev": "vite", @@ -31,7 +32,8 @@ "prepare": "npm run build", "prepublishOnly": "npm run build", "test:e2e": "npx playwright test", - "check:contrast": "node scripts/check-contrast.mjs" + "check:contrast": "node scripts/check-contrast.mjs", + "test:unit": "node --test tests/*.test.mjs" }, "keywords": [ "markdown", @@ -51,20 +53,19 @@ "@types/markdown-it": "^14.1.2", "@types/papaparse": "^5.5.2", "typescript": "~6.0.2", - "vite": "^8.0.4" + "vite": "^8.3.0" }, "dependencies": { "@marp-team/marp-core": "^4.3.0", - "c2pa-node": "^0.5.26", "chokidar": "^5.0.0", "cron-parser": "^5.5.0", "cronstrue": "^3.14.0", - "dompurify": "^3.3.3", + "dompurify": "^3.4.15", "exifr": "^7.1.3", "highlight.js": "^11.11.1", "jschardet": "^3.1.4", "katex": "^0.16.45", - "markdown-it": "^14.1.1", + "markdown-it": "^14.3.2", "markdown-it-anchor": "^9.2.0", "markdown-it-container": "^4.0.0", "markdown-it-deflist": "^3.0.0", @@ -76,10 +77,21 @@ "markdown-it-sub": "^2.0.0", "markdown-it-sup": "^2.0.0", "markdown-it-texmath": "^1.0.0", - "mermaid": "^11.14.0", + "mermaid": "^11.17.2", "modern-screenshot": "^4.6.8", "papaparse": "^5.5.3", "yaml": "^2.8.3" }, - "packageManager": "pnpm@11.1.1+sha512.d1fdf5f73c617b64fa1a56a81c3c8dfe0e966e33a6010aa256b517ae77be21d93e05affc0de1a83b0e4f29d569f68b446ae8f068cd7247c0bb3df0fb4d7bdf9a" + "packageManager": "npm@11.9.0", + "optionalDependencies": { + "c2pa-node": "^0.5.26" + }, + "overrides": { + "c2pa-node": { + "sharp": "^0.35.4" + }, + "speech-rule-engine": { + "@xmldom/xmldom": "^0.9.12" + } + } } diff --git a/playwright.config.ts b/playwright.config.ts index fad7a97..21b55cf 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -6,6 +6,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); export default defineConfig({ testDir: './tests', + testMatch: '**/*.spec.ts', timeout: 30000, globalSetup: './tests/setup.ts', use: { diff --git a/scripts/check-contrast.mjs b/scripts/check-contrast.mjs index 51c28cf..c355918 100644 --- a/scripts/check-contrast.mjs +++ b/scripts/check-contrast.mjs @@ -18,8 +18,13 @@ import { dirname, join } from 'node:path'; const __dirname = dirname(fileURLToPath(import.meta.url)); const CSS_PATH = join(__dirname, '..', 'src', 'style.css'); -function hexToRgb(hex) { - let h = hex.replace('#', ''); +function colorToRgb(color, background = [255, 255, 255]) { + const rgba = color.match(/^rgba?\(([^)]+)\)$/); + if (rgba) { + const [r, g, b, alpha = 1] = rgba[1].split(',').map(Number); + return [r, g, b].map((channel, i) => channel * alpha + background[i] * (1 - alpha)); + } + let h = color.replace('#', ''); if (h.length === 3) h = h.split('').map((c) => c + c).join(''); return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)]; } @@ -33,8 +38,9 @@ function relativeLuminance([r, g, b]) { } function contrast(fg, bg) { - const lf = relativeLuminance(hexToRgb(fg)); - const lb = relativeLuminance(hexToRgb(bg)); + const background = colorToRgb(bg); + const lf = relativeLuminance(colorToRgb(fg, background)); + const lb = relativeLuminance(background); const [hi, lo] = lf > lb ? [lf, lb] : [lb, lf]; return (hi + 0.05) / (lo + 0.05); } @@ -48,7 +54,7 @@ function parseThemes(css) { const name = m[1]; const body = m[2]; themes[name] = themes[name] || {}; - const varRe = /--([\w-]+)\s*:\s*(#[0-9a-fA-F]{3,6})\s*;/g; + const varRe = /--([\w-]+)\s*:\s*(#[0-9a-fA-F]{3,6}|rgba?\([^;)]+\))\s*;/g; let v; while ((v = varRe.exec(body)) !== null) { themes[name][v[1]] = v[2]; @@ -60,7 +66,7 @@ function parseThemes(css) { const name = m[1]; const body = m[2]; themes[name] = themes[name] || {}; - const varRe = /--([\w-]+)\s*:\s*(#[0-9a-fA-F]{3,6})\s*;/g; + const varRe = /--([\w-]+)\s*:\s*(#[0-9a-fA-F]{3,6}|rgba?\([^;)]+\))\s*;/g; let v; while ((v = varRe.exec(body)) !== null) { themes[name][v[1]] = v[2]; diff --git a/server.mjs b/server.mjs index ed5ae48..a2ca617 100644 --- a/server.mjs +++ b/server.mjs @@ -9,6 +9,8 @@ import { Readable } from 'node:stream'; import { isIP } from 'node:net'; import chokidar from 'chokidar'; import jschardet from 'jschardet'; +import Papa from 'papaparse'; +import { createRegexSearch } from './lib/server-regex.mjs'; import { parseDimensions, buildDimensions, parsePngTextChunksFromFile, extractExif, extractPngColorInfo, detectAiProvenance, @@ -257,7 +259,7 @@ for (let i = 0; i < args.length; i++) { )); } const parsedSize = Number(raw); - if (parsedSize < 1) { + if (!Number.isSafeInteger(parsedSize) || parsedSize < 1) { reportAndExit(Object.assign( new Error(`--remote-max-size の値が範囲外です: "${raw}" (1 以上のバイト数を指定してください)`), { code: 'EINVALIDREMOTESIZE' }, @@ -321,7 +323,7 @@ function compileIgnorePattern(pattern) { const body = pattern.replace(/^\/+|\/+$/g, ''); const rx = body .replace(/[.+^${}()|[\]\\]/g, '\\$&') - .replace(/\*+/g, (m) => (m.length >= 2 ? '.*' : '[^/]*')); + .replace(/\*+|\?/g, (m) => (m === '?' ? '[^/]' : m.length >= 2 ? '.*' : '[^/]*')); return { hasSlash, re: new RegExp('^' + rx + '$') }; } @@ -427,21 +429,81 @@ const SEARCH_CONTEXT_LINES = 20; // files are skipped so a huge fixture can't block the event loop (see searchDir). const MAX_SEARCH_FILE_BYTES = 10 * 1024 * 1024; // 10 MB const REDACTED = '[REDACTED]'; -const SECRET_KEY_VALUE_RE = - /(["']?)(password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key|client[_-]?secret|authorization|auth[_-]?token|cookie|session)(\1\s*[:=]\s*)(["']?)([^"',\s}\]]{3,}|[^"',\n}\]]{8,})(\4)/gi; -const BEARER_SECRET_RE = /\b(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi; -const JWT_SECRET_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g; +const SECRET_KEY_RE = + /(?:^|[_\-\s.])(password|passwd|pwd|secret|token|api[_-]?key|access[_-]?key|private[_-]?key|client[_-]?secret|authorization|auth[_-]?token|bearer|cookie|session)(?:$|[_\-\s.])/i; + +// Match keys separately so quoted and structured values can be consumed whole. +const KEY_VALUE_RE = /(["']?)([A-Za-z_][A-Za-z0-9_.-]*)(\1[ \t]*[:=][ \t]*)/g; + +const BEARER_RE = /\b(Bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi; +const JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g; const HEX_SECRET_RE = /\b[a-f0-9]{32,}\b/gi; -const TOKENISH_SECRET_RE = /\b(?=[A-Za-z0-9._~+/=-]{28,}\b)(?=[A-Za-z0-9._~+/=-]*[A-Za-z])(?=[A-Za-z0-9._~+/=-]*\d)[A-Za-z0-9._~+/=-]+\b/g; +const TOKENISH_RE = /\b(?=[A-Za-z0-9._~+/=-]{28,}\b)(?=[A-Za-z0-9._~+/=-]*[A-Za-z])(?=[A-Za-z0-9._~+/=-]*\d)[A-Za-z0-9._~+/=-]+\b/g; + + +function isLikelySecretKey(key) { + if (typeof key !== 'string') return false; + const normalized = key.replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2').replace(/([a-z0-9])([A-Z])/g, '$1_$2'); + return SECRET_KEY_RE.test(normalized); +} + + +/** Redact the entire assigned value, including spaces, escapes and containers. */ +function maskKeyValues(text) { + const re = new RegExp(KEY_VALUE_RE.source, 'g'); + let out = ''; + let last = 0; + let match; + while ((match = re.exec(text)) !== null) { + if (!isLikelySecretKey(match[2])) continue; + const start = re.lastIndex; + const first = text[start]; + if (first === undefined || /[\r\n]/.test(first)) continue; + let end = start; + let quote = ''; + const stack = []; + if (first === '"' || first === "'") quote = first; + if (quote) { + end++; + while (end < text.length) { + if (text[end] === '\\') { end += 2; continue; } + if (text[end++] === quote) break; + } + } else if (first === '{' || first === '[') { + for (; end < text.length; end++) { + const ch = text[end]; + if (quote) { + if (ch === '\\') { end++; continue; } + if (ch === quote) quote = ''; + } else if (ch === '"' || ch === "'") quote = ch; + else if (ch === '{' || ch === '[') stack.push(ch); + else if (ch === '}' || ch === ']') { + stack.pop(); + if (!stack.length) { end++; break; } + } + } + } else if (!match[1] && /(?:authorization|cookie)$/i.test(match[2])) { + // Header values include schemes and multiple cookies separated by spaces. + while (end < text.length && !/[\r\n]/.test(text[end])) end++; + } else { + while (end < text.length && !/[\s,;&}\]"']/.test(text[end])) end++; + } + if (end === start) continue; + const valueQuote = first === '"' || first === "'" ? first : ''; + out += text.slice(last, start) + valueQuote + REDACTED + valueQuote; + last = end; + re.lastIndex = end; + } + return out + text.slice(last); +} function maskSecrets(text) { if (!text) return text; - return text - .replace(SECRET_KEY_VALUE_RE, (_match, keyQuote, key, sep, valueQuote, _value, closeQuote) => `${keyQuote}${key}${sep}${valueQuote}${REDACTED}${closeQuote}`) - .replace(BEARER_SECRET_RE, (_match, prefix) => `${prefix}${REDACTED}`) - .replace(JWT_SECRET_RE, REDACTED) + return maskKeyValues(text) + .replace(BEARER_RE, (_match, prefix) => `${prefix}${REDACTED}`) + .replace(JWT_RE, REDACTED) .replace(HEX_SECRET_RE, REDACTED) - .replace(TOKENISH_SECRET_RE, (match) => { + .replace(TOKENISH_RE, (match) => { if (!/[A-Z]/.test(match) && !/[+/=_-]/.test(match)) return match; return REDACTED; }); @@ -483,12 +545,17 @@ function isPrivateIPv4(ip) { } function isPrivateIPv6(ip) { - const lower = ip.toLowerCase(); - // Normalize IPv6 like ::ffff:127.0.0.1 to IPv4 form - const v4Mapped = lower.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/); - if (v4Mapped) return isPrivateIPv4(v4Mapped[1]); + // WHATWG URLs normalize expanded and dotted IPv6 spellings alike. Mapped + // IPv4 addresses become hexadecimal (::ffff:7f00:1), not dotted decimal. + const lower = new URL(`http://[${ip}]/`).hostname.slice(1, -1); + const v4Mapped = lower.match(/^::ffff:([\da-f]+):([\da-f]+)$/); + if (v4Mapped) { + const high = parseInt(v4Mapped[1], 16); + const low = parseInt(v4Mapped[2], 16); + return isPrivateIPv4(`${high >>> 8}.${high & 255}.${low >>> 8}.${low & 255}`); + } if (lower === '::1' || lower === '::') return true; - if (lower.startsWith('fe80:') || lower.startsWith('fe80')) return true; // link-local + if ((parseInt(lower.split(':')[0], 16) & 0xffc0) === 0xfe80) return true; // link-local fe80::/10 if (lower.startsWith('fc') || lower.startsWith('fd')) return true; // ULA if (lower.startsWith('ff')) return true; // multicast return false; @@ -537,7 +604,8 @@ async function fetchRemoteUrl(rawUrl, config, hopsLeft = 3) { let address, family; try { const { lookup } = await import('node:dns/promises'); - const result = await lookup(urlObj.hostname, { verbatim: true }); + const hostname = urlObj.hostname.replace(/^\[|\]$/g, ''); + const result = await lookup(hostname, { verbatim: true }); address = result?.address; family = result?.family; } catch (err) { @@ -566,12 +634,11 @@ async function fetchRemoteUrl(rawUrl, config, hopsLeft = 3) { // routing intact, and servername drives TLS SNI. const port = urlObj.port || (urlObj.protocol === 'https:' ? 443 : 80); const hostHeader = urlObj.port ? `${urlObj.hostname}:${urlObj.port}` : urlObj.hostname; - const connectHost = numericFamily === 6 ? `[${address}]` : address; return new Promise((resolve) => { const reqOptions = { method: 'GET', - host: connectHost, + host: address, path: urlObj.pathname + urlObj.search, port, headers: { @@ -582,7 +649,7 @@ async function fetchRemoteUrl(rawUrl, config, hopsLeft = 3) { 'Accept-Encoding': 'identity', }, timeout: timeoutMs, - servername: urlObj.hostname, // TLS SNI + servername: isIP(urlObj.hostname.replace(/^\[|\]$/g, '')) ? '' : urlObj.hostname, // TLS SNI is for DNS names }; if (urlObj.protocol === 'https:' && insecureTls) { // User opted into skipping cert verification — common when operating @@ -839,17 +906,22 @@ function parseRange(header, total) { } async function readJsonRequestBody(req, maxBytes = 16 * 1024) { - let body = ''; - for await (const chunk of req) { - body += chunk; - if (body.length > maxBytes) { + const chunks = []; + let bytes = 0; + for await (const chunk of req.iterator({ destroyOnReturn: false })) { + bytes += chunk.length; + if (bytes > maxBytes) { + req.resume(); const err = new Error('Request body too large'); err.status = 413; throw err; } + chunks.push(chunk); } try { - return JSON.parse(body || '{}'); + // A UTF-8 character may cross TCP chunks. Decode only after joining the + // bytes; converting each chunk separately corrupts non-ASCII filenames. + return JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}'); } catch { const err = new Error('Invalid JSON'); err.status = 400; @@ -864,7 +936,7 @@ function getOpenCommand(filePath) { return null; } -function launchDefaultApp(filePath) { +async function launchDefaultApp(filePath) { const spec = getOpenCommand(filePath); if (!spec) { const err = new Error(`Opening files is not supported on ${process.platform}`); @@ -876,6 +948,12 @@ function launchDefaultApp(filePath) { stdio: 'ignore', windowsHide: true, }); + // Spawn failures (for example a missing xdg-open) are asynchronous. Handle + // them before reporting success instead of crashing the HTTP server later. + await new Promise((resolve, reject) => { + child.once('error', reject); + child.once('spawn', resolve); + }); child.unref(); return spec; } @@ -996,6 +1074,7 @@ async function buildTree(dir, base = dir) { for (const entry of entries) { const fullPath = join(dir, entry.name); const relPath = relative(base, fullPath).replace(/\\/g, '/'); + if (entry.isSymbolicLink() && !await safePath(relPath)) continue; if (entry.isDirectory()) { if (isSupportedFilename(entry.name) && OFFICE_EXTENSIONS.has(extname(entry.name).toLowerCase())) { @@ -1125,6 +1204,42 @@ async function readLineRange(filePath, offset, limit) { }); } +/** + * Paginate delimited files by complete records. Physical newlines can occur + * inside quoted fields, so the CSV table explicitly opts into this mode. + */ +async function readCsvRecords(filePath, offset, limit, query = null) { + const delimiter = extname(filePath).toLowerCase() === '.tsv' ? '\t' : ''; + const input = await createTextReadStream(filePath); + const lowerQuery = query?.toLowerCase(); + return new Promise((resolve, reject) => { + const lines = []; + const matches = []; + let totalLines = 0; + let totalMatches = 0; + let headerLine = null; + Papa.parse(input, { + delimiter, + skipEmptyLines: true, + step({ data, meta }) { + const text = Papa.unparse([data], { delimiter: meta.delimiter, newline: '\n' }); + if (totalLines === 0) headerLine = text; + if (lowerQuery !== null && lowerQuery !== undefined) { + if (totalLines > 0 && text.toLowerCase().includes(lowerQuery)) { + if (totalMatches >= offset && matches.length < limit) matches.push({ lineNum: totalLines, text }); + totalMatches++; + } + } else if (totalLines >= offset && lines.length < limit) { + lines.push(text); + } + totalLines++; + }, + complete: () => resolve({ lines, matches, totalLines, totalMatches, headerLine }), + error: reject, + }); + }); +} + /** * Estimate total line count. For small files (< 1 MB) count exactly. * For larger files, sample the first 8 KB and extrapolate. @@ -1171,6 +1286,7 @@ async function estimateLineCount(filePath, fileSize) { */ async function searchFileLines(filePath, query, offset, limit) { const lowerQuery = query.toLowerCase(); + const hasHeader = ['.csv', '.tsv'].includes(extname(filePath).toLowerCase()); const inputStream = await createTextReadStream(filePath); return new Promise((resolve, reject) => { const matches = []; @@ -1189,7 +1305,7 @@ async function searchFileLines(filePath, query, offset, limit) { headerLine = line; } - if (line.toLowerCase().includes(lowerQuery)) { + if ((!hasHeader || lineNum > 0) && line.toLowerCase().includes(lowerQuery)) { if (totalMatches >= offset && matches.length < limit) { matches.push({ lineNum, text: line }); } @@ -1415,7 +1531,14 @@ const server = createServer(async (req, res) => { } if (url.pathname.startsWith('/api/raw/')) { - const rawPath = decodeURIComponent(url.pathname.slice('/api/raw/'.length)); + let rawPath; + try { + rawPath = decodeURIComponent(url.pathname.slice('/api/raw/'.length)); + } catch { + res.writeHead(400, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: 'Invalid path encoding' })); + return; + } await serveRawFile(req, res, rawPath); return; } @@ -1480,7 +1603,10 @@ const server = createServer(async (req, res) => { // Streaming line-range read — never loads the full file into memory const offset = Math.max(0, parseInt(offsetParam || '0', 10) || 0); const limit = Math.max(1, parseInt(limitParam || '1000', 10) || 1000); - const { lines, totalLines } = await readLineRange(resolved, offset, limit); + const records = url.searchParams.get('records') === '1' && ['.csv', '.tsv'].includes(ext); + const { lines, totalLines } = records + ? await readCsvRecords(resolved, offset, limit) + : await readLineRange(resolved, offset, limit); const headers = { 'Content-Type': 'text/plain; charset=utf-8', @@ -1529,7 +1655,10 @@ const server = createServer(async (req, res) => { try { const offset = Math.max(0, parseInt(url.searchParams.get('offset') || '0', 10) || 0); const limit = Math.max(1, parseInt(url.searchParams.get('limit') || '1000', 10) || 1000); - const { matches, totalMatches, totalLines, headerLine } = await searchFileLines(resolved, query, offset, limit); + const records = url.searchParams.get('records') === '1' && ['.csv', '.tsv'].includes(ext); + const { matches, totalMatches, totalLines, headerLine } = records + ? await readCsvRecords(resolved, offset, limit, query) + : await searchFileLines(resolved, query, offset, limit); const body = JSON.stringify({ matches, totalMatches, totalLines, headerLine }); res.writeHead(200, { @@ -1663,7 +1792,7 @@ const server = createServer(async (req, res) => { return; } - if (!data?.dryRun) launchDefaultApp(resolved); + if (!data?.dryRun) await launchDefaultApp(resolved); res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ ok: true, @@ -1719,7 +1848,7 @@ const server = createServer(async (req, res) => { return; } - if (!data?.dryRun) launchDefaultApp(resolved); + if (!data?.dryRun) await launchDefaultApp(resolved); res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify({ ok: true, @@ -1776,6 +1905,7 @@ const server = createServer(async (req, res) => { const lowerQuery = query.toLowerCase(); matcher = { test: (s) => s.toLowerCase().includes(lowerQuery) }; } + const regexSearch = useRegex ? createRegexSearch(query) : null; async function searchDir(dir) { if (results.length >= 100) return; @@ -1784,6 +1914,7 @@ const server = createServer(async (req, res) => { if (results.length >= 100) return; const fullPath = join(dir, entry.name); const relPath = relative(targetDir, fullPath).replace(/\\/g, '/'); + if (entry.isSymbolicLink() && !await safePath(relPath)) continue; if (entry.isDirectory()) { if (shouldSkipDir(entry.name, relPath)) continue; await searchDir(fullPath); @@ -1800,8 +1931,11 @@ const server = createServer(async (req, res) => { if (st.size > MAX_SEARCH_FILE_BYTES) continue; const content = await readFileText(fullPath); const lines = content.split('\n'); + const matchingLines = regexSearch + ? new Set(await regexSearch.findMatches(lines, 100 - results.length)) + : null; for (let i = 0; i < lines.length && results.length < 100; i++) { - if (matcher.test(lines[i])) { + if (matchingLines ? matchingLines.has(i) : matcher.test(lines[i])) { const start = Math.max(0, i - contextLines); const end = Math.min(lines.length, i + contextLines + 1); results.push({ @@ -1813,7 +1947,8 @@ const server = createServer(async (req, res) => { }); } } - } catch { + } catch (err) { + if (err.regexSearch) throw err; // Skip unreadable files } } @@ -1826,8 +1961,10 @@ const server = createServer(async (req, res) => { res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' }); res.end(JSON.stringify(results)); } catch (err) { - res.writeHead(500, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: 'Internal server error' })); + res.writeHead(err.status || 500, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: err.status ? err.message : 'Internal server error' })); + } finally { + await regexSearch?.close(); } return; } @@ -1896,6 +2033,7 @@ const server = createServer(async (req, res) => { if (items.length >= limitNum) return true; const fullPath = join(dir, entry.name); const mediaRel = relative(targetDir, fullPath).replace(/\\/g, '/'); + if (entry.isSymbolicLink() && !await safePath(mediaRel)) continue; if (entry.isDirectory()) { if (shouldSkipDir(entry.name, mediaRel)) continue; if (recursive) { @@ -1973,7 +2111,12 @@ const server = createServer(async (req, res) => { } if (url.pathname === '/api/custom-css') { - const cssPath = join(targetDir, '.docview.css'); + const cssPath = await safePath('.docview.css'); + if (!cssPath) { + res.writeHead(403, { 'Content-Type': 'text/plain' }); + res.end('Access denied'); + return; + } try { const content = await readFile(cssPath, 'utf-8'); res.writeHead(200, { 'Content-Type': 'text/css; charset=utf-8' }); @@ -2018,6 +2161,7 @@ const server = createServer(async (req, res) => { if (backlinks.length >= 50) return; const fullPath = join(dir, entry.name); const entryRel = relative(targetDir, fullPath).replace(/\\/g, '/'); + if (entry.isSymbolicLink() && !await safePath(entryRel)) continue; if (entry.isDirectory()) { if (shouldSkipDir(entry.name, entryRel)) continue; await scanBacklinks(fullPath); @@ -2066,26 +2210,13 @@ const server = createServer(async (req, res) => { const MAX_FILES = 500; const MAX_TOTAL_BYTES = 500 * 1024 * 1024; - let body = ''; - try { - for await (const chunk of req) { - body += chunk; - if (body.length > MAX_BODY) { - res.writeHead(413, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: 'Request body too large' })); - return; - } - } - } catch { - // Client aborted mid-body — connection is gone, nothing to answer. - res.destroy(); - return; - } - let data; - try { data = JSON.parse(body); } catch { - res.writeHead(400, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: 'Invalid JSON' })); + try { + data = await readJsonRequestBody(req, MAX_BODY); + } catch (err) { + if (req.aborted) { res.destroy(); return; } + res.writeHead(err.status || 400, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: err.message || 'Invalid JSON' })); return; } @@ -2102,7 +2233,7 @@ const server = createServer(async (req, res) => { } const entries = []; - const usedNames = new Map(); + const usedNames = new Set(); let totalBytes = 0; for (const reqPath of paths) { @@ -2134,17 +2265,17 @@ const server = createServer(async (req, res) => { } const content = await readFile(resolved); - let name = basename(resolved); - if (usedNames.has(name)) { - const n = usedNames.get(name) + 1; - usedNames.set(name, n); - const dot = name.lastIndexOf('.'); + const originalName = basename(resolved); + let name = originalName; + let n = 0; + while (usedNames.has(name)) { + n++; + const dot = originalName.lastIndexOf('.'); name = dot > 0 - ? `${name.slice(0, dot)} (${n})${name.slice(dot)}` - : `${name} (${n})`; - } else { - usedNames.set(name, 0); + ? `${originalName.slice(0, dot)} (${n})${originalName.slice(dot)}` + : `${originalName} (${n})`; } + usedNames.add(name); entries.push({ name, data: content }); } catch { res.writeHead(404, { 'Content-Type': 'application/json' }); @@ -2175,31 +2306,18 @@ const server = createServer(async (req, res) => { if (req.method === 'POST' && url.pathname === '/api/diagram') { // Body size limit (1 MB) to prevent memory exhaustion const MAX_BODY = 1024 * 1024; - let body = ''; - try { - for await (const chunk of req) { - body += chunk; - if (body.length > MAX_BODY) { - res.writeHead(413, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: 'Request body too large' })); - return; - } - } - } catch { - // Client aborted mid-body — connection is gone, nothing to answer. - res.destroy(); - return; - } - let data; - try { data = JSON.parse(body); } catch { - res.writeHead(400, { 'Content-Type': 'application/json' }); - res.end(JSON.stringify({ error: 'Invalid JSON' })); + try { + data = await readJsonRequestBody(req, MAX_BODY); + } catch (err) { + if (req.aborted) { res.destroy(); return; } + res.writeHead(err.status || 400, { 'Content-Type': 'application/json' }); + res.end(JSON.stringify({ error: err.message || 'Invalid JSON' })); return; } - const { type, source } = data; - if (!type || !source) { + const { type, source } = data ?? {}; + if (typeof type !== 'string' || typeof source !== 'string' || !type || !source) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: 'Missing type or source' })); return; @@ -2275,8 +2393,10 @@ function tryLocalDiagramCLI(type, source) { const proc = spawn(cmd[0], cmd[1], { timeout: 15000 }); let out = ''; proc.stdout.on('data', (d) => { out += d; }); + proc.stderr.resume(); proc.on('close', (code) => { resolve(code === 0 && out ? out : null); }); proc.on('error', () => resolve(null)); + proc.stdin.on('error', () => resolve(null)); proc.stdin.write(source); proc.stdin.end(); } catch { resolve(null); } @@ -2286,24 +2406,27 @@ function tryLocalDiagramCLI(type, source) { // File watcher — chokidar v5 has no glob support, so watch the directory // itself, prune ignored paths via the `ignored` function, and filter events // by extension before broadcasting. -function isWatchIgnored(path) { +function isWatchIgnored(path, stats) { const rel = relative(targetDir, resolve(targetDir, path)); if (!rel || rel.startsWith('..')) return false; - for (const seg of rel.split(sep)) { - if (seg.startsWith('.') || DEFAULT_IGNORED_DIRS.has(seg)) return true; + const segments = rel.split(sep); + for (let i = 0; i < segments.length; i++) { + const seg = segments[i]; + const isDirectory = i < segments.length - 1 || stats?.isDirectory(); + if (isDirectory && (seg.startsWith('.') || DEFAULT_IGNORED_DIRS.has(seg))) return true; } return matchesIgnorePattern(basename(rel), rel); } function isWatchTarget(relPath) { const name = basename(relPath).toLowerCase(); - return SUPPORTED_EXTENSIONS.has(extname(name)) || CRON_FILENAMES.has(name); + return isSupportedFilename(name); } const watcher = chokidar.watch(targetDir, { cwd: targetDir, ignoreInitial: true, - ignored: (path) => isWatchIgnored(path), + ignored: (path, stats) => isWatchIgnored(path, stats), }); function broadcast(event, filePath) { @@ -2379,12 +2502,16 @@ function pickTip() { } server.listen(port, host, () => { + // Preserve the default localhost origin so saved tabs/preferences survive an + // upgrade, while custom bind addresses and IPv6 get a reachable URL. + const browserHost = host === '127.0.0.1' || host === '0.0.0.0' ? 'localhost' : host === '::' ? '::1' : host; + const browserUrl = `http://${isIP(browserHost) === 6 ? `[${browserHost}]` : browserHost}:${port}/`; console.log(''); console.log(BANNER); console.log(` ─────────────────────────────────────────────`); console.log(` Watching: ${targetDir}`); if (initialFile) console.log(` File: ${initialFile}`); - console.log(` Server: http://localhost:${port}/`); + console.log(` Server: ${browserUrl}`); if (remoteEnabled) { const priv = allowPrivateRemote ? ' (incl. private IPs)' : ''; const tls = remoteInsecureTls ? ' · TLS verify off' : ' · TLS strict'; @@ -2395,5 +2522,5 @@ server.listen(port, host, () => { console.log(` ─────────────────────────────────────────────`); console.log(` Tip: ${pickTip()}`); console.log(''); - if (process.send) process.send({ type: 'listening', port }); + if (process.send) process.send({ type: 'listening', port, url: browserUrl }); }); diff --git a/src/album-viewer.ts b/src/album-viewer.ts index 46471b5..4cb6fd9 100644 --- a/src/album-viewer.ts +++ b/src/album-viewer.ts @@ -56,6 +56,8 @@ let _selectedIndex = -1; let _albumTarget: HTMLElement | null = null; let _keyboardHandler: ((e: KeyboardEvent) => void) | null = null; let _observer: IntersectionObserver | null = null; +let _albumRenderId = 0; +let _albumAbortController: AbortController | null = null; // ---- Multi-select state ---- // MAX_COMPARE gates only the Compare button visibility (compare view supports @@ -158,6 +160,7 @@ let _lightboxOpen = false; let _lightboxKeyHandler: ((e: KeyboardEvent) => void) | null = null; let _lightboxPopstateHandler: (() => void) | null = null; let _preloadLinks: HTMLLinkElement[] = []; +let _lightboxAbortController: AbortController | null = null; // Zoom/pan state per Lightbox open session let _lbScale = 1; @@ -452,6 +455,7 @@ async function loadLightboxVideo(item: AlbumImage, wrap: HTMLElement): Promise { + if (!v.isConnected) return; if (!wrap.querySelector('.lightbox__video-error')) { const ext = '.' + (item.path.split('.').pop()?.toLowerCase() ?? ''); const note = ext === '.mov' @@ -485,23 +489,43 @@ async function loadLightboxVideo(item: AlbumImage, wrap: HTMLElement): Promise { + clearLightboxMedia(); + const ctrl = new AbortController(); + _lightboxAbortController = ctrl; if (itemKind(item) === 'video') { await loadLightboxVideo(item, wrap); return; } - return loadLightboxImageInternal(item, wrap); + return loadLightboxImageInternal(item, wrap, ctrl.signal); } -async function loadLightboxImageInternal(image: AlbumImage, wrap: HTMLElement): Promise { +function clearLightboxMedia(): void { + _lightboxAbortController?.abort(); + _lightboxAbortController = null; + const video = getLightboxVideoEl(); + if (video) { + video.pause(); + video.removeAttribute('src'); + video.load(); + } + if (_lbMouseMoveHandler) document.removeEventListener('mousemove', _lbMouseMoveHandler); + if (_lbMouseUpHandler) document.removeEventListener('mouseup', _lbMouseUpHandler); + _lbMouseMoveHandler = null; + _lbMouseUpHandler = null; + _lbDragging = false; +} + +async function loadLightboxImageInternal(image: AlbumImage, wrap: HTMLElement, signal: AbortSignal): Promise { wrap.innerHTML = ''; const url = `/api/file?path=${encodeURIComponent(image.path)}`; if (isSvg(image.path)) { try { - const res = await fetch(url); + const res = await fetch(url, { signal }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const svgText = await res.text(); + if (signal.aborted || !wrap.isConnected) return; const cleanSvg = DOMPurify.sanitize(svgText, { USE_PROFILES: { html: true, svg: true, svgFilters: true }, ADD_TAGS: ['use', 'foreignObject'], @@ -516,6 +540,7 @@ async function loadLightboxImageInternal(image: AlbumImage, wrap: HTMLElement): const imgEl = wrap.querySelector('.lightbox__img'); if (imgEl) initLightboxZoom(imgEl); } catch { + if (signal.aborted || !wrap.isConnected) return; wrap.innerHTML = ''; } return; @@ -565,7 +590,7 @@ async function navigateLightbox(newIndex: number): Promise { // Load image const wrap = _lightboxEl.querySelector('#lightbox-img-wrap'); - if (wrap) await loadLightboxImage(image, wrap); + if (wrap) void loadLightboxImage(image, wrap); // Update preloads updatePreloadLinks(_lightboxIndex, _currentImages); @@ -573,9 +598,10 @@ async function navigateLightbox(newIndex: number): Promise { // ---- Open / Close Lightbox ---- -function closeLightbox(): void { +function closeLightbox(restoreFocus = true): void { if (!_lightboxOpen) return; _lightboxOpen = false; + clearLightboxMedia(); // Re-enable body scroll document.body.classList.remove('lightbox-open'); @@ -615,7 +641,7 @@ function closeLightbox(): void { } // Restore focus to the album tile - if (_albumTarget && _lightboxIndex >= 0) { + if (restoreFocus && _albumTarget && _lightboxIndex >= 0) { const tiles = _albumTarget.querySelectorAll('.album-tile'); const tile = tiles[_lightboxIndex]; if (tile) { @@ -837,7 +863,7 @@ async function openLightbox(index: number): Promise { // Load image into wrap const wrap = overlay.querySelector('#lightbox-img-wrap'); - if (wrap) await loadLightboxImage(image, wrap); + if (wrap) void loadLightboxImage(image, wrap); // Preload adjacent updatePreloadLinks(index, _currentImages); @@ -1234,12 +1260,12 @@ function renderGrid(images: AlbumImage[]): string { return `
${tiles}
`; } -async function fetchAlbum(path: string, recursive: boolean): Promise { +async function fetchAlbum(path: string, recursive: boolean, signal: AbortSignal): Promise { // Query the unified gallery endpoint (image + video). Map back to the legacy // AlbumResponse shape so the rest of the renderer can stay agnostic of the // wire format. const params = new URLSearchParams({ path, recursive: recursive ? '1' : '0', kind: 'all' }); - const res = await fetch(`/api/gallery?${params.toString()}`); + const res = await fetch(`/api/gallery?${params.toString()}`, { signal }); if (!res.ok) { const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` })); throw new Error((body as { error?: string }).error ?? `HTTP ${res.status}`); @@ -1270,14 +1296,16 @@ export async function renderAlbum( recursive = false, onCompare: CompareCallback | null = null, ): Promise { + // Invalidate pending work before installing the next album's state. + disposeAlbum(); + const renderId = _albumRenderId; + const ctrl = new AbortController(); + _albumAbortController = ctrl; _albumTarget = target; _currentAlbumPath = path; _selectedIndex = -1; _currentImages = []; - // Dispose any previous keyboard handler and lightbox - disposeAlbum(); - // Set compare callback AFTER disposeAlbum (which clears it) _compareCallback = onCompare; @@ -1304,11 +1332,14 @@ export async function renderAlbum( let data: AlbumResponse; try { - data = await fetchAlbum(path, recursive); + data = await fetchAlbum(path, recursive, ctrl.signal); } catch (err: unknown) { + if (ctrl.signal.aborted || renderId !== _albumRenderId || !target.contains(albumView)) return; target.innerHTML = `

アルバムの読み込みに失敗しました: ${esc(String(err instanceof Error ? err.message : err))}

`; return; } + if (ctrl.signal.aborted || renderId !== _albumRenderId || !target.contains(albumView)) return; + _albumAbortController = null; _currentImages = sortImages(data.images, getSortKey(), getSortDir()); @@ -1766,36 +1797,11 @@ function upsertPrintControls(toolbar: HTMLElement, images: AlbumImage[], dirPath * Call this when navigating away from album view. */ export function disposeAlbum(): void { + _albumRenderId++; + _albumAbortController?.abort(); + _albumAbortController = null; // Close lightbox without using history.back() to avoid unintended navigation - if (_lightboxOpen) { - _lightboxOpen = false; - document.body.classList.remove('lightbox-open'); - - if (_lightboxKeyHandler) { - document.removeEventListener('keydown', _lightboxKeyHandler); - _lightboxKeyHandler = null; - } - if (_lightboxPopstateHandler) { - window.removeEventListener('popstate', _lightboxPopstateHandler); - _lightboxPopstateHandler = null; - } - if (_lbMouseMoveHandler) { - document.removeEventListener('mousemove', _lbMouseMoveHandler); - _lbMouseMoveHandler = null; - } - if (_lbMouseUpHandler) { - document.removeEventListener('mouseup', _lbMouseUpHandler); - _lbMouseUpHandler = null; - } - for (const link of _preloadLinks) { - link.remove(); - } - _preloadLinks = []; - if (_lightboxEl) { - _lightboxEl.remove(); - _lightboxEl = null; - } - } + closeLightbox(false); if (_keyboardHandler) { document.removeEventListener('keydown', _keyboardHandler); @@ -1809,6 +1815,10 @@ export function disposeAlbum(): void { _multiSelected.clear(); _lastClickedIndex = -1; _compareCallback = null; + _currentAlbumPath = null; + _currentImages = []; + _selectedIndex = -1; + _albumTarget = null; } /** @@ -1825,7 +1835,10 @@ export async function refreshAlbum( const wasSelected = _selectedIndex; // Preserve multi-selected paths across refresh (paths that still exist will be re-applied) const prevMultiSelected = new Set(_multiSelected); - await renderAlbum(path, target, openImage, recursive, onCompare); + const render = renderAlbum(path, target, openImage, recursive, onCompare); + const renderId = _albumRenderId; + await render; + if (renderId !== _albumRenderId) return; // Restore multi-selection for paths that still exist in the new image list const newPaths = new Set(_currentImages.map((img) => img.path)); for (const p of prevMultiSelected) { diff --git a/src/chunked-table.ts b/src/chunked-table.ts index c968813..7b91329 100644 --- a/src/chunked-table.ts +++ b/src/chunked-table.ts @@ -5,6 +5,7 @@ import Papa from 'papaparse'; import { detectLogFormat, type LogEntry, type LogFormat } from './log-viewer'; +import { isSecretSafeModeEnabled, maskSecretValue, type SecretMasker } from './secret-mask'; type FileKind = 'csv' | 'jsonl' | 'log'; @@ -17,6 +18,7 @@ interface ChunkMeta { } interface SearchMatch { + /** Zero-based source line (or CSV record with records=1). */ lineNum: number; text: string; } @@ -37,13 +39,12 @@ function esc(s: string): string { return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } -/** Escape HTML then wrap matching portions in */ +/** Match the source text before escaping so matches cannot split HTML entities. */ function escWithHighlight(s: string, query: string): string { - const escaped = esc(s); - if (!query) return escaped; - const escapedQuery = esc(query); - const re = new RegExp(`(${escapedQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); - return escaped.replace(re, '$1'); + if (!query) return esc(s); + const re = new RegExp(`(${query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi'); + return s.split(re).map((part, i) => i % 2 + ? `${esc(part)}` : esc(part)).join(''); } function statusClass(status: string): string { @@ -60,17 +61,18 @@ function statusClass(status: string): string { interface CsvChunkResult { fields: string[]; rows: Record[]; + delimiter: string; } function parseCsvChunk(text: string, hasHeader: boolean): CsvChunkResult { const result = Papa.parse(text, { header: hasHeader, skipEmptyLines: true, - dynamicTyping: true, + dynamicTyping: false, }); const fields = result.meta.fields ?? []; const rows = (result.data as Record[]) ?? []; - return { fields, rows }; + return { fields, rows, delimiter: result.meta.delimiter }; } // --- JSONL chunk parsing --- @@ -79,19 +81,23 @@ interface JsonlChunkResult { fields: string[]; rows: Record[]; parseErrors: number; + lineIndexes: number[]; } function parseJsonlChunk(text: string): JsonlChunkResult { - const lines = text.split('\n').filter((l) => l.trim() !== ''); + const lines = text.split('\n'); const rows: Record[] = []; + const lineIndexes: number[] = []; let parseErrors = 0; const fieldSet = new Map(); - for (const line of lines) { + for (const [index, line] of lines.entries()) { + if (!line.trim()) continue; try { const obj = JSON.parse(line); if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) { rows.push(obj as Record); + lineIndexes.push(index); for (const key of Object.keys(obj)) fieldSet.set(key, true); } else { parseErrors++; @@ -101,7 +107,7 @@ function parseJsonlChunk(text: string): JsonlChunkResult { } } - return { fields: Array.from(fieldSet.keys()), rows, parseErrors }; + return { fields: Array.from(fieldSet.keys()), rows, parseErrors, lineIndexes }; } // --- Log chunk parsing --- @@ -137,45 +143,49 @@ function parseLogLine(line: string, format: LogFormat): LogEntry | null { // --- Render helpers with optional highlighting --- -function renderCsvRows(fields: string[], rows: Record[], rowNums: number[], query = ''): string { +function renderCsvRows(fields: string[], rows: Record[], rowNums: number[], query = '', maskValue?: SecretMasker): string { return rows.map((row, i) => { - const tds = fields.map((f) => `${escWithHighlight(String(row[f] ?? ''), query)}`).join(''); + const tds = fields.map((f) => { + const value = String(Object.hasOwn(row, f) ? row[f] ?? '' : ''); + return `${escWithHighlight(maskValue ? maskValue(value, f) : value, query)}`; + }).join(''); const n = rowNums[i]; return `${n}${tds}`; }).join(''); } -function renderJsonlRows(fields: string[], rows: Record[], rowNums: number[], query = ''): string { +function renderJsonlRows(fields: string[], rows: Record[], rowNums: number[], query = '', maskValue?: SecretMasker): string { return rows.map((row, i) => { const tds = fields.map((f) => { - const val = row[f]; + const val = Object.hasOwn(row, f) ? row[f] : undefined; const cell = val === undefined || val === null ? '' : typeof val === 'object' ? JSON.stringify(val) : String(val); - return `${escWithHighlight(cell, query)}`; + return `${escWithHighlight(maskValue ? maskValue(cell, f) : cell, query)}`; }).join(''); const n = rowNums[i]; return `${n}${tds}`; }).join(''); } -function renderLogRows(entries: LogEntry[], isCombined: boolean, query = ''): string { +function renderLogRows(entries: LogEntry[], isCombined: boolean, query = '', maskValue?: SecretMasker): string { return entries.map((e, i) => { const sc = statusClass(e.status); - const h = (s: string) => escWithHighlight(s, query); + const mask = (s: string) => maskValue ? maskValue(s) : s; + const h = (s: string) => escWithHighlight(mask(s), query); const tds = [ `${h(e.ip)}`, `${h(e.user)}`, `${h(e.timestamp)}`, `${h(e.method)}`, - `${h(e.path)}`, + `${h(e.path)}`, `${h(e.status)}`, `${h(e.size)}`, ]; if (isCombined) { tds.push( - `${h(e.referer)}`, - `${h(e.userAgent)}`, + `${h(e.referer)}`, + `${h(e.userAgent)}`, ); } return `${tds.join('')}`; @@ -213,6 +223,8 @@ function renderSearchBar(query: string, totalMatches: number | null): string { // --- Main chunked table class --- interface ChunkedOptions { + /** Ignore responses after the owning document navigation has changed. */ + isCurrent?: () => boolean; /** Target line from URL hash. Used to open the page that contains it. */ initialLine?: number | null; /** Retained for signature parity with the main viewer; currently unused @@ -226,9 +238,13 @@ export class ChunkedTable { private currentPage = 1; private totalPages: number; private initialLine: number | null; + private isCurrent: () => boolean; + private requestId = 0; + private maskValue?: SecretMasker; // Cached header for CSV (first row parsed from first chunk) private csvFields: string[] | null = null; + private csvDelimiter = ','; // Cached log format private logFormat: LogFormat = 'unknown'; @@ -241,6 +257,8 @@ export class ChunkedTable { this.container = container; this.meta = meta; this.initialLine = options.initialLine ?? null; + this.isCurrent = options.isCurrent ?? (() => true); + this.maskValue = isSecretSafeModeEnabled() ? maskSecretValue : undefined; const dataLines = meta.kind === 'csv' ? Math.max(0, meta.totalLines - 1) : meta.totalLines; this.totalPages = Math.max(1, Math.ceil(dataLines / PAGE_SIZE)); } @@ -248,12 +266,15 @@ export class ChunkedTable { async init(): Promise { if (this.meta.kind === 'csv') { const headerText = await this.fetchLines(0, 1); + if (!this.isCurrent()) return; const parsed = parseCsvChunk(headerText, true); this.csvFields = parsed.fields.length > 0 ? parsed.fields : null; + this.csvDelimiter = parsed.delimiter; } if (this.meta.kind === 'log') { const sampleText = await this.fetchLines(0, 5); + if (!this.isCurrent()) return; this.logFormat = detectLogFormat(sampleText); // Chunked rendering only supports the line-oriented Apache/nginx formats. // Laravel entries can span multiple lines (stack traces, var_dump output), @@ -271,7 +292,7 @@ export class ChunkedTable { if (this.meta.kind === 'jsonl' && this.initialLine != null) { this.pendingHighlightRow = this.initialLine; } - await this.loadPage(this.computeInitialPage()); + await this.loadPage(this.computeInitialPage(), true); } /** Page that contains `initialLine`. Falls back to 1 when unset. */ @@ -281,7 +302,9 @@ export class ChunkedTable { // CSV line 1 is the header; data rows span lines 2..N, so the data index // is (line - 1) and paging counts from there. const dataIdx = this.meta.kind === 'csv' ? Math.max(1, n - 1) : n; - return Math.max(1, Math.min(this.totalPages, Math.ceil(dataIdx / PAGE_SIZE))); + // Metadata is sampled for large files. The first range response supplies + // the exact count, so do not clamp a deep link against an estimate. + return Math.max(1, Math.ceil(dataIdx / PAGE_SIZE)); } isLogUnknown(): boolean { @@ -291,14 +314,16 @@ export class ChunkedTable { return this.meta.kind === 'log' && (this.logFormat === 'unknown' || this.logFormat === 'laravel'); } - private async fetchLines(offset: number, limit: number): Promise { - const url = `/api/file?path=${encodeURIComponent(this.meta.path)}&offset=${offset}&limit=${limit}`; + private async fetchLines(offset: number, limit: number, requestId = this.requestId): Promise { + const records = this.meta.kind === 'csv' ? '&records=1' : ''; + const url = `/api/file?path=${encodeURIComponent(this.meta.path)}&offset=${offset}&limit=${limit}${records}`; const res = await fetch(url); if (!res.ok) throw new Error(`Fetch failed: ${res.status}`); + if (requestId !== this.requestId || !this.isCurrent()) return ''; const totalHeader = res.headers.get('X-Total-Lines'); if (totalHeader) { const total = parseInt(totalHeader, 10); - if (!isNaN(total) && total > 0) { + if (!isNaN(total) && total >= 0) { const dataLines = this.meta.kind === 'csv' ? Math.max(0, total - 1) : total; if (!this.searchQuery) { this.totalPages = Math.max(1, Math.ceil(dataLines / PAGE_SIZE)); @@ -310,28 +335,42 @@ export class ChunkedTable { } private async fetchSearchResults(query: string, offset: number, limit: number): Promise { - const url = `/api/file/search?path=${encodeURIComponent(this.meta.path)}&q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}`; + const records = this.meta.kind === 'csv' ? '&records=1' : ''; + const url = `/api/file/search?path=${encodeURIComponent(this.meta.path)}&q=${encodeURIComponent(query)}&offset=${offset}&limit=${limit}${records}`; const res = await fetch(url); if (!res.ok) throw new Error(`Search failed: ${res.status}`); return res.json(); } - private async loadPage(page: number): Promise { + private async loadPage(page: number, initial = false): Promise { + if (!this.isCurrent()) return; if (this.searchQuery) { await this.loadSearchPage(page); return; } - this.currentPage = Math.max(1, Math.min(page, this.totalPages)); + const requestId = ++this.requestId; + this.currentPage = Math.max(1, initial ? page : Math.min(page, this.totalPages)); const dataOffset = (this.currentPage - 1) * PAGE_SIZE; const lineOffset = this.meta.kind === 'csv' ? dataOffset + 1 : dataOffset; this.showLoading(); - const text = await this.fetchLines(lineOffset, PAGE_SIZE); - this.renderTable(text); + try { + const text = await this.fetchLines(lineOffset, PAGE_SIZE); + if (requestId !== this.requestId || !this.isCurrent()) return; + if (this.currentPage > this.totalPages) { + await this.loadPage(this.totalPages); + return; + } + this.renderTable(text); + } catch (error) { + this.showError(error, requestId); + } } private async loadSearchPage(page: number): Promise { + if (!this.isCurrent()) return; + const requestId = ++this.requestId; const searchPages = Math.max(1, Math.ceil(this.searchTotalMatches / PAGE_SIZE)); this.currentPage = Math.max(1, Math.min(page, searchPages)); this.totalPages = searchPages; @@ -339,11 +378,34 @@ export class ChunkedTable { const offset = (this.currentPage - 1) * PAGE_SIZE; this.showLoading(); - const result = await this.fetchSearchResults(this.searchQuery, offset, PAGE_SIZE); - this.searchTotalMatches = result.totalMatches; - this.totalPages = Math.max(1, Math.ceil(result.totalMatches / PAGE_SIZE)); + try { + const result = await this.fetchSearchResults(this.searchQuery, offset, PAGE_SIZE); + if (requestId !== this.requestId || !this.isCurrent()) return; + this.searchTotalMatches = result.totalMatches; + this.totalPages = Math.max(1, Math.ceil(result.totalMatches / PAGE_SIZE)); + if (this.currentPage > this.totalPages) { + await this.loadSearchPage(this.totalPages); + return; + } + this.renderSearchResults(result); + } catch (error) { + this.showError(error, requestId); + } + } - this.renderSearchResults(result); + private showError(error: unknown, requestId: number): void { + if (requestId !== this.requestId || !this.isCurrent()) return; + const message = esc(error instanceof Error ? error.message : 'Unable to load data'); + const tbody = this.container.querySelector('.chunk-tbody'); + if (tbody) tbody.innerHTML = `${message}`; + else this.container.innerHTML = `

${message}

`; + this.container.querySelectorAll('.chunk-page-input').forEach((input) => { + input.value = String(this.currentPage); + }); + this.container.querySelectorAll('.chunk-page-btn').forEach((button) => { + const before = button.dataset.page === 'first' || button.dataset.page === 'prev'; + button.disabled = before ? this.currentPage <= 1 : this.currentPage >= this.totalPages; + }); } private showLoading(): void { @@ -354,6 +416,8 @@ export class ChunkedTable { } private async executeSearch(query: string): Promise { + if (!this.isCurrent()) return; + if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer); this.searchQuery = query; if (!query) { // Clear search — restore normal view @@ -364,14 +428,7 @@ export class ChunkedTable { return; } - // Fetch first page of search results - this.showLoading(); - const result = await this.fetchSearchResults(query, 0, PAGE_SIZE); - this.searchTotalMatches = result.totalMatches; - this.totalPages = Math.max(1, Math.ceil(result.totalMatches / PAGE_SIZE)); - this.currentPage = 1; - - this.renderSearchResults(result); + await this.loadSearchPage(1); } private renderSearchResults(result: SearchResult): void { @@ -380,19 +437,15 @@ export class ChunkedTable { let theadHtml: string; let tbodyHtml: string; - // Sequential numbering within the result set (match ordinal across pages). - const matchOffset = (this.currentPage - 1) * PAGE_SIZE; - const matchNumbering = (rows: unknown[]): number[] => rows.map((_, i) => matchOffset + i + 1); - if (kind === 'csv') { const fields = this.csvFields ?? []; if (fields.length && result.matches.length) { // Re-parse each matched line with the known header - const headerLine = result.headerLine || fields.join(','); + const headerLine = result.headerLine || fields.map((f) => `"${f.replace(/"/g, '""')}"`).join(this.csvDelimiter); const chunkText = headerLine + '\n' + result.matches.map((m) => m.text).join('\n'); const parsed = parseCsvChunk(chunkText, true); theadHtml = this.buildThead(fields, true); - tbodyHtml = renderCsvRows(fields, parsed.rows, matchNumbering(parsed.rows), query); + tbodyHtml = renderCsvRows(fields, parsed.rows, result.matches.map((m) => m.lineNum), query, this.maskValue); } else { theadHtml = this.buildThead(fields, true); tbodyHtml = ''; @@ -401,7 +454,7 @@ export class ChunkedTable { const chunkText = result.matches.map((m) => m.text).join('\n'); const parsed = parseJsonlChunk(chunkText); theadHtml = this.buildThead(parsed.fields, true); - tbodyHtml = renderJsonlRows(parsed.fields, parsed.rows, matchNumbering(parsed.rows), query); + tbodyHtml = renderJsonlRows(parsed.fields, parsed.rows, parsed.lineIndexes.map((i) => result.matches[i].lineNum + 1), query, this.maskValue); } else { // log const isCombined = this.logFormat === 'combined'; @@ -414,7 +467,7 @@ export class ChunkedTable { const entry = parseLogLine(m.text, this.logFormat); if (entry) entries.push(entry); } - tbodyHtml = renderLogRows(entries, isCombined, query); + tbodyHtml = renderLogRows(entries, isCombined, query, this.maskValue); } const startMatch = (this.currentPage - 1) * PAGE_SIZE + 1; @@ -468,22 +521,21 @@ export class ChunkedTable { const parsed = parseCsvChunk(chunkText, true); this.csvFields = parsed.fields; theadHtml = this.buildThead(parsed.fields, true); - tbodyHtml = renderCsvRows(parsed.fields, parsed.rows, numbering(parsed.rows)); + tbodyHtml = renderCsvRows(parsed.fields, parsed.rows, numbering(parsed.rows), '', this.maskValue); } else { // 合成ヘッダ行はクォート必須: フィールド名に区切り文字や引用符が // 含まれると Papa.parse が列をずらして解釈してしまう - const delim = this.meta.path.toLowerCase().endsWith('.tsv') ? '\t' : ','; - const headerLine = fields.map((f) => `"${String(f).replace(/"/g, '""')}"`).join(delim); + const headerLine = fields.map((f) => `"${String(f).replace(/"/g, '""')}"`).join(this.csvDelimiter); const parsed = parseCsvChunk(headerLine + '\n' + chunkText, true); theadHtml = this.buildThead(fields, true); - tbodyHtml = renderCsvRows(fields, parsed.rows, numbering(parsed.rows)); + tbodyHtml = renderCsvRows(fields, parsed.rows, numbering(parsed.rows), '', this.maskValue); } const ext = this.meta.path.split('.').pop()?.toUpperCase() || 'CSV'; - infoHtml = `${(this.meta.totalLines - 1).toLocaleString()} rows — ${ext} (chunked)`; + infoHtml = `${Math.max(0, this.meta.totalLines - 1).toLocaleString()} rows — ${ext} (chunked)`; } else if (kind === 'jsonl') { const parsed = parseJsonlChunk(chunkText); theadHtml = this.buildThead(parsed.fields, true); - tbodyHtml = renderJsonlRows(parsed.fields, parsed.rows, numbering(parsed.rows)); + tbodyHtml = renderJsonlRows(parsed.fields, parsed.rows, parsed.lineIndexes.map((i) => pageStartRow + i), '', this.maskValue); infoHtml = `${this.meta.totalLines.toLocaleString()} lines — JSONL (chunked)`; } else { const isCombined = this.logFormat === 'combined'; @@ -497,12 +549,13 @@ export class ChunkedTable { const entry = parseLogLine(line, this.logFormat); if (entry) entries.push(entry); } - tbodyHtml = renderLogRows(entries, isCombined); + tbodyHtml = renderLogRows(entries, isCombined, '', this.maskValue); infoHtml = `${this.meta.totalLines.toLocaleString()} lines • Format: ${esc(this.logFormat)} (chunked)`; } - const startRow = (this.currentPage - 1) * PAGE_SIZE + 1; - const endRow = Math.min(this.currentPage * PAGE_SIZE, kind === 'csv' ? this.meta.totalLines - 1 : this.meta.totalLines); + const totalRows = Math.max(0, kind === 'csv' ? this.meta.totalLines - 1 : this.meta.totalLines); + const startRow = totalRows ? (this.currentPage - 1) * PAGE_SIZE + 1 : 0; + const endRow = Math.min(this.currentPage * PAGE_SIZE, totalRows); const rangeInfo = `Rows ${startRow.toLocaleString()}–${endRow.toLocaleString()}`; const sizeLabel = this.meta.fileSize >= 1024 * 1024 @@ -621,11 +674,12 @@ export class ChunkedTable { if (searchInput) { searchInput.addEventListener('input', () => { if (this.searchDebounceTimer) clearTimeout(this.searchDebounceTimer); + // Invalidate a pending response as soon as the query changes, before + // debounce elapses; otherwise it can replace the input being edited. + this.requestId++; this.searchDebounceTimer = setTimeout(() => { const val = searchInput.value.trim(); - if (val.length >= 2 || val.length === 0) { - this.executeSearch(val); - } + void this.executeSearch(val); }, SEARCH_DEBOUNCE_MS); }); searchInput.addEventListener('keydown', (e) => { diff --git a/src/cron-viewer.ts b/src/cron-viewer.ts index 39f8946..caabf49 100644 --- a/src/cron-viewer.ts +++ b/src/cron-viewer.ts @@ -1,4 +1,4 @@ -import cronstrue from 'cronstrue/i18n'; +import cronstrue from 'cronstrue/i18n.js'; import { CronExpressionParser } from 'cron-parser'; import type { SecretMasker } from './secret-mask'; @@ -33,7 +33,7 @@ function parseCrontab(content: string): { jobs: CronJob[]; envs: CronEnv[] } { if (!line || line.startsWith('#')) return; // 空行・コメント行はスキップ // @reboot: 起動時実行。cron-parser/cronstrue が解釈できないため特別扱い - if (/^@reboot\b/.test(line)) { + if (/^@reboot(?:\s|$)/.test(line)) { jobs.push({ line: lineNo, schedule: '@reboot', command: line.replace(/^@reboot\s*/, ''), isReboot: true }); return; } @@ -58,9 +58,9 @@ function parseCrontab(content: string): { jobs: CronJob[]; envs: CronEnv[] } { // 標準の 5 フィールド + コマンド。 // 注: /etc/crontab 形式 (6 番目が実行ユーザー) は特別扱いせず、ユーザー名はコマンド側に含めて表示する。 - const parts = line.split(/\s+/); - if (parts.length >= 6) { - jobs.push({ line: lineNo, schedule: parts.slice(0, 5).join(' '), command: parts.slice(5).join(' '), isReboot: false }); + const standard = line.match(/^(\S+\s+\S+\s+\S+\s+\S+\s+\S+)\s+(.+)$/); + if (standard) { + jobs.push({ line: lineNo, schedule: standard[1].replace(/\s+/g, ' '), command: standard[2], isReboot: false }); } else { // 5 フィールド以下: コマンドなし、あるいは不正な行。スケジュールとしてそのまま解析を試みる。 jobs.push({ line: lineNo, schedule: line, command: '', isReboot: false }); @@ -115,6 +115,9 @@ function computeRuns(schedule: string, now: Date, tz: string): string[] { } function analyzeJob(job: CronJob, now: Date): JobAnalysis { + if (!job.command) { + return { descJa: '解析できないスケジュール', descEn: 'Unable to parse schedule', runsJst: [], runsUtc: [], timeline: null, valid: false }; + } if (job.isReboot) { return { descJa: 'システム起動時に実行', descEn: 'At system startup', runsJst: [], runsUtc: [], timeline: null, valid: true }; } @@ -122,6 +125,8 @@ function analyzeJob(job: CronJob, now: Date): JobAnalysis { let descJa: string; let descEn: string; try { + // The description formatter accepts expressions the scheduler rejects. + CronExpressionParser.parse(job.schedule); descJa = cronstrue.toString(job.schedule, { locale: 'ja', use24HourTimeFormat: true }); descEn = cronstrue.toString(job.schedule, { locale: 'en', use24HourTimeFormat: true }); } catch { @@ -208,7 +213,7 @@ function computeHeatmap(jobs: CronJob[]): { grid: number[][]; max: number } | nu const grid: number[][] = Array.from({ length: 7 }, () => new Array(24).fill(0)); let max = 0; for (const job of jobs) { - if (job.isReboot) continue; + if (job.isReboot || !job.command) continue; try { const e = CronExpressionParser.parse(job.schedule); const dows = new Set(); @@ -272,10 +277,12 @@ interface JobRuns { function gatherRuns(jobs: CronJob[], now: Date): JobRuns[] { const horizon = now.getTime() + FREQ_HORIZON_DAYS * DAY_MS; return jobs.map((job, idx) => { - if (job.isReboot) return { idx, job, runs: [], perDay: 0 }; + if (job.isReboot || !job.command) return { idx, job, runs: [], perDay: 0 }; const runs: Date[] = []; try { - const it = CronExpressionParser.parse(job.schedule, { currentDate: now }); + // Collision timestamps are labelled JST, so interpret schedules in JST + // regardless of the browser's own timezone. + const it = CronExpressionParser.parse(job.schedule, { currentDate: now, tz: 'Asia/Tokyo' }); while (runs.length < FREQ_CAP && it.hasNext()) { const d = it.next().toDate(); if (d.getTime() > horizon) break; @@ -371,7 +378,7 @@ function renderFrequency(jr: JobRuns[]): string { function renderCollisions(cols: Collision[], jr: JobRuns[], maskValue?: SecretMasker): string { if (!cols.length) { - return `
同時刻に重なるジョブはありません(今後 ${FREQ_HORIZON_DAYS} 日間)
`; + return `
先読みした範囲では重複はありません(最大 ${FREQ_HORIZON_DAYS} 日間・各ジョブ ${FREQ_CAP} 回まで · JST)
`; } const MAX = 8; const items = cols @@ -383,7 +390,7 @@ function renderCollisions(cols: Collision[], jr: JobRuns[], maskValue?: SecretMa .join(''); const more = cols.length > MAX ? `
  • ほか ${cols.length - MAX} 件
  • ` : ''; return `
    -
    ⚠ 同時実行の重複 (${cols.length} 件 · 今後 ${FREQ_HORIZON_DAYS} 日間 · JST)
    +
    ⚠ 同時実行の重複 (${cols.length} 件 · 最大 ${FREQ_HORIZON_DAYS} 日間・各ジョブ ${FREQ_CAP} 回まで · JST)
      ${items}${more}
    `; } diff --git a/src/csv-viewer.ts b/src/csv-viewer.ts index f35d0f1..742164b 100644 --- a/src/csv-viewer.ts +++ b/src/csv-viewer.ts @@ -1,15 +1,26 @@ import Papa from 'papaparse'; -import type { SecretMasker } from './secret-mask'; +import { maskSecretValue, type SecretMasker } from './secret-mask'; + +/** Redact source cells using their header keys as well as token patterns. */ +export function maskCsvSecrets(content: string): string { + const parsed = Papa.parse(content, { dynamicTyping: false }); + const [fields, ...rows] = parsed.data; + if (!fields) return content; + return Papa.unparse([fields, ...rows.map((row) => row.map((cell, i) => maskSecretValue(cell, fields[i])))], { + delimiter: parsed.meta.delimiter, + newline: parsed.meta.linebreak, + }); +} export function renderCsvTable(content: string, path: string, maskValue?: SecretMasker): string { const result = Papa.parse(content, { header: true, skipEmptyLines: true, - dynamicTyping: true, + dynamicTyping: false, }); if (!result.data.length || !result.meta.fields?.length) { - return `

    No data found in ${path}

    `; + return `

    No data found in ${esc(path)}

    `; } const fields = result.meta.fields; @@ -48,25 +59,27 @@ function esc(s: string): string { return s.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } -const NUM_RE = /^-?[\d,]+\.?\d*$/; +const NUM_RE = /^[+-]?(?:\d+(?:,\d{3})*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i; const DATE_RE = /^\d{4}[-/]\d{1,2}[-/]\d{1,2}/; function parseNum(s: string): number { - return parseFloat(s.replace(/,/g, '')) || 0; + return NUM_RE.test(s) ? Number(s.replace(/,/g, '')) : NaN; } function detectColumnType(rows: Element[], colIndex: number): 'number' | 'date' | 'string' { let numCount = 0; let dateCount = 0; + let nonEmptyCount = 0; const sample = Math.min(rows.length, 20); for (let i = 0; i < sample; i++) { const text = (rows[i].children[colIndex]?.textContent ?? '').trim(); if (!text) continue; + nonEmptyCount++; if (NUM_RE.test(text)) numCount++; else if (DATE_RE.test(text) && !isNaN(Date.parse(text))) dateCount++; } - if (numCount >= sample * 0.8) return 'number'; - if (dateCount >= sample * 0.8) return 'date'; + if (nonEmptyCount && numCount >= nonEmptyCount * 0.8) return 'number'; + if (nonEmptyCount && dateCount >= nonEmptyCount * 0.8) return 'date'; return 'string'; } @@ -91,8 +104,13 @@ function compareRows( ): number { const aText = (a.children[colIndex]?.textContent ?? '').trim(); const bText = (b.children[colIndex]?.textContent ?? '').trim(); - if (colType === 'number') return parseNum(aText) - parseNum(bText); - if (colType === 'date') return Date.parse(aText) - Date.parse(bText); + if (colType !== 'string') { + const aValue = colType === 'number' ? parseNum(aText) : Date.parse(aText); + const bValue = colType === 'number' ? parseNum(bText) : Date.parse(bText); + if (Number.isFinite(aValue) && Number.isFinite(bValue)) return aValue - bValue; + if (Number.isFinite(aValue)) return -1; + if (Number.isFinite(bValue)) return 1; + } return aText.localeCompare(bText); } diff --git a/src/html-viewer.ts b/src/html-viewer.ts index 2a9e6de..15b344d 100644 --- a/src/html-viewer.ts +++ b/src/html-viewer.ts @@ -60,18 +60,28 @@ function splitLocalUrl(raw: string): { path: string; suffix: string } | null { function resolveResourceUrl(currentPath: string, raw: string): string | null { if (isExternalOrSpecialUrl(raw)) return null; + if (/^https?:\/\//i.test(currentPath)) { + try { return new URL(raw, currentPath).href; } catch { return null; } + } const split = splitLocalUrl(raw); if (!split) return null; + // Resource attributes contain URLs, whereas currentPath is a filesystem + // path. Decode the URL once before encoding the raw-file endpoint path so + // spaces, Unicode and literal percent signs are not double-encoded. + let resourcePath = split.path; + try { resourcePath = decodeURIComponent(resourcePath); } catch { /* literal percent sign */ } + const baseDir = currentPath.includes('/') ? currentPath.replace(/\/[^/]+$/, '') : ''; - const candidate = split.path.startsWith('/') - ? split.path.slice(1) - : `${baseDir ? `${baseDir}/` : ''}${split.path}`; + const candidate = resourcePath.startsWith('/') + ? resourcePath.slice(1) + : `${baseDir ? `${baseDir}/` : ''}${resourcePath}`; const normalized = normalizeLocalPath(candidate); if (!normalized) return null; - const resourceUrl = `/api/raw/${normalized.split('/').map(encodeURIComponent).join('/')}`; - if (split.suffix.startsWith('?')) return `${resourceUrl}${split.suffix}`; + const resourceUrl = `/api/raw/${normalized.split('/').map((part) => + encodeURIComponent(part).replace(/[!'()*]/g, (char) => `%${char.charCodeAt(0).toString(16).toUpperCase()}`), + ).join('/')}`; return `${resourceUrl}${split.suffix}`; } @@ -125,10 +135,69 @@ function buildPreviewHtml(displayContent: string, currentPath: string): string { if (raw) el.setAttribute('style', rewriteCssResourceUrls(raw, currentPath)); }); + // Read the rendered document through messaging while its origin remains + // opaque. Capturing this snapshot preserves script-generated HTML without + // ever replaying document scripts in the application's origin. + const captureBridge = doc.createElement('script'); + captureBridge.textContent = `window.addEventListener('message', (event) => { + if (event.source !== parent || event.data?.type !== 'docview-capture-request' + || typeof event.data.requestId !== 'string') return; + const snapshot = document.documentElement.cloneNode(true); + const canvases = document.querySelectorAll('canvas'); + snapshot.querySelectorAll('canvas').forEach((node, index) => { + const original = canvases[index]; + try { + const image = document.createElement('img'); + for (const attribute of node.attributes) image.setAttribute(attribute.name, attribute.value); + image.src = original.toDataURL(); + // Canvas pixels are not part of outerHTML. Preserve their rendered + // appearance as an image without rerunning scripts during capture. + const styles = getComputedStyle(original); + for (let i = 0; i < styles.length; i++) { + const name = styles[i]; + image.style.setProperty(name, styles.getPropertyValue(name), styles.getPropertyPriority(name)); + } + node.replaceWith(image); + } catch { /* Cross-origin canvas pixels may be unreadable. */ } + }); + snapshot.querySelectorAll('script, noscript').forEach((node) => node.remove()); + parent.postMessage({ type: 'docview-capture-response', requestId: event.data.requestId, + html: '\\n' + snapshot.outerHTML }, '*'); + });`; + doc.body.appendChild(captureBridge); + const doctype = doc.doctype ? `` : ''; return `${doctype}\n${doc.documentElement.outerHTML}`; } +function snapshotPreviewHtml(frame: HTMLIFrameElement): Promise { + const fallback = frame.getAttribute('srcdoc') || ''; + const previewWindow = frame.contentWindow; + if (!previewWindow || !frame.sandbox.contains('allow-scripts')) return Promise.resolve(fallback); + + return new Promise((resolve) => { + const requestId = `${Date.now()}-${Math.random().toString(36).slice(2)}`; + const finish = (html: string) => { + clearTimeout(timeout); + window.removeEventListener('message', onMessage); + resolve(html); + }; + const onMessage = (event: MessageEvent) => { + if (event.source !== previewWindow || event.data?.type !== 'docview-capture-response' + || event.data.requestId !== requestId || typeof event.data.html !== 'string') return; + finish(event.data.html); + }; + // Disabled scripts, document CSP or navigation can prevent a response. + const timeout = setTimeout(() => finish(fallback), 1000); + window.addEventListener('message', onMessage); + try { + previewWindow.postMessage({ type: 'docview-capture-request', requestId }, '*'); + } catch { + finish(fallback); + } + }); +} + /** * Build the HTML-view markup. `displayContent` is the (already secret-masked * when applicable) raw HTML; `sourceHighlighted` is the hljs-highlighted source. @@ -184,10 +253,12 @@ export function initHtmlScriptsToggle(): void { export async function captureHtmlFullPage(frame: HTMLIFrameElement, defaultFilename = 'html-screenshot.png'): Promise { const { domToCanvas } = await import('modern-screenshot'); - const srcdoc = frame.getAttribute('srcdoc') || ''; + const srcdoc = await snapshotPreviewHtml(frame); const width = Math.max(frame.clientWidth || 1200, 800); - // Create a temporary same-origin iframe to render full document with body styles + // Same-origin access is needed by the DOM capture library, so scripts MUST + // remain disabled here. Replaying untrusted srcdoc with both allow-scripts + // and allow-same-origin would let a captured document access the parent app. const tempFrame = document.createElement('iframe'); tempFrame.className = 'html-capture-temp-frame'; tempFrame.style.cssText = ` @@ -205,7 +276,7 @@ export async function captureHtmlFullPage(frame: HTMLIFrameElement, defaultFilen pointer-events: none; overflow: visible; `; - tempFrame.setAttribute('sandbox', 'allow-scripts allow-same-origin'); + tempFrame.setAttribute('sandbox', 'allow-same-origin'); tempFrame.setAttribute('srcdoc', srcdoc); document.body.appendChild(tempFrame); @@ -388,4 +459,3 @@ export function initHtmlScreenshotToggle(): void { } }); } - diff --git a/src/image-meta-panel.ts b/src/image-meta-panel.ts index f1479c0..9bed811 100644 --- a/src/image-meta-panel.ts +++ b/src/image-meta-panel.ts @@ -13,7 +13,7 @@ interface ImageMetaDimensions { width: number; height: number; aspectRatio: string; - megapixels: number | null; + megapixels: number | 'N/A' | null; } interface ImageMetaExif { @@ -107,7 +107,8 @@ function buildBasicSection(meta: ImageMeta): string { if (d) { dims = `${d.width} × ${d.height} px`; aspect = sanitize(d.aspectRatio); - mp = d.megapixels != null ? `${d.megapixels.toFixed(2)} MP` : 'N/A'; + mp = typeof d.megapixels === 'number' && Number.isFinite(d.megapixels) + ? `${d.megapixels.toFixed(2)} MP` : 'N/A'; } const content = ` ${row('ファイルサイズ', b.sizeHuman)} @@ -292,12 +293,16 @@ export class ImageMetaPanel { } // Copy buttons (FR-12) — delegate - panel.addEventListener('click', (e) => { + panel.addEventListener('click', async (e) => { const btn = (e.target as HTMLElement).closest('.imp-copy'); if (!btn) return; const value = btn.dataset.value ?? ''; - navigator.clipboard.writeText(value).catch(() => { /* ignore */ }); - btn.textContent = '✓'; + try { + await navigator.clipboard.writeText(value); + btn.textContent = '✓'; + } catch { + btn.textContent = '✗'; + } setTimeout(() => { btn.textContent = '⎘'; }, 1500); }); } @@ -342,6 +347,8 @@ export class ImageMetaPanel { // Unwrap imp-wrapper → restore children to original parent const wrapper = this.container.querySelector('.imp-wrapper'); if (wrapper && wrapper.parentElement) { + wrapper.querySelector('.imp-toggle-btn')?.remove(); + wrapper.querySelector('.imp-panel')?.remove(); const parent = wrapper.parentElement; while (wrapper.firstChild) { parent.insertBefore(wrapper.firstChild, wrapper); diff --git a/src/json-tree.ts b/src/json-tree.ts index dbc4ac0..fe19be5 100644 --- a/src/json-tree.ts +++ b/src/json-tree.ts @@ -1,4 +1,4 @@ -import type { SecretMasker } from './secret-mask'; +import { isLikelySecretKey, REDACTED, type SecretMasker } from './secret-mask'; export function renderJsonTree(json: string, maskValue?: SecretMasker): string { try { @@ -10,7 +10,11 @@ export function renderJsonTree(json: string, maskValue?: SecretMasker): string { } function renderNode(value: unknown, key: string, isRoot = false, maskValue?: SecretMasker): string { - const keyHtml = key && !isRoot ? `${escapeHtml(key)}: ` : ''; + const keyHtml = !isRoot ? `${escapeHtml(key)}: ` : ''; + + if (maskValue && isLikelySecretKey(key)) { + return `
    ${keyHtml}${REDACTED}
    `; + } if (value === null) return `
    ${keyHtml}null
    `; if (typeof value === 'boolean') return `
    ${keyHtml}${value}
    `; diff --git a/src/jsonl-viewer.ts b/src/jsonl-viewer.ts index 505eba0..db10909 100644 --- a/src/jsonl-viewer.ts +++ b/src/jsonl-viewer.ts @@ -1,20 +1,23 @@ import type { SecretMasker } from './secret-mask'; export function renderJsonlTable(content: string, path: string, maskValue?: SecretMasker): string { - const lines = content.split('\n').filter((l) => l.trim() !== ''); + const lines = content.split('\n'); - if (!lines.length) { + if (!content.trim()) { return `

    No data found in ${esc(path)}

    `; } const rows: Record[] = []; const parseErrors: number[] = []; + const rowLines: number[] = []; lines.forEach((line, i) => { + if (!line.trim()) return; try { const obj = JSON.parse(line); if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) { rows.push(obj as Record); + rowLines.push(i + 1); } else { parseErrors.push(i + 1); } @@ -56,7 +59,7 @@ export function renderJsonlTable(content: string, path: string, maskValue?: Secr .map((row, i) => { const tds = fields .map((f) => { - const val = row[f]; + const val = Object.hasOwn(row, f) ? row[f] : undefined; const cell = val === undefined || val === null ? '' @@ -66,9 +69,8 @@ export function renderJsonlTable(content: string, path: string, maskValue?: Secr return `
    `; }) .join(''); - // `data-line` (1-based table row number) lets the shared line-jump - // machinery (URL `&line=N` + the row-jump input) target this row. - return `${tds}`; + // Keep source line numbers even when blank or invalid lines were skipped. + return `${tds}`; }) .join(''); @@ -77,7 +79,7 @@ export function renderJsonlTable(content: string, path: string, maskValue?: Secr ${rows.length} rows × ${fields.length} columns diff --git a/src/locator.ts b/src/locator.ts index bb9a53d..2dfe215 100644 --- a/src/locator.ts +++ b/src/locator.ts @@ -54,6 +54,10 @@ function parseHashFragment(hash: string): LocatorResult { } } } + if (line !== null && (!Number.isSafeInteger(line) || line < 1 || (lineEnd !== null && (!Number.isSafeInteger(lineEnd) || lineEnd < 1)))) { + line = null; + lineEnd = null; + } return { kind: 'local', path: normalizePath(path), line, lineEnd }; } diff --git a/src/log-viewer.ts b/src/log-viewer.ts index 3e9b2d9..e4be565 100644 --- a/src/log-viewer.ts +++ b/src/log-viewer.ts @@ -51,7 +51,7 @@ function parseRequest(req: string): { method: string; path: string; protocol: st } export function detectLogFormat(content: string): LogFormat { - const firstLines = content.split('\n').filter((l) => l.trim()).slice(0, 10); + const firstLines = content.split(/\r?\n/).filter((l) => l.trim()).slice(0, 10); let laravelHits = 0; for (const line of firstLines) { if (COMBINED_RE.test(line)) return 'combined'; @@ -118,7 +118,7 @@ interface LaravelEntry { } function parseLaravel(content: string): LaravelEntry[] { - const lines = content.split('\n'); + const lines = content.split(/\r?\n/); const entries: LaravelEntry[] = []; let current: LaravelEntry | null = null; const bodyParts: string[] = []; diff --git a/src/main.ts b/src/main.ts index 4a06ffc..ed930c9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,9 +5,9 @@ import { FileTree, initSidebarResize } from './filetree'; import { TableOfContents } from './toc'; import { SearchModal } from './search'; import { renderJsonTree } from './json-tree'; -import { renderYamlTree } from './yaml-tree'; +import { renderYamlTree, maskYamlSecrets } from './yaml-tree'; import { TabBar, addRecent, getRecent } from './tabs'; -import { renderCsvTable, initCsvSort, initCsvColumnCopy } from './csv-viewer'; +import { renderCsvTable, maskCsvSecrets, initCsvSort, initCsvColumnCopy } from './csv-viewer'; import { renderJsonlTable } from './jsonl-viewer'; import { renderHtmlView, initHtmlScriptsToggle, initHtmlScreenshotToggle, captureHtmlFullPage } from './html-viewer'; import { renderLogTable, initLaravelSort } from './log-viewer'; @@ -41,6 +41,15 @@ const exportMode = new URLSearchParams(location.search).has('export'); if (exportMode) document.documentElement.classList.add('export-mode'); let currentFilePath: string | null = null; +let leftLoadSeq = 0; +let rightLoadSeq = 0; +let disposeCurrentAlbum: (() => void) | null = null; + +function isCurrentPaneLoad(pane: PaneId, seq: number, target: HTMLElement): boolean { + return pane === 'left' + ? seq === leftLoadSeq && target === viewer + : seq === rightLoadSeq && target === splitViewer && splitActive; +} let sidebarVisible = false; let tocVisible = localStorage.getItem('docview.tocVisible') !== 'false'; let wordWrap = false; // (#7) @@ -570,6 +579,10 @@ function parseHash(hash: string = location.hash): ParsedHash { } } } + if (line !== null && (!Number.isSafeInteger(line) || line < 1 || (lineEnd !== null && (!Number.isSafeInteger(lineEnd) || lineEnd < 1)))) { + line = null; + lineEnd = null; + } return { path, line, lineEnd, albumPath: null, albumRecursive: false, comparePaths: null }; } @@ -603,7 +616,7 @@ function updateHash(path: string | null, line?: number | null, lineEnd?: number if (path) { history.replaceState(null, '', buildHash(path, line, lineEnd)); } else { - history.replaceState(null, '', location.pathname); + history.replaceState(null, '', location.pathname + location.search); } } @@ -612,13 +625,14 @@ function openFileLocation(path: string, line: number | null = null, lineEnd: num if (line != null) { setPendingLineJump('right', { line, lineEnd }); if (path === splitFilePath) { - scrollToLine(line, lineEnd, splitViewer, 'right'); + if (scrollToLine(line, lineEnd, splitViewer, 'right')) setPendingLineJump('right', null); return; } void loadIntoSplit(path); return; } + setPendingLineJump('right', null); if (path !== splitFilePath) void loadIntoSplit(path); return; } @@ -628,7 +642,7 @@ function openFileLocation(path: string, line: number | null = null, lineEnd: num updateHash(path, line, lineEnd); if (path === currentFilePath) { - scrollToLine(line, lineEnd, viewer, 'left'); + if (scrollToLine(line, lineEnd, viewer, 'left')) setPendingLineJump('left', null); return; } @@ -636,6 +650,7 @@ function openFileLocation(path: string, line: number | null = null, lineEnd: num return; } + setPendingLineJump('left', null); updateHash(path, null, null); if (path !== currentFilePath) void loadServerFile(path); } @@ -651,13 +666,10 @@ function clearLineHighlights(target: HTMLElement = viewer) { function highlightLines(start: number, end: number | null, target: HTMLElement = viewer) { clearLineHighlights(target); const last = end ?? start; - for (let n = start; n <= last; n++) { - target.querySelectorAll(`[data-line="${n}"]`).forEach((el) => { - if (el.classList.contains('line-row') || el.tagName === 'TR') { - el.classList.add('line-highlighted'); - } - }); - } + target.querySelectorAll('.line-row[data-line], tr[data-line]').forEach((el) => { + const line = Number(el.dataset.line); + if (line >= start && line <= last) el.classList.add('line-highlighted'); + }); } function scrollToLine(line: number, lineEnd: number | null, target: HTMLElement = viewer, pane: PaneId = 'left') { @@ -813,28 +825,59 @@ function bindLineInteractions(target: HTMLElement, pane: PaneId) { // Delegated line-number click handler on the viewer. bindLineInteractions(viewer, 'left'); +// Resolve URI-encoded Markdown resources against the current document directory. +function resolveDocumentResource(href: string, currentPath: string): { path: string; heading: string } | null { + if (/^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(href)) return null; + try { + const base = currentPath.split('/').map(encodeURIComponent).join('/'); + const url = new URL(href, `https://docview.invalid/${base}`); + return { path: decodeURIComponent(url.pathname.slice(1)), heading: decodeURIComponent(url.hash.slice(1)) }; + } catch { return null; } +} + +const pendingHeadings = new Map(); + // --- Relative link navigation (#10) --- function interceptRelativeLinks(currentPath: string, target: HTMLElement = viewer, pane: PaneId = 'left') { target.querySelectorAll('a[href]').forEach((a) => { const href = a.getAttribute('href'); - if (!href || href.startsWith('http') || href.startsWith('#')) return; - // Relative link to another file + if (!href) return; + if (href.startsWith('#')) { + // Shared DocView links are application routes, handled by hashchange. + const params = new URLSearchParams(href.slice(1)); + if (params.has('file') || params.has('album') || params.has('compare')) return; + a.addEventListener('click', (e) => { + if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; + e.preventDefault(); + if (href === '#') { target.scrollTop = 0; return; } + try { target.querySelector(`#${CSS.escape(decodeURIComponent(href.slice(1)))}`)?.scrollIntoView({ block: 'start' }); } catch { /* ignore malformed fragments */ } + }); + return; + } + if (/^https?:\/\//i.test(currentPath)) { + try { a.href = new URL(href, currentPath).href; } catch { /* leave invalid links unchanged */ } + return; + } + const resource = resolveDocumentResource(href, currentPath); + if (!resource) return; a.addEventListener('click', (e) => { + if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return; e.preventDefault(); - let targetPath = href; - if (!href.startsWith('/')) { - const dir = currentPath.includes('/') ? currentPath.replace(/\/[^/]+$/, '/') : ''; - targetPath = dir + href; + const previousPath = getPanePath(pane); + pendingHeadings.delete(pane); + openFileLocation(resource.path, null, null, pane); + if (resource.heading) { + const heading = previousPath === resource.path + ? target.querySelector(`#${CSS.escape(resource.heading)}`) : null; + if (heading) heading.scrollIntoView({ block: 'start' }); + else pendingHeadings.set(pane, { ...resource, seq: pane === 'left' ? leftLoadSeq : rightLoadSeq }); } - // Normalize path (remove ./) - targetPath = targetPath.replace(/^\.\//, ''); - openFileLocation(targetPath, null, null, pane); }); }); } // --- Rendering --- -function renderContent(content: string, path: string, target: HTMLElement = viewer) { +function renderContent(content: string, path: string, target: HTMLElement = viewer, sourceUrl?: string) { const pane = getPaneIdForTarget(target) ?? 'left'; // Replacing the viewer's innerHTML below detaches any nodes the find bar // holds Ranges into, leaving it pointing at stale content. Close it first. @@ -862,12 +905,12 @@ function renderContent(content: string, path: string, target: HTMLElement = view initToggleButtons(target); renderMermaidDiagrams(target); renderExternalDiagrams(target); - fixRelativeImages(path, target); + fixRelativeImages(sourceUrl ?? path, target); if (target === viewer) { toc.update(); toc.loadBacklinks(path); } - interceptRelativeLinks(path, target, pane); + interceptRelativeLinks(sourceUrl ?? path, target, pane); addHeadingCopyButtons(target, path); if (target === viewer) refreshSlidesButton(displayContent); break; @@ -912,7 +955,7 @@ function renderContent(content: string, path: string, target: HTMLElement = view } else if (path.endsWith('.yaml') || path.endsWith('.yml')) { const treeHtml = renderYamlTree(content, secretSafe ? maskSecretValue : undefined); if (treeHtml) { - const highlighted = hljs.highlight(displayContent, { language: 'yaml' }).value; + const highlighted = hljs.highlight(secretSafe ? maskYamlSecrets(content) : content, { language: 'yaml' }).value; target.innerHTML = `
    @@ -934,7 +977,7 @@ function renderContent(content: string, path: string, target: HTMLElement = view case 'csv': { const tableHtml = renderCsvTable(content, path, secretSafe ? maskSecretValue : undefined); const ext = path.split('.').pop()?.toUpperCase() || 'CSV'; - const escaped = escapeHtml(displayContent); + const escaped = escapeHtml(secretSafe ? maskCsvSecrets(content) : content); target.innerHTML = `
    @@ -1002,7 +1045,7 @@ function renderContent(content: string, path: string, target: HTMLElement = view const htmlSource = hljs.getLanguage('xml') ? hljs.highlight(displayContent, { language: 'xml' }).value : escapeHtml(displayContent); - target.innerHTML = renderHtmlView(displayContent, htmlExt, htmlSource, path); + target.innerHTML = renderHtmlView(displayContent, htmlExt, htmlSource, sourceUrl ?? path); initToggleButtons(target); if (target === viewer) toc.clear(); break; @@ -1022,10 +1065,18 @@ function renderContent(content: string, path: string, target: HTMLElement = view break; default: - target.innerHTML = `
    ${escapeHtml(content)}
    `; + target.innerHTML = `
    ${escapeHtml(displayContent)}
    `; if (target === viewer) toc.clear(); } + const heading = pendingHeadings.get(pane); + const hasPendingHeading = heading?.path === path && isCurrentPaneLoad(pane, heading.seq, target); + if (hasPendingHeading) { + pendingHeadings.delete(pane); + requestAnimationFrame(() => { + if (isCurrentPaneLoad(pane, heading.seq, target)) target.querySelector(`#${CSS.escape(heading.heading)}`)?.scrollIntoView({ block: 'start' }); + }); + } addCopyButtons(target); addCollapseButtons(target); initImageZoom(target); @@ -1035,7 +1086,7 @@ function renderContent(content: string, path: string, target: HTMLElement = view setPendingLineJump(pane, null); scrollToLine(line, lineEnd, target, pane); } else { - restoreScrollPosition(path, pane); + if (!hasPendingHeading) restoreScrollPosition(path, pane); } } @@ -1077,6 +1128,7 @@ function officeKind(path: string): 'Excel' | 'PowerPoint' | 'Numbers' | 'Pages' async function renderOfficeUnsupported(path: string, target: HTMLElement = viewer, options: { localFile?: File; remote?: boolean } = {}) { const pane = getPaneIdForTarget(target) ?? 'left'; + const seq = pane === 'left' ? leftLoadSeq : rightLoadSeq; const kind = officeKind(path); const ext = getExt(path).replace('.', '').toUpperCase(); let sizeText = ''; @@ -1097,6 +1149,7 @@ async function renderOfficeUnsupported(path: string, target: HTMLElement = viewe } catch { /* ignore */ } } + if (!isCurrentPaneLoad(pane, seq, target)) return; if (target === viewer) updateBreadcrumb(path, mtime); const canOpenInApp = !options.remote && !options.localFile; @@ -1140,6 +1193,7 @@ async function renderOfficeUnsupported(path: string, target: HTMLElement = viewe // drag-and-dropped files are shown from a blob: URL (CSP frame-src allows it). async function renderPdf(path: string, target: HTMLElement = viewer, options: { src?: string; localFile?: File; remote?: boolean } = {}) { const pane = getPaneIdForTarget(target) ?? 'left'; + const seq = pane === 'left' ? leftLoadSeq : rightLoadSeq; const isServerFile = !options.remote && !options.localFile; const src = options.src ?? `/api/file?path=${encodeURIComponent(path)}`; const fileName = path.split('/').pop() || path; @@ -1147,10 +1201,12 @@ async function renderPdf(path: string, target: HTMLElement = viewer, options: { if (target === viewer && isServerFile) { try { const headRes = await fetch(src, { method: 'HEAD' }); + if (!isCurrentPaneLoad(pane, seq, target)) return; updateBreadcrumb(path, headRes.headers.get('X-File-Mtime')); } catch { /* ignore */ } } + if (!isCurrentPaneLoad(pane, seq, target)) return; const actions = [ `新しいタブで開く`, isServerFile ? '' : '', @@ -1173,11 +1229,11 @@ async function renderPdf(path: string, target: HTMLElement = viewer, options: { setPendingLineJump(pane, null); } -async function renderVideo(path: string) { - const url = `/api/file?path=${encodeURIComponent(path)}`; +async function renderVideo(path: string, target: HTMLElement = viewer, src?: string) { + const url = src ?? `/api/file?path=${encodeURIComponent(path)}`; // Single-file mode: just show a controlled
    ${cell}
    ${i + 1}
    ${rowLines[i]}