From cd24af139fe61f23bac4226dac8c8eaa66b92410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=97=A5=E5=A4=A9?= Date: Thu, 6 Aug 2026 00:05:19 +0800 Subject: [PATCH 1/5] feat(release): add TNMSO and bump to 2026.10805.0 --- .githooks/sync-versions.test.ts | 59 +- .githooks/sync-versions.ts | 55 +- .github/actions/setup-bun/action.yml | 31 + .github/workflows/ci.yml | 98 +- .github/workflows/release.yml | 108 ++- Cargo.lock | 14 +- Cargo.toml | 2 +- README.md | 9 +- cli/local-tests/tests/agents_md_smoke.rs | 7 +- cli/local-tests/tests/claude_smoke.rs | 7 +- cli/local-tests/tests/clean_blackbox.rs | 7 +- cli/local-tests/tests/codex_smoke.rs | 7 +- cli/local-tests/tests/install_smoke.rs | 7 +- cli/local-tests/tests/rules_source_smoke.rs | 7 +- cli/local-tests/tests/support/opencode.rs | 7 +- cli/local-tests/tests/trae_smoke.rs | 7 +- cli/npm/darwin-arm64/package.json | 2 +- cli/npm/darwin-x64/package.json | 2 +- cli/npm/linux-arm64-gnu/package.json | 2 +- cli/npm/linux-x64-gnu/package.json | 2 +- cli/npm/win32-x64-msvc/package.json | 2 +- cli/package.json | 12 +- doc/package.json | 2 +- gui/package.json | 2 +- gui/src-tauri/Cargo.toml | 2 +- gui/src-tauri/tauri.conf.json | 2 +- manifest.json | 10 + mcp/npm/darwin-arm64/package.json | 2 +- mcp/npm/darwin-x64/package.json | 2 +- mcp/npm/linux-arm64-gnu/package.json | 2 +- mcp/npm/linux-x64-gnu/package.json | 2 +- mcp/npm/win32-x64-msvc/package.json | 2 +- mcp/package.json | 12 +- obsidian-plugin/RELEASING.md | 11 + obsidian-plugin/bun.lock | 905 ++++++++++++++++++ obsidian-plugin/eslint.config.ts | 33 + obsidian-plugin/manifest.json | 10 + obsidian-plugin/package.json | 43 + obsidian-plugin/scripts/build.ts | 36 + obsidian-plugin/scripts/package-release.ts | 20 + obsidian-plugin/scripts/verify-dist.ts | 73 ++ obsidian-plugin/src/compiler/compiler.test.ts | 86 ++ obsidian-plugin/src/compiler/compiler.ts | 442 +++++++++ obsidian-plugin/src/compiler/types.ts | 16 + obsidian-plugin/src/main.ts | 189 ++++ .../src/preview/diagnostic-store.test.ts | 30 + .../src/preview/diagnostic-store.ts | 36 + obsidian-plugin/src/preview/processor.test.ts | 88 ++ obsidian-plugin/src/preview/processor.ts | 46 + .../src/preview/prompt-metadata-cache.test.ts | 55 ++ .../src/preview/prompt-metadata-cache.ts | 58 ++ obsidian-plugin/src/settings-tab.ts | 44 + obsidian-plugin/src/settings.test.ts | 26 + obsidian-plugin/src/settings.ts | 42 + obsidian-plugin/styles.css | 39 + obsidian-plugin/tsconfig.json | 21 + obsidian-plugin/versions.json | 4 + package.json | 4 +- scripts/shared/check-version-surfaces.ts | 19 +- .../output_plans/claude_code_output_plan.rs | 3 +- sdk/src/domain/output_plans/mod.rs | 19 +- .../domain/output_plans/warp_output_plan.rs | 16 +- sdk/src/infra/git_fs.rs | 38 +- sdk/src/infra/md_compiler/expression_eval.rs | 4 +- sdk/src/repositories/project_prompt.rs | 5 +- sdk/src/repositories/skill.rs | 68 +- sdk/src/services/clean_service.rs | 26 +- sdk/src/services/dry_run_service.rs | 2 +- sdk/src/services/install_service.rs | 2 +- sdk/src/services/output_plan.rs | 8 +- versions.json | 4 + xtask/src/main.rs | 2 +- 72 files changed, 2922 insertions(+), 145 deletions(-) create mode 100644 .github/actions/setup-bun/action.yml create mode 100644 manifest.json create mode 100644 obsidian-plugin/RELEASING.md create mode 100644 obsidian-plugin/bun.lock create mode 100644 obsidian-plugin/eslint.config.ts create mode 100644 obsidian-plugin/manifest.json create mode 100644 obsidian-plugin/package.json create mode 100644 obsidian-plugin/scripts/build.ts create mode 100644 obsidian-plugin/scripts/package-release.ts create mode 100644 obsidian-plugin/scripts/verify-dist.ts create mode 100644 obsidian-plugin/src/compiler/compiler.test.ts create mode 100644 obsidian-plugin/src/compiler/compiler.ts create mode 100644 obsidian-plugin/src/compiler/types.ts create mode 100644 obsidian-plugin/src/main.ts create mode 100644 obsidian-plugin/src/preview/diagnostic-store.test.ts create mode 100644 obsidian-plugin/src/preview/diagnostic-store.ts create mode 100644 obsidian-plugin/src/preview/processor.test.ts create mode 100644 obsidian-plugin/src/preview/processor.ts create mode 100644 obsidian-plugin/src/preview/prompt-metadata-cache.test.ts create mode 100644 obsidian-plugin/src/preview/prompt-metadata-cache.ts create mode 100644 obsidian-plugin/src/settings-tab.ts create mode 100644 obsidian-plugin/src/settings.test.ts create mode 100644 obsidian-plugin/src/settings.ts create mode 100644 obsidian-plugin/styles.css create mode 100644 obsidian-plugin/tsconfig.json create mode 100644 obsidian-plugin/versions.json create mode 100644 versions.json diff --git a/.githooks/sync-versions.test.ts b/.githooks/sync-versions.test.ts index 505ad446..2b1b5a83 100644 --- a/.githooks/sync-versions.test.ts +++ b/.githooks/sync-versions.test.ts @@ -2,7 +2,7 @@ import {execFileSync} from 'node:child_process' import {mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync} from 'node:fs' import {tmpdir} from 'node:os' import {dirname, join} from 'node:path' -import {afterEach, describe, expect, it} from 'vitest' +import {afterEach, describe, expect, it} from 'bun:test' import {runSyncVersions} from './sync-versions' function writeJson(filePath: string, value: Record): void { @@ -56,6 +56,22 @@ function createFixtureRepo(): string { version: initialVersion, private: true }) + writeJson(join(rootDir, 'obsidian-plugin', 'package.json'), { + name: 'tnmso', + version: initialVersion, + private: true + }) + const manifest = { + id: 'tnmso', + name: 'TNMSO', + version: initialVersion, + minAppVersion: '1.0.0', + isDesktopOnly: false + } + writeJson(join(rootDir, 'obsidian-plugin', 'manifest.json'), manifest) + writeJson(join(rootDir, 'manifest.json'), manifest) + writeJson(join(rootDir, 'obsidian-plugin', 'versions.json'), {[initialVersion]: '1.0.0'}) + writeJson(join(rootDir, 'versions.json'), {[initialVersion]: '1.0.0'}) writeJson(join(rootDir, 'cli', 'npm', 'darwin-arm64', 'package.json'), { name: '@truenine/memory-sync-cli-darwin-arm64', version: initialVersion @@ -149,6 +165,14 @@ function expectSharedVersionSurfaces(rootDir: string, nextVersion: string): void }) expect(JSON.parse(readFileSync(join(rootDir, 'gui', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) expect(JSON.parse(readFileSync(join(rootDir, 'doc', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) + expect(JSON.parse(readFileSync(join(rootDir, 'obsidian-plugin', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) + const pluginManifest = JSON.parse(readFileSync(join(rootDir, 'obsidian-plugin', 'manifest.json'), 'utf-8')) as {version: string, minAppVersion: string} + expect(pluginManifest).toMatchObject({version: nextVersion, minAppVersion: '1.0.0'}) + expect(JSON.parse(readFileSync(join(rootDir, 'manifest.json'), 'utf-8'))).toEqual(pluginManifest) + expect(JSON.parse(readFileSync(join(rootDir, 'obsidian-plugin', 'versions.json'), 'utf-8'))).toMatchObject({[nextVersion]: '1.0.0'}) + expect(JSON.parse(readFileSync(join(rootDir, 'versions.json'), 'utf-8'))).toEqual( + JSON.parse(readFileSync(join(rootDir, 'obsidian-plugin', 'versions.json'), 'utf-8')) + ) expect(JSON.parse(readFileSync(join(rootDir, 'cli', 'npm', 'darwin-arm64', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) expect(JSON.parse(readFileSync(join(rootDir, 'cli', 'npm', 'linux-x64-gnu', 'package.json'), 'utf-8')) as {version: string}).toMatchObject({version: nextVersion}) expect(readFileSync(join(rootDir, 'Cargo.toml'), 'utf-8')).toContain(`version = "${nextVersion}"`) @@ -197,7 +221,12 @@ describe('sync-versions hook', () => { 'gui/src-tauri/Cargo.toml', 'gui/src-tauri/tauri.conf.json', 'mcp/package.json', - 'package.json' + 'manifest.json', + 'obsidian-plugin/manifest.json', + 'obsidian-plugin/package.json', + 'obsidian-plugin/versions.json', + 'package.json', + 'versions.json' ])) }) @@ -229,7 +258,12 @@ describe('sync-versions hook', () => { 'gui/src-tauri/Cargo.toml', 'gui/src-tauri/tauri.conf.json', 'mcp/package.json', - 'package.json' + 'manifest.json', + 'obsidian-plugin/manifest.json', + 'obsidian-plugin/package.json', + 'obsidian-plugin/versions.json', + 'package.json', + 'versions.json' ])) }) @@ -252,6 +286,25 @@ describe('sync-versions hook', () => { expectSharedVersionSurfaces(rootDir, nextVersion) }) + it('accepts the TNMSO package version as the staged system version source', () => { + const rootDir = createFixtureRepo() + tempDirs.push(rootDir) + + const nextVersion = '2026.10324.10319' + writeJson(join(rootDir, 'obsidian-plugin', 'package.json'), { + name: 'tnmso', + version: nextVersion, + private: true + }) + runGit(rootDir, ['add', 'obsidian-plugin/package.json']) + + const result = runSyncVersions({rootDir}) + + expect(result.targetVersion).toBe(nextVersion) + expect(result.versionSource).toBe('obsidian-plugin/package.json') + expectSharedVersionSurfaces(rootDir, nextVersion) + }) + it('fails when staged package.json files propose conflicting versions', () => { const rootDir = createFixtureRepo() tempDirs.push(rootDir) diff --git a/.githooks/sync-versions.ts b/.githooks/sync-versions.ts index 7833eb41..43a623ab 100644 --- a/.githooks/sync-versions.ts +++ b/.githooks/sync-versions.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env tsx +#!/usr/bin/env bun /** * Version Sync Script * Auto-sync all publishable package versions before commit. @@ -45,6 +45,57 @@ function writeJsonFile(filePath: string, value: VersionedJson): void { writeFileSync(filePath, JSON.stringify(value, null, 2) + '\n', 'utf-8') } +function writeJsonFileIfChanged( + filePath: string, + value: VersionedJson, + changedPaths: Set, +): void { + let current: VersionedJson | undefined + try { + current = readJsonFile(filePath) + } catch { + current = undefined + } + + if (current != null && JSON.stringify(current) === JSON.stringify(value)) { + return + } + + writeJsonFile(filePath, value) + changedPaths.add(filePath) +} + +function syncObsidianReleaseMetadata( + rootDir: string, + targetVersion: string, + changedPaths: Set, +): void { + const pluginManifestPath = resolve(rootDir, 'obsidian-plugin', 'manifest.json') + const rootManifestPath = resolve(rootDir, 'manifest.json') + const pluginVersionsPath = resolve(rootDir, 'obsidian-plugin', 'versions.json') + const rootVersionsPath = resolve(rootDir, 'versions.json') + const manifest = readJsonFile(pluginManifestPath) + const minAppVersion = manifest.minAppVersion + + if (manifest.id !== 'tnmso' || typeof minAppVersion !== 'string' || minAppVersion.trim() === '') { + throw new Error('TNMSO manifest must define id=tnmso and a non-empty minAppVersion') + } + + const updatedManifest = {...manifest, version: targetVersion} + writeJsonFileIfChanged(pluginManifestPath, updatedManifest, changedPaths) + writeJsonFileIfChanged(rootManifestPath, updatedManifest, changedPaths) + + let versions: VersionedJson + try { + versions = readJsonFile(pluginVersionsPath) + } catch { + versions = {} + } + const updatedVersions = {...versions, [targetVersion]: minAppVersion} + writeJsonFileIfChanged(pluginVersionsPath, updatedVersions, changedPaths) + writeJsonFileIfChanged(rootVersionsPath, updatedVersions, changedPaths) +} + function discoverFilesByName(baseDir: string, fileName: string): string[] { const found: string[] = [] const entries = readdirSync(baseDir, {withFileTypes: true}) @@ -469,6 +520,8 @@ export function runSyncVersions(options: SyncVersionsOptions = {}): SyncVersions syncJsonVersion(filePath, target.version, changedPaths) } + syncObsidianReleaseMetadata(rootDir, target.version, changedPaths) + stageFiles(rootDir, [...changedPaths].sort()) return { diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml new file mode 100644 index 00000000..5a026536 --- /dev/null +++ b/.github/actions/setup-bun/action.yml @@ -0,0 +1,31 @@ +name: Setup Bun +description: Setup the pinned Bun runtime and optionally install TNMSO dependencies + +inputs: + bun-version: + description: Bun version + required: false + default: "1.3.14" + install: + description: Whether to install dependencies + required: false + default: "true" + working-directory: + description: Directory containing bun.lock + required: false + default: obsidian-plugin + +runs: + using: composite + steps: + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: ${{ inputs.bun-version }} + + - name: Install Bun dependencies + if: inputs.install == 'true' + shell: bash + run: bun install --frozen-lockfile --cwd "$BUN_WORKING_DIRECTORY" + env: + BUN_WORKING_DIRECTORY: ${{ inputs.working-directory }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5eaa0c6c..2155e247 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,7 @@ jobs: outputs: docs: ${{ steps.filter.outputs.docs }} gui: ${{ steps.filter.outputs.gui }} + obsidian: ${{ steps.filter.outputs.obsidian }} steps: - uses: actions/checkout@v6 @@ -50,6 +51,37 @@ jobs: - 'pnpm-lock.yaml' - 'pnpm-workspace.yaml' - 'xtask/**' + obsidian: + - 'obsidian-plugin/**' + - 'manifest.json' + - 'versions.json' + - '.githooks/sync-versions.ts' + - '.githooks/sync-versions.test.ts' + - 'scripts/shared/check-version-surfaces.ts' + - '.github/actions/setup-bun/action.yml' + - '.github/workflows/ci.yml' + - '.github/workflows/release.yml' + - 'package.json' + + version-surfaces: + if: github.event_name != 'pull_request' || github.event.pull_request.draft == false + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v6 + + - uses: ./.github/actions/setup-bun + with: + install: "false" + + - name: Test version synchronization + run: bun test ./.githooks/sync-versions.test.ts + + - name: Validate current version surfaces + shell: bash + run: | + version="$(bun -e 'console.log(require("./package.json").version)')" + bun scripts/shared/check-version-surfaces.ts "$version" validate-monorepo: if: github.event_name != 'pull_request' || github.event.pull_request.draft == false @@ -93,10 +125,41 @@ jobs: run: cargo build --release -p tnmsc -p tnmsm - name: CLI packaging smoke - run: cargo test -p tnmsc-local-tests packaging_smoke_covers_release_binary_and_global_install -- --exact --nocapture + shell: bash + run: | + set -euo pipefail + target/release/tnmsc assemble-npm --profile release + + pack_dir="$(mktemp -d)" + prefix_dir="$(mktemp -d)" + trap 'rm -rf "$pack_dir" "$prefix_dir"' EXIT + pnpm -C cli/npm/linux-x64-gnu pack --pack-destination "$pack_dir" + pnpm -C cli pack --pack-destination "$pack_dir" + + platform_tarballs=("$pack_dir"/truenine-memory-sync-cli-linux-x64-gnu-*.tgz) + main_tarballs=("$pack_dir"/truenine-memory-sync-cli-[0-9]*.tgz) + npm install --global --prefix "$prefix_dir" "${platform_tarballs[0]}" "${main_tarballs[0]}" --ignore-scripts + "$prefix_dir/bin/tnmsc" help >"$pack_dir/tnmsc-help.txt" + grep -q 'install' "$pack_dir/tnmsc-help.txt" - name: MCP packaging smoke - run: cargo test -p tnmsm-local-tests packaging_smoke_covers_release_binary_and_global_install -- --exact --nocapture + shell: bash + run: | + set -euo pipefail + target/release/tnmsm assemble-npm --profile release + + pack_dir="$(mktemp -d)" + prefix_dir="$(mktemp -d)" + trap 'rm -rf "$pack_dir" "$prefix_dir"' EXIT + pnpm -C mcp/npm/linux-x64-gnu pack --pack-destination "$pack_dir" + pnpm -C mcp pack --pack-destination "$pack_dir" + + platform_tarballs=("$pack_dir"/truenine-memory-sync-mcp-linux-x64-gnu-*.tgz) + main_tarballs=("$pack_dir"/truenine-memory-sync-mcp-[0-9]*.tgz) + npm install --global --prefix "$prefix_dir" "${platform_tarballs[0]}" "${main_tarballs[0]}" --ignore-scripts + printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \ + | "$prefix_dir/bin/tnmsm" >"$pack_dir/tnmsm-initialize.json" + grep -q '"jsonrpc":"2.0"' "$pack_dir/tnmsm-initialize.json" gui-smoke: needs: changes @@ -151,3 +214,34 @@ jobs: - name: Build docs run: pnpm -C doc run build + + obsidian-plugin-check: + needs: changes + if: | + (github.event_name != 'pull_request' || github.event.pull_request.draft == false) && + needs.changes.outputs.obsidian == 'true' + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v6 + + - uses: ./.github/actions/setup-bun + + - name: Test TNMSO + run: bun test + working-directory: obsidian-plugin + + - name: Typecheck TNMSO + run: bun run check:type + working-directory: obsidian-plugin + + - name: Lint TNMSO + run: bun run lint + working-directory: obsidian-plugin + + - name: Build and package TNMSO + run: | + bun run build + bun run package:release + bun run verify:dist + working-directory: obsidian-plugin diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b6de7fe0..9648f009 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,6 +35,10 @@ jobs: cache: "false" install: "true" + - uses: ./.github/actions/setup-bun + with: + install: "false" + - name: Resolve release version id: release-version shell: bash @@ -55,7 +59,22 @@ jobs: echo "version=$version" >> "$GITHUB_OUTPUT" - name: Validate version surfaces - run: pnpm exec tsx scripts/shared/check-version-surfaces.ts "${{ steps.release-version.outputs.version }}" + run: bun scripts/shared/check-version-surfaces.ts "${{ steps.release-version.outputs.version }}" + + - name: Validate existing release tag targets + shell: bash + run: | + set -euo pipefail + git fetch --force --tags + for tag in "v${{ steps.release-version.outputs.version }}" "${{ steps.release-version.outputs.version }}"; do + if git rev-parse --verify --quiet "refs/tags/${tag}" >/dev/null; then + tag_commit="$(git rev-list -n 1 "refs/tags/${tag}")" + if [[ "$tag_commit" != "${GITHUB_SHA}" ]]; then + echo "::error::Existing tag ${tag} points to ${tag_commit}, expected ${GITHUB_SHA}." + exit 1 + fi + fi + done build-cli-binaries: needs: validate-version @@ -470,8 +489,38 @@ jobs: signing-private-key-password: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} version: ${{ needs.validate-version.outputs.version }} + build-obsidian-plugin: + needs: validate-version + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - uses: actions/checkout@v6 + + - uses: ./.github/actions/setup-bun + + - name: Test and validate TNMSO + working-directory: obsidian-plugin + run: | + bun test + bun run check:type + bun run lint + + - name: Build and package TNMSO + working-directory: obsidian-plugin + run: | + bun run build + bun run package:release + bun run verify:dist + + - name: Upload TNMSO release artifact + uses: actions/upload-artifact@v7 + with: + name: obsidian-plugin-release + path: obsidian-plugin/dist/ + if-no-files-found: error + create-github-release: - needs: [validate-version, build-cli-binaries, publish-cli-npm, build-mcp-binaries, publish-mcp-npm, build-gui] + needs: [validate-version, build-cli-binaries, publish-cli-npm, build-mcp-binaries, publish-mcp-npm, build-gui, build-obsidian-plugin] runs-on: ubuntu-24.04 timeout-minutes: 20 steps: @@ -496,6 +545,12 @@ jobs: pattern: mcp-archive-* merge-multiple: true + - name: Download TNMSO artifacts + uses: actions/download-artifact@v8 + with: + name: obsidian-plugin-release + path: artifacts/obsidian + - name: Clean up unnecessary macOS artifacts shell: bash run: | @@ -511,6 +566,7 @@ jobs: updater_count=$(find artifacts/gui -type f \( -name '*.sig' -o -name '*.tar.gz' -o -name '*.zip' \) | wc -l | tr -d ' ') cli_archive_count=$(find artifacts/cli -type f \( -name '*.tar.gz' -o -name '*.zip' \) | wc -l | tr -d ' ') mcp_archive_count=$(find artifacts/mcp -type f \( -name '*.tar.gz' -o -name '*.zip' \) | wc -l | tr -d ' ') + obsidian_archive_count=$(find artifacts/obsidian -maxdepth 1 -type f -name 'tnmso-${{ needs.validate-version.outputs.version }}.zip' | wc -l | tr -d ' ') if [[ "$installer_count" -eq 0 ]]; then echo "::error::No GUI installer artifacts were downloaded." @@ -532,10 +588,16 @@ jobs: exit 1 fi + if [[ "$obsidian_archive_count" -ne 1 ]]; then + echo "::error::Expected one TNMSO archive, found ${obsidian_archive_count}." + exit 1 + fi + - name: Publish GitHub release uses: softprops/action-gh-release@v3.0.0 with: tag_name: v${{ needs.validate-version.outputs.version }} + target_commitish: ${{ github.sha }} name: v${{ needs.validate-version.outputs.version }} files: | artifacts/gui/**/*.dmg @@ -551,5 +613,47 @@ jobs: artifacts/cli/**/*.zip artifacts/mcp/**/*.tar.gz artifacts/mcp/**/*.zip + artifacts/obsidian/tnmso-*.zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + create-obsidian-release: + needs: [validate-version, build-obsidian-plugin] + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - name: Download TNMSO artifacts + uses: actions/download-artifact@v8 + with: + name: obsidian-plugin-release + path: artifacts/obsidian + + - name: Verify Obsidian release files + shell: bash + run: | + set -euo pipefail + for file in main.js manifest.json styles.css "tnmso-${{ needs.validate-version.outputs.version }}.zip"; do + test -f "artifacts/obsidian/${file}" || { + echo "::error::Missing TNMSO release file: ${file}" + exit 1 + } + done + + - name: Publish Obsidian release + uses: softprops/action-gh-release@v3.0.0 + with: + tag_name: ${{ needs.validate-version.outputs.version }} + target_commitish: ${{ github.sha }} + name: TNMSO ${{ needs.validate-version.outputs.version }} + body: | + TNMSO safely previews prompt-focused MDX files as Markdown in Obsidian without evaluating JavaScript. + + Install `main.js`, `manifest.json`, and `styles.css` in `/.obsidian/plugins/tnmso/`, then reload Obsidian and enable TNMSO. + fail_on_unmatched_files: true + files: | + artifacts/obsidian/main.js + artifacts/obsidian/manifest.json + artifacts/obsidian/styles.css + artifacts/obsidian/tnmso-${{ needs.validate-version.outputs.version }}.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Cargo.lock b/Cargo.lock index 9447357d..f0d7053b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2835,7 +2835,7 @@ dependencies = [ [[package]] name = "memory-sync" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "tnmsc", ] @@ -5893,7 +5893,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tnmsc" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "clap", "serde_json", @@ -5902,7 +5902,7 @@ dependencies = [ [[package]] name = "tnmsc-local-tests" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "dirs", "json5", @@ -5911,7 +5911,7 @@ dependencies = [ [[package]] name = "tnmsd" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "base64 0.23.0", "chrono", @@ -5940,7 +5940,7 @@ dependencies = [ [[package]] name = "tnmsg" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "dirs", "proptest", @@ -5955,7 +5955,7 @@ dependencies = [ [[package]] name = "tnmsm" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "assert_cmd", "clap", @@ -7286,7 +7286,7 @@ dependencies = [ [[package]] name = "xtask" -version = "2026.10801.0" +version = "2026.10805.0" dependencies = [ "clap", "serde", diff --git a/Cargo.toml b/Cargo.toml index f2075b61..947f9013 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ members = [ ] [workspace.package] -version = "2026.10801.0" +version = "2026.10805.0" edition = "2024" rust-version = "1.88" license = "AGPL-3.0-only" diff --git a/README.md b/README.md index 62312c5b..02986d56 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ A rat carries even its own memories when moving. `memory-sync` is that kind of t - Auto-write configs for each tool: AGENTS.md, Claude Code, Codex CLI, Cursor, Windsurf, Qoder, Trae, Warp, JetBrains AI, etc. - Manage derived artifacts: prompt outputs, skills exports organized as `skills///`, README-class outputs - Multiple entry points: `tnmsc` CLI, private SDK, MCP stdio server, Tauri GUI +- Obsidian integration: TNMSO opens `.mdx` as native Markdown and safely previews static prompt syntax - Fine-grained write-scope control (`outputScopes`, `cleanupProtection`) - Source and derivations are auditable — no silent source mutations, no hidden residuals - Memories follow the person, not the project — no leakage @@ -26,6 +27,12 @@ MCP server: npm install -g @truenine/memory-sync-mcp ``` +### TNMSO for Obsidian + +TNMSO is the Obsidian plugin in [`obsidian-plugin/`](obsidian-plugin/README.md). Download `main.js`, `manifest.json`, and `styles.css` from the GitHub Release tagged with the exact CalVer version, then install them under `/.obsidian/plugins/tnmso/`. BRAT users can install `TrueNine/memory-sync` for beta testing. + +TNMSO shares the repository version. System releases use `v` tags; Obsidian releases use the matching plain `` tag because the community plugin updater requires the tag and manifest version to be identical. + ## Supported Tools | Type | Tools | @@ -68,4 +75,4 @@ If you're scraping by in a world of profoundly unequal resources — free tiers, - [zjarlin](https://github.com/zjarlin) ## License -[AGPL-3.0](LICENSE) \ No newline at end of file +[AGPL-3.0](LICENSE) diff --git a/cli/local-tests/tests/agents_md_smoke.rs b/cli/local-tests/tests/agents_md_smoke.rs index 961491d4..452396d5 100644 --- a/cli/local-tests/tests/agents_md_smoke.rs +++ b/cli/local-tests/tests/agents_md_smoke.rs @@ -93,7 +93,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/claude_smoke.rs b/cli/local-tests/tests/claude_smoke.rs index 6159f156..353e6f25 100644 --- a/cli/local-tests/tests/claude_smoke.rs +++ b/cli/local-tests/tests/claude_smoke.rs @@ -111,7 +111,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/clean_blackbox.rs b/cli/local-tests/tests/clean_blackbox.rs index fc7db17d..874b7d8c 100644 --- a/cli/local-tests/tests/clean_blackbox.rs +++ b/cli/local-tests/tests/clean_blackbox.rs @@ -102,7 +102,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/codex_smoke.rs b/cli/local-tests/tests/codex_smoke.rs index 4b71f0cc..ba2cf3fd 100644 --- a/cli/local-tests/tests/codex_smoke.rs +++ b/cli/local-tests/tests/codex_smoke.rs @@ -122,7 +122,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/install_smoke.rs b/cli/local-tests/tests/install_smoke.rs index e0319e58..5b0a76d5 100644 --- a/cli/local-tests/tests/install_smoke.rs +++ b/cli/local-tests/tests/install_smoke.rs @@ -100,7 +100,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/rules_source_smoke.rs b/cli/local-tests/tests/rules_source_smoke.rs index 75e6a71e..b26378e9 100644 --- a/cli/local-tests/tests/rules_source_smoke.rs +++ b/cli/local-tests/tests/rules_source_smoke.rs @@ -79,7 +79,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/support/opencode.rs b/cli/local-tests/tests/support/opencode.rs index 830a4554..836fa873 100644 --- a/cli/local-tests/tests/support/opencode.rs +++ b/cli/local-tests/tests/support/opencode.rs @@ -142,7 +142,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/local-tests/tests/trae_smoke.rs b/cli/local-tests/tests/trae_smoke.rs index 5743a5a8..c84b9672 100644 --- a/cli/local-tests/tests/trae_smoke.rs +++ b/cli/local-tests/tests/trae_smoke.rs @@ -104,7 +104,12 @@ fn init_git_repo(project_dir: &Path) { .arg("--quiet") .current_dir(project_dir) .output() - .unwrap_or_else(|error| panic!("failed to run git init in {}: {error}", project_dir.display())); + .unwrap_or_else(|error| { + panic!( + "failed to run git init in {}: {error}", + project_dir.display() + ) + }); assert!( output.status.success(), diff --git a/cli/npm/darwin-arm64/package.json b/cli/npm/darwin-arm64/package.json index e0bf677a..1337da3c 100644 --- a/cli/npm/darwin-arm64/package.json +++ b/cli/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-darwin-arm64", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsc native binary for macOS arm64", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/cli/npm/darwin-x64/package.json b/cli/npm/darwin-x64/package.json index a9a4b7e7..2c31f097 100644 --- a/cli/npm/darwin-x64/package.json +++ b/cli/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-darwin-x64", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsc native binary for macOS x64", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/cli/npm/linux-arm64-gnu/package.json b/cli/npm/linux-arm64-gnu/package.json index c9c70607..0bb2f61b 100644 --- a/cli/npm/linux-arm64-gnu/package.json +++ b/cli/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-linux-arm64-gnu", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsc native binary for Linux arm64 (glibc)", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/cli/npm/linux-x64-gnu/package.json b/cli/npm/linux-x64-gnu/package.json index 89b07e59..f1949660 100644 --- a/cli/npm/linux-x64-gnu/package.json +++ b/cli/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-linux-x64-gnu", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsc native binary for Linux x64 (glibc)", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/cli/npm/win32-x64-msvc/package.json b/cli/npm/win32-x64-msvc/package.json index 5483ab18..48459f51 100644 --- a/cli/npm/win32-x64-msvc/package.json +++ b/cli/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli-win32-x64-msvc", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsc native binary for Windows x64", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/cli/package.json b/cli/package.json index 871a90e8..41494e5f 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-cli", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "TrueNine Memory Synchronization CLI metadata package", "author": "TrueNine", "license": "AGPL-3.0-only", @@ -34,10 +34,10 @@ "test": "cargo test --manifest-path Cargo.toml" }, "optionalDependencies": { - "@truenine/memory-sync-cli-darwin-arm64": "2026.10801.0", - "@truenine/memory-sync-cli-darwin-x64": "2026.10801.0", - "@truenine/memory-sync-cli-linux-arm64-gnu": "2026.10801.0", - "@truenine/memory-sync-cli-linux-x64-gnu": "2026.10801.0", - "@truenine/memory-sync-cli-win32-x64-msvc": "2026.10801.0" + "@truenine/memory-sync-cli-darwin-arm64": "2026.10805.0", + "@truenine/memory-sync-cli-darwin-x64": "2026.10805.0", + "@truenine/memory-sync-cli-linux-arm64-gnu": "2026.10805.0", + "@truenine/memory-sync-cli-linux-x64-gnu": "2026.10805.0", + "@truenine/memory-sync-cli-win32-x64-msvc": "2026.10805.0" } } diff --git a/doc/package.json b/doc/package.json index 458bf84d..6485d257 100644 --- a/doc/package.json +++ b/doc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-docs", - "version": "2026.10801.0", + "version": "2026.10805.0", "private": true, "packageManager": "pnpm@11.18.0", "description": "Chinese-first manifesto-led documentation site for @truenine/memory-sync.", diff --git a/gui/package.json b/gui/package.json index d76caa27..dd2c8e71 100644 --- a/gui/package.json +++ b/gui/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-gui", - "version": "2026.10801.0", + "version": "2026.10805.0", "private": true, "engines": { "node": ">= 22" diff --git a/gui/src-tauri/Cargo.toml b/gui/src-tauri/Cargo.toml index 056642b2..ab605dd7 100644 --- a/gui/src-tauri/Cargo.toml +++ b/gui/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tnmsg" -version = "2026.10801.0" +version = "2026.10805.0" description = "Memory Sync desktop GUI application" authors.workspace = true edition.workspace = true diff --git a/gui/src-tauri/tauri.conf.json b/gui/src-tauri/tauri.conf.json index d0de1c67..b2858396 100644 --- a/gui/src-tauri/tauri.conf.json +++ b/gui/src-tauri/tauri.conf.json @@ -1,6 +1,6 @@ { "$schema": "https://schema.tauri.app/config/2", - "version": "2026.10801.0", + "version": "2026.10805.0", "productName": "Memory Sync", "identifier": "org.truenine.memory-sync", "build": { diff --git a/manifest.json b/manifest.json new file mode 100644 index 00000000..eefc3744 --- /dev/null +++ b/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "tnmso", + "name": "TNMSO", + "version": "2026.10805.0", + "minAppVersion": "1.13.4", + "description": "Preview prompt-focused MDX files safely as Markdown.", + "author": "TrueNine", + "authorUrl": "https://github.com/TrueNine", + "isDesktopOnly": false +} diff --git a/mcp/npm/darwin-arm64/package.json b/mcp/npm/darwin-arm64/package.json index 19d9e499..9eb7c0da 100644 --- a/mcp/npm/darwin-arm64/package.json +++ b/mcp/npm/darwin-arm64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-mcp-darwin-arm64", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsm native binary for macOS arm64", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/mcp/npm/darwin-x64/package.json b/mcp/npm/darwin-x64/package.json index e22b9b0b..035d38da 100644 --- a/mcp/npm/darwin-x64/package.json +++ b/mcp/npm/darwin-x64/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-mcp-darwin-x64", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsm native binary for macOS x64", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/mcp/npm/linux-arm64-gnu/package.json b/mcp/npm/linux-arm64-gnu/package.json index 6baf2131..2074b969 100644 --- a/mcp/npm/linux-arm64-gnu/package.json +++ b/mcp/npm/linux-arm64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-mcp-linux-arm64-gnu", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsm native binary for Linux arm64 (glibc)", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/mcp/npm/linux-x64-gnu/package.json b/mcp/npm/linux-x64-gnu/package.json index eb88c41b..dae748e3 100644 --- a/mcp/npm/linux-x64-gnu/package.json +++ b/mcp/npm/linux-x64-gnu/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-mcp-linux-x64-gnu", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsm native binary for Linux x64 (glibc)", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/mcp/npm/win32-x64-msvc/package.json b/mcp/npm/win32-x64-msvc/package.json index 5808ff30..a1c42179 100644 --- a/mcp/npm/win32-x64-msvc/package.json +++ b/mcp/npm/win32-x64-msvc/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-mcp-win32-x64-msvc", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "tnmsm native binary for Windows x64", "author": "TrueNine", "license": "AGPL-3.0-only", diff --git a/mcp/package.json b/mcp/package.json index 14f41133..92c577fa 100644 --- a/mcp/package.json +++ b/mcp/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync-mcp", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "TrueNine Memory Sync MCP metadata package", "author": "TrueNine", "license": "AGPL-3.0-only", @@ -32,10 +32,10 @@ "test": "cargo test --manifest-path Cargo.toml" }, "optionalDependencies": { - "@truenine/memory-sync-mcp-darwin-arm64": "2026.10801.0", - "@truenine/memory-sync-mcp-darwin-x64": "2026.10801.0", - "@truenine/memory-sync-mcp-linux-arm64-gnu": "2026.10801.0", - "@truenine/memory-sync-mcp-linux-x64-gnu": "2026.10801.0", - "@truenine/memory-sync-mcp-win32-x64-msvc": "2026.10801.0" + "@truenine/memory-sync-mcp-darwin-arm64": "2026.10805.0", + "@truenine/memory-sync-mcp-darwin-x64": "2026.10805.0", + "@truenine/memory-sync-mcp-linux-arm64-gnu": "2026.10805.0", + "@truenine/memory-sync-mcp-linux-x64-gnu": "2026.10805.0", + "@truenine/memory-sync-mcp-win32-x64-msvc": "2026.10805.0" } } diff --git a/obsidian-plugin/RELEASING.md b/obsidian-plugin/RELEASING.md new file mode 100644 index 00000000..85dfbb80 --- /dev/null +++ b/obsidian-plugin/RELEASING.md @@ -0,0 +1,11 @@ +# TNMSO Release Checklist + +1. Update the shared memory-sync CalVer version; do not version TNMSO independently. +2. Run the version hook and `scripts/shared/check-version-surfaces.ts` from the repository root. +3. Run TNMSO tests, type checking, lint, build, packaging, and dist verification with Bun. +4. Confirm the system `v` Release contains `tnmso-.zip`. +5. Confirm the Obsidian `` Release points to the same commit and contains `main.js`, `manifest.json`, and `styles.css`. +6. For the first community listing, sign in at [community.obsidian.md](https://community.obsidian.md), link the maintainer GitHub account, and submit `https://github.com/TrueNine/memory-sync` under **Plugins > New plugin**. +7. Confirm the directory reads the root `manifest.json` from the default branch and passes its automated review before selecting **Publish**. + +The initial directory submission requires an Obsidian account and is intentionally a maintainer action. Later plugin versions are discovered from GitHub Releases automatically. diff --git a/obsidian-plugin/bun.lock b/obsidian-plugin/bun.lock new file mode 100644 index 00000000..f288266d --- /dev/null +++ b/obsidian-plugin/bun.lock @@ -0,0 +1,905 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "tnmso", + "dependencies": { + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.1", + "remark-mdx": "^3.1.1", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.5", + "yaml": "^2.9.0", + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/bun": "1.3.14", + "@types/estree": "^1.0.9", + "@types/mdast": "^4.0.4", + "@types/node": "^26.1.2", + "esbuild": "^0.25.5", + "eslint": "^10.8.0", + "eslint-plugin-obsidianmd": "^0.4.0", + "fflate": "^0.8.2", + "globals": "^17.6.0", + "jiti": "2.7.0", + "obsidian": "latest", + "typescript": "6.0.3", + "typescript-eslint": "^8.65.0", + }, + }, + }, + "packages": { + "@codemirror/state": ["@codemirror/state@6.5.0", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw=="], + + "@codemirror/view": ["@codemirror/view@6.38.6", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-qiS0z1bKs5WOvHIAC0Cybmv4AJSkAXgX5aD6Mqd2epSLlVJsQl8NG23jCVouIgkh4All/mrbdsf2UOLFnJw0tw=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], + + "@eslint-community/eslint-plugin-eslint-comments": ["@eslint-community/eslint-plugin-eslint-comments@4.7.2", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "ignore": "^7.0.5" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" } }, "sha512-LF03qURSwEWm2dz5wtdDCzNk+7Opl0X7q6I3undsaIuNsEiNvRV3BCtqu14Q/6Pzg1tBj44LcxpW2EpSLZStZw=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.10.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw=="], + + "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="], + + "@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="], + + "@eslint/json": ["@eslint/json@0.14.0", "", { "dependencies": { "@eslint/core": "^0.17.0", "@eslint/plugin-kit": "^0.4.1", "@humanwhocodes/momoa": "^3.3.10", "natural-compare": "^1.4.0" } }, "sha512-rvR/EZtvUG3p9uqrSmcDJPYSH7atmWr0RnFWN6m917MAPx82+zQgPUmDu0whPFG6XTyM0vB/hR6c1Q63OaYtCQ=="], + + "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.2", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A=="], + + "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="], + + "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="], + + "@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/momoa": ["@humanwhocodes/momoa@3.3.10", "", {}, "sha512-KWiFQpSAqEIyrTXko3hFNLeQvSK8zXlJQzhhxsyVn58WFRYXST99b3Nqnu+ttOtjds2Pl2grUHGpe2NzhPynuQ=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@marijn/find-cluster-break": ["@marijn/find-cluster-break@1.0.3", "", {}, "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA=="], + + "@microsoft/eslint-plugin-sdl": ["@microsoft/eslint-plugin-sdl@1.1.0", "", { "dependencies": { "eslint-plugin-n": "17.10.3", "eslint-plugin-react": "7.37.3", "eslint-plugin-security": "1.4.0" }, "peerDependencies": { "eslint": "^9" } }, "sha512-dxdNHOemLnBhfY3eByrujX9KyLigcNtW8sU+axzWv5nLGcsSBeKW2YYyTpfPo1hV8YPOmIGnfA4fZHyKVtWqBQ=="], + + "@pkgr/core": ["@pkgr/core@0.1.2", "", {}, "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ=="], + + "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], + + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], + + "@types/codemirror": ["@types/codemirror@5.60.8", "", { "dependencies": { "@types/tern": "*" } }, "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw=="], + + "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="], + + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], + + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + + "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], + + "@types/hast": ["@types/hast@3.0.5", "", { "dependencies": { "@types/unist": "*" } }, "sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], + + "@types/node": ["@types/node@26.1.2", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-Vu4a5UFA9rIIFJ7rB/Vaafh9lrCQszopTCx6KjFboXTGQbPNasehVR5TEiithSDGyd1DEiUByggTZsg8jukeIg=="], + + "@types/tern": ["@types/tern@0.23.9", "", { "dependencies": { "@types/estree": "*" } }, "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.66.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.66.0", "@typescript-eslint/type-utils": "8.66.0", "@typescript-eslint/utils": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.66.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-p088eaGrzYz1s+7cov0aMOCkNGTJlVxF4jgubf28c8L0Cv9Rloj8YBHnv4hXLq6IIEE1AsjNWavO+k+8kP2Y0A=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.66.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.66.0", "@typescript-eslint/types": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-X6ypGChaWYk6PBtUg2BwuTZEFFcHJAtGTVJ9/lCTOufhZ4i9fNolQNnktq+kkMCwMj7V8Svsq7+TxSDslmhE0g=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.66.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.66.0", "@typescript-eslint/types": "^8.66.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-7MthGPTt4BP69lSryqpqq8HQqxuzynssckL/jyDyk3+TNMQ3y2jFWkptCrktWvBrP+EH787Nl5N5Qpw7WZg+5g=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0" } }, "sha512-8TGcH25j9zqJ/IULB/ppyhRvxA8QYfFEZ7nfbg6/BN9spDgb8fPWQXlE5l8TWBL50EtUx007uZ1o9VOwrq2/9g=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.66.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-9D5gLYZG4rOjcoag8MQ/fWI8WqA9wcPDyOGyWtWFhvM1lHRbliqUSPIY5J3zqCU1tvSwzXxnnjhQhz5Ne7mJ4g=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0", "@typescript-eslint/utils": "8.66.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-LG2dWfjZQQp0ADtAu/EWJVayefGL2UEZ3CDeI44D9v3rXB/WYUqE/jpO28KrEKul5AySrmI+Zh1v6v+xW2U9+g=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.66.0", "", {}, "sha512-H6gcYaSDOyvL3AD/jHUtUFo2jqGgn/F6nuyuZSu0QTesxL+cP4dQoIMrODRofuJC09g64+WgZ6tE19Y1N2YIFQ=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.66.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.66.0", "@typescript-eslint/tsconfig-utils": "8.66.0", "@typescript-eslint/types": "8.66.0", "@typescript-eslint/visitor-keys": "8.66.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8/x4INiiQb10jGgXYD7116/zQ+OL84ZIFn0za68wwFHCanT/VLbBEroWht8RV8fn0/ZCAoazHLQgwUC0UQcDfg=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.66.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.66.0", "@typescript-eslint/types": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-jasearZPolBw5NJNYGMwxzHMF83niVWmMU1VdHzG1CyfI2VS7f7nZltnKtHcg20hW+7Uo5GfK4MeDPoU3qI8EA=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.66.0", "", { "dependencies": { "@typescript-eslint/types": "8.66.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-dkKR8q+lKciskj1Y3vthHktl+3cMLWGyVUP23bRiPZ5O9BRT++4EqDDV+TVeIKBL1VXVEqrJlz8MYbcnvJcAlg=="], + + "acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], + + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], + + "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], + + "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], + + "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], + + "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], + + "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], + + "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], + + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], + + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="], + + "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + + "brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="], + + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + + "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "crelt": ["crelt@1.0.7", "", {}, "sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], + + "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], + + "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "empathic": ["empathic@2.0.1", "", {}, "sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q=="], + + "enhanced-resolve": ["enhanced-resolve@5.24.5", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A=="], + + "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="], + + "es-abstract-get": ["es-abstract-get@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "es-object-atoms": "^1.1.2", "is-callable": "^1.2.7", "object-inspect": "^1.13.4" } }, "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-iterator-helpers": ["es-iterator-helpers@1.4.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q=="], + + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="], + + "es-to-primitive": ["es-to-primitive@1.3.4", "", { "dependencies": { "es-abstract-get": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "is-callable": "^1.2.7", "is-date-object": "^1.1.0", "is-symbol": "^1.1.1" } }, "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw=="], + + "esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@10.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ=="], + + "eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], + + "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="], + + "eslint-module-utils": ["eslint-module-utils@2.14.0", "", { "dependencies": { "debug": "^3.2.7" }, "peerDependencies": { "eslint": "*" }, "optionalPeers": ["eslint"] }, "sha512-W2WCRZ9Dqntd+2u8jJcVMV2PKulc6RdLgUUoh/yQr3uB6lo/ZOeGx11sv60/8S4QFFKNslAlWhr9u0Ef7ZW6Ig=="], + + "eslint-plugin-depend": ["eslint-plugin-depend@1.3.1", "", { "dependencies": { "empathic": "^2.0.0", "module-replacements": "^2.8.0", "semver": "^7.6.3" } }, "sha512-1uo2rFAr9vzNrCYdp7IBZRB54LiyVxfaIso0R6/QV3t6Dax6DTbW/EV2Hktf0f4UtmGHK8UyzJWI382pwW04jw=="], + + "eslint-plugin-es-x": ["eslint-plugin-es-x@7.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", "eslint-compat-utils": "^0.5.1" }, "peerDependencies": { "eslint": ">=8" } }, "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ=="], + + "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="], + + "eslint-plugin-json-schema-validator": ["eslint-plugin-json-schema-validator@5.1.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.3.0", "ajv": "^8.0.0", "debug": "^4.3.1", "eslint-compat-utils": "^0.5.0", "json-schema-migrate": "^2.0.0", "jsonc-eslint-parser": "^2.0.0", "minimatch": "^8.0.0", "synckit": "^0.9.0", "toml-eslint-parser": "^0.9.0", "tunnel-agent": "^0.6.0", "yaml-eslint-parser": "^1.0.0" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-ZmVyxRIjm58oqe2kTuy90PpmZPrrKvOjRPXKzq8WCgRgAkidCgm5X8domL2KSfadZ3QFAmifMgGTcVNhZ5ez2g=="], + + "eslint-plugin-n": ["eslint-plugin-n@17.10.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "enhanced-resolve": "^5.17.0", "eslint-plugin-es-x": "^7.5.0", "get-tsconfig": "^4.7.0", "globals": "^15.8.0", "ignore": "^5.2.4", "minimatch": "^9.0.5", "semver": "^7.5.3" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-ySZBfKe49nQZWR1yFaA0v/GsH6Fgp8ah6XV0WDz6CN8WO0ek4McMzb7A2xnf4DCYV43frjCygvb9f/wx7UUxRw=="], + + "eslint-plugin-no-unsanitized": ["eslint-plugin-no-unsanitized@4.1.5", "", { "peerDependencies": { "eslint": "^9 || ^10" } }, "sha512-MSB4hXPVFQrI8weqzs6gzl7reP2k/qSjtCoL2vUMSDejIIq9YL1ZKvq5/ORBXab/PvfBBrWO2jWviYpL+4Ghfg=="], + + "eslint-plugin-obsidianmd": ["eslint-plugin-obsidianmd@0.4.1", "", { "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.7.2", "@eslint/config-helpers": "^0.4.2", "@eslint/js": "^9.30.1", "@eslint/json": "0.14.0", "@microsoft/eslint-plugin-sdl": "^1.1.0", "@types/eslint": "9.6.1", "@types/node": "20.12.12", "@typescript-eslint/types": "^8.33.1", "@typescript-eslint/utils": "^8.33.1", "eslint": ">=9.19.0", "eslint-plugin-depend": "1.3.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-json-schema-validator": "5.1.0", "eslint-plugin-no-unsanitized": "^4.1.5", "eslint-plugin-security": "2.1.1", "globals": "14.0.0", "obsidian": "1.12.3", "semver": "^7.7.4", "typescript": "5.4.5", "typescript-eslint": "^8.35.1" }, "bin": { "eslint-plugin-obsidian": "dist/lib/index.js" } }, "sha512-Nv3593kVsFOS8kir/HWaJ5CR3xcyiPWEPyXst5Pib8mxRYYuLYPpJS2ALMoZXHulHyiGwoYW8AaxvLRc4rhrRg=="], + + "eslint-plugin-react": ["eslint-plugin-react@7.37.3", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA=="], + + "eslint-plugin-security": ["eslint-plugin-security@2.1.1", "", { "dependencies": { "safe-regex": "^2.1.1" } }, "sha512-7cspIGj7WTfR3EhaILzAPcfCo5R9FbeWvbgsPYWivSurTBKW88VQxtP3c4aWMG9Hz/GfJlJVdXEJ3c8LqS+u2w=="], + + "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], + + "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], + + "estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fast-uri": ["fast-uri@3.1.5", "", {}, "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw=="], + + "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.4.4", "", {}, "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q=="], + + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + + "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "function.prototype.name": ["function.prototype.name@1.2.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2", "hasown": "^2.0.4", "is-callable": "^1.2.7", "is-document.all": "^1.0.0" } }, "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew=="], + + "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], + + "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], + + "get-tsconfig": ["get-tsconfig@4.14.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-Dz/6HxkrxgNehhxLVeyv8sad9UzF2xBVeaKBQNDfJ5XiSXmp2gTR0eO0RWiT2NCKS5aGP9jjkOMggTN90qU50A=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@17.9.0", "", {}, "sha512-m/MvAW61QVU5VDNF1Vj8axt016h8w7L5TU1e9zlab7XIttAT2YAlCwl75K1fOqvMM9apmD7lbCIRhpfkhmxhCg=="], + + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + + "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], + + "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], + + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], + + "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], + + "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], + + "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], + + "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], + + "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], + + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], + + "is-document.all": ["is-document.all@1.0.0", "", { "dependencies": { "call-bound": "^1.0.4" } }, "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], + + "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], + + "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], + + "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], + + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], + + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], + + "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], + + "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], + + "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], + + "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], + + "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], + + "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], + + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], + + "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-migrate": ["json-schema-migrate@2.0.0", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], + + "jsonc-eslint-parser": ["jsonc-eslint-parser@2.4.2", "", { "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^3.0.0", "espree": "^9.0.0", "semver": "^7.3.5" } }, "sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA=="], + + "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], + + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], + + "mdast-util-frontmatter": ["mdast-util-frontmatter@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "escape-string-regexp": "^5.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0" } }, "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA=="], + + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], + + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], + + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="], + + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], + + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], + + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], + + "mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="], + + "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="], + + "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="], + + "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="], + + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], + + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], + + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], + + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], + + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], + + "micromark-extension-frontmatter": ["micromark-extension-frontmatter@2.0.0", "", { "dependencies": { "fault": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg=="], + + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], + + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], + + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="], + + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="], + + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="], + + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], + + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], + + "micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q=="], + + "micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.2", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ=="], + + "micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="], + + "micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="], + + "micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="], + + "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], + + "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], + + "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ=="], + + "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], + + "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], + + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], + + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="], + + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="], + + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="], + + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg=="], + + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], + + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], + + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + + "minimatch": ["minimatch@10.2.6", "", { "dependencies": { "brace-expansion": "^5.0.8" } }, "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "module-replacements": ["module-replacements@2.11.0", "", {}, "sha512-j5sNQm3VCpQQ7nTqGeOZtoJtV3uKERgCBm9QRhmGRiXiqkf7iRFOkfxdJRZWLkqYY8PNf4cDQF/WfXUYLENrRA=="], + + "moment": ["moment@2.29.4", "", {}, "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "node-exports-info": ["node-exports-info@1.6.2", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], + + "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], + + "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="], + + "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], + + "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], + + "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], + + "obsidian": ["obsidian@1.13.1", "", { "dependencies": { "@types/codemirror": "5.60.8", "moment": "2.29.4" }, "peerDependencies": { "@codemirror/state": "6.5.0", "@codemirror/view": "6.38.6" } }, "sha512-qtTEA2pmhJzhuhJqzbBFRYhpIOqvW+krDYjtFynv66KbxBbumHBlsJfWw3I4jtnK/6fZwbQhCrmmDdRwXmX56w=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "own-keys": ["own-keys@1.0.2", "", { "dependencies": { "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], + + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], + + "regexp-tree": ["regexp-tree@0.1.27", "", { "bin": { "regexp-tree": "bin/regexp-tree" } }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="], + + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], + + "remark-frontmatter": ["remark-frontmatter@5.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-frontmatter": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0", "unified": "^11.0.0" } }, "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ=="], + + "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="], + + "remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="], + + "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="], + + "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "resolve": ["resolve@2.0.0-next.7", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.2", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ=="], + + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + + "ret": ["ret@0.1.15", "", {}, "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg=="], + + "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], + + "safe-regex": ["safe-regex@2.1.1", "", { "dependencies": { "regexp-tree": "~0.1.1" } }, "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A=="], + + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], + + "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], + + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], + + "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], + + "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], + + "string.prototype.trim": ["string.prototype.trim@1.2.11", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-object-atoms": "^1.1.2", "has-property-descriptors": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w=="], + + "string.prototype.trimend": ["string.prototype.trimend@1.0.10", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.2" } }, "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw=="], + + "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "synckit": ["synckit@0.9.3", "", { "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" } }, "sha512-JJoOEKTfL1urb1mDoEblhD9NhEbWmq9jHEMEnxoC4ujUaZ4itA8vKgwkFAyNClgxplLi9tsUKX+EduK0p/l7sg=="], + + "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], + + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], + + "toml-eslint-parser": ["toml-eslint-parser@0.9.3", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0" } }, "sha512-moYoCvkNUAPCxSW9jmHmRElhm4tVJpHL8ItC/+uYD0EpPSFXbck7yREz9tNdJVTSpHVod8+HoipcpbQ0oE6gsw=="], + + "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="], + + "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], + + "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], + + "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], + + "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], + + "typed-array-length": ["typed-array-length@1.0.8", "", { "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", "gopd": "^1.2.0", "is-typed-array": "^1.1.15", "possible-typed-array-names": "^1.1.0", "reflect.getprototypeof": "^1.0.10" } }, "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g=="], + + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], + + "typescript-eslint": ["typescript-eslint@8.66.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.66.0", "@typescript-eslint/parser": "8.66.0", "@typescript-eslint/typescript-estree": "8.66.0", "@typescript-eslint/utils": "8.66.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-QlEbBPz/RuJ1XUHj29nm3t0F/O/cSlEnntozqPOYHnnTGAXFamnMBu5i9Vn6vhUPHGAjR+Vl+5J8vPN/BMUrJw=="], + + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], + + "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], + + "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], + + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], + + "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + + "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], + + "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], + + "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], + + "which-typed-array": ["which-typed-array@1.1.22", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], + + "yaml-eslint-parser": ["yaml-eslint-parser@1.3.2", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0", "yaml": "^2.0.0" } }, "sha512-odxVsHAkZYYglR30aPYRY4nUGJnoJ2y1ww2HDvZALo0BDETv9kWbi16J52eHs+PWRNmF4ub6nZqfVOeesOvntg=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "@eslint-community/eslint-plugin-eslint-comments/ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/json/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + + "@eslint/json/@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + + "@microsoft/eslint-plugin-sdl/eslint-plugin-security": ["eslint-plugin-security@1.4.0", "", { "dependencies": { "safe-regex": "^1.1.0" } }, "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.6", "", {}, "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw=="], + + "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + + "eslint-plugin-import/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "eslint-plugin-json-schema-validator/ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], + + "eslint-plugin-json-schema-validator/minimatch": ["minimatch@8.0.7", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg=="], + + "eslint-plugin-n/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], + + "eslint-plugin-n/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "eslint-plugin-obsidianmd/@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], + + "eslint-plugin-obsidianmd/@eslint/js": ["@eslint/js@9.39.5", "", {}, "sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A=="], + + "eslint-plugin-obsidianmd/@types/node": ["@types/node@20.12.12", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw=="], + + "eslint-plugin-obsidianmd/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "eslint-plugin-obsidianmd/obsidian": ["obsidian@1.12.3", "", { "dependencies": { "@types/codemirror": "5.60.8", "moment": "2.29.4" }, "peerDependencies": { "@codemirror/state": "6.5.0", "@codemirror/view": "6.38.6" } }, "sha512-HxWqe763dOqzXjnNiHmAJTRERN8KILBSqxDSEqbeSr7W8R8Jxezzbca+nz1LiiqXnMpM8lV2jzAezw3CZ4xNUw=="], + + "eslint-plugin-obsidianmd/typescript": ["typescript@5.4.5", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], + + "eslint-plugin-react/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "json-schema-migrate/ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], + + "jsonc-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "jsonc-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], + + "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "node-exports-info/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], + + "toml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@microsoft/eslint-plugin-sdl/eslint-plugin-security/safe-regex": ["safe-regex@1.1.0", "", { "dependencies": { "ret": "~0.1.10" } }, "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg=="], + + "eslint-plugin-import/minimatch/brace-expansion": ["brace-expansion@1.1.18", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw=="], + + "eslint-plugin-json-schema-validator/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "eslint-plugin-json-schema-validator/minimatch/brace-expansion": ["brace-expansion@2.1.4", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg=="], + + "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.1.4", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg=="], + + "eslint-plugin-obsidianmd/@eslint/config-helpers/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + + "eslint-plugin-obsidianmd/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + + "eslint-plugin-react/minimatch/brace-expansion": ["brace-expansion@1.1.18", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw=="], + + "json-schema-migrate/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "eslint-plugin-import/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "eslint-plugin-json-schema-validator/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "eslint-plugin-n/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "eslint-plugin-react/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + } +} diff --git a/obsidian-plugin/eslint.config.ts b/obsidian-plugin/eslint.config.ts new file mode 100644 index 00000000..ddee316a --- /dev/null +++ b/obsidian-plugin/eslint.config.ts @@ -0,0 +1,33 @@ +import obsidianmd from 'eslint-plugin-obsidianmd' +import globals from 'globals' +import {defineConfig, globalIgnores} from 'eslint/config' + +export default defineConfig( + globalIgnores(['node_modules', 'dist', 'bun.lock', 'manifest.json', 'versions.json']), + { + languageOptions: { + globals: globals.browser, + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + }, + ...obsidianmd.configs.recommended, + { + files: ['scripts/**/*.ts'], + languageOptions: { + globals: globals.node, + }, + rules: { + 'obsidianmd/no-nodejs-modules': 'off', + 'obsidianmd/rule-custom-message': 'off', + }, + }, + { + files: ['src/settings-tab.ts'], + rules: { + 'obsidianmd/settings-tab/prefer-setting-definitions': 'off', + }, + }, +) diff --git a/obsidian-plugin/manifest.json b/obsidian-plugin/manifest.json new file mode 100644 index 00000000..eefc3744 --- /dev/null +++ b/obsidian-plugin/manifest.json @@ -0,0 +1,10 @@ +{ + "id": "tnmso", + "name": "TNMSO", + "version": "2026.10805.0", + "minAppVersion": "1.13.4", + "description": "Preview prompt-focused MDX files safely as Markdown.", + "author": "TrueNine", + "authorUrl": "https://github.com/TrueNine", + "isDesktopOnly": false +} diff --git a/obsidian-plugin/package.json b/obsidian-plugin/package.json new file mode 100644 index 00000000..30fa314c --- /dev/null +++ b/obsidian-plugin/package.json @@ -0,0 +1,43 @@ +{ + "name": "tnmso", + "version": "2026.10805.0", + "description": "Safe MDX prompt previews for Obsidian.", + "author": "TrueNine", + "license": "AGPL-3.0-only", + "private": true, + "type": "module", + "scripts": { + "build": "bun run scripts/build.ts", + "check:type": "tsc --noEmit", + "dev": "bun run scripts/build.ts --watch", + "lint": "eslint .", + "package:release": "bun run scripts/package-release.ts", + "test": "bun test", + "verify:dist": "bun run scripts/verify-dist.ts" + }, + "dependencies": { + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.1", + "remark-mdx": "^3.1.1", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.5", + "yaml": "^2.9.0" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/bun": "1.3.14", + "@types/estree": "^1.0.9", + "@types/mdast": "^4.0.4", + "@types/node": "^26.1.2", + "esbuild": "^0.25.5", + "eslint": "^10.8.0", + "eslint-plugin-obsidianmd": "^0.4.0", + "fflate": "^0.8.2", + "globals": "^17.6.0", + "jiti": "2.7.0", + "obsidian": "latest", + "typescript": "6.0.3", + "typescript-eslint": "^8.65.0" + } +} diff --git a/obsidian-plugin/scripts/build.ts b/obsidian-plugin/scripts/build.ts new file mode 100644 index 00000000..cf4d7f21 --- /dev/null +++ b/obsidian-plugin/scripts/build.ts @@ -0,0 +1,36 @@ +#!/usr/bin/env bun +import {cp, mkdir, rm} from 'node:fs/promises' +import {resolve} from 'node:path' + +import {context} from 'esbuild' + +const rootDir = resolve(import.meta.dirname, '..') +const distDir = resolve(rootDir, 'dist') +const watch = process.argv.includes('--watch') + +await rm(distDir, {recursive: true, force: true}) +await mkdir(distDir, {recursive: true}) +await Promise.all([ + cp(resolve(rootDir, 'manifest.json'), resolve(distDir, 'manifest.json')), + cp(resolve(rootDir, 'styles.css'), resolve(distDir, 'styles.css')), +]) + +const buildContext = await context({ + entryPoints: [resolve(rootDir, 'src/main.ts')], + outfile: resolve(distDir, 'main.js'), + bundle: true, + external: ['obsidian'], + format: 'cjs', + platform: 'browser', + target: 'es2022', + sourcemap: watch ? 'inline' : false, + logLevel: 'info', +}) + +if (watch) { + await buildContext.watch() + console.log('Watching TNMSO sources...') +} else { + await buildContext.rebuild() + await buildContext.dispose() +} diff --git a/obsidian-plugin/scripts/package-release.ts b/obsidian-plugin/scripts/package-release.ts new file mode 100644 index 00000000..03c5720e --- /dev/null +++ b/obsidian-plugin/scripts/package-release.ts @@ -0,0 +1,20 @@ +#!/usr/bin/env bun +import {readFile, writeFile} from 'node:fs/promises' +import {resolve} from 'node:path' + +import {zipSync} from 'fflate' + +interface Manifest { + version: string +} + +const rootDir = resolve(import.meta.dirname, '..') +const distDir = resolve(rootDir, 'dist') +const requiredFiles = ['main.js', 'manifest.json', 'styles.css'] as const +const entries = Object.fromEntries(await Promise.all( + requiredFiles.map(async file => [file, new Uint8Array(await readFile(resolve(distDir, file)))] as const), +)) +const manifest = JSON.parse(new TextDecoder().decode(entries['manifest.json'])) as Manifest +const archivePath = resolve(distDir, `tnmso-${manifest.version}.zip`) + +await writeFile(archivePath, zipSync(entries, {level: 9})) diff --git a/obsidian-plugin/scripts/verify-dist.ts b/obsidian-plugin/scripts/verify-dist.ts new file mode 100644 index 00000000..13e32584 --- /dev/null +++ b/obsidian-plugin/scripts/verify-dist.ts @@ -0,0 +1,73 @@ +#!/usr/bin/env bun +import {readdir, readFile, stat} from 'node:fs/promises' +import {resolve} from 'node:path' + +import {unzipSync} from 'fflate' + +interface Manifest { + author: string + description: string + id: string + isDesktopOnly: boolean + minAppVersion: string + name: string + version: string +} + +interface PackageJson { + version: string +} + +const rootDir = resolve(import.meta.dirname, '..') +const repoDir = resolve(rootDir, '..') +const distDir = resolve(rootDir, 'dist') +const files = (await readdir(distDir)).sort() +const requiredFiles = ['main.js', 'manifest.json', 'styles.css'] +const semanticVersion = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)$/u + +for (const file of requiredFiles) { + if (!files.includes(file)) throw new Error(`Missing release file: ${file}`) +} + +const [manifest, sourceManifest, packageJson, rootPackageJson, rootVersions, pluginVersions, mainStat, mainSource] = await Promise.all([ + readFile(resolve(distDir, 'manifest.json'), 'utf8').then(value => JSON.parse(value) as Manifest), + readFile(resolve(rootDir, 'manifest.json'), 'utf8').then(value => JSON.parse(value) as Manifest), + readFile(resolve(rootDir, 'package.json'), 'utf8').then(value => JSON.parse(value) as PackageJson), + readFile(resolve(repoDir, 'package.json'), 'utf8').then(value => JSON.parse(value) as PackageJson), + readFile(resolve(repoDir, 'versions.json'), 'utf8').then(value => JSON.parse(value) as Record), + readFile(resolve(rootDir, 'versions.json'), 'utf8').then(value => JSON.parse(value) as Record), + stat(resolve(distDir, 'main.js')), + readFile(resolve(distDir, 'main.js'), 'utf8'), +]) + +if (manifest.id !== 'tnmso' || manifest.name !== 'TNMSO') throw new Error('Unexpected plugin identity.') +if (!/^[a-z][a-z-]*$/u.test(manifest.id) || manifest.id.includes('obsidian') || manifest.id.endsWith('plugin')) { + throw new Error(`Invalid Obsidian plugin id: ${manifest.id}`) +} +if (!semanticVersion.test(manifest.version) || !semanticVersion.test(manifest.minAppVersion)) { + throw new Error('TNMSO version and minAppVersion must use x.y.z numeric versions.') +} +if (manifest.author.trim() === '' || manifest.description.length > 250 || !manifest.description.endsWith('.')) { + throw new Error('TNMSO manifest author and store description do not meet submission requirements.') +} +if (typeof manifest.isDesktopOnly !== 'boolean') throw new Error('TNMSO isDesktopOnly must be a boolean.') +if (manifest.version !== packageJson.version || manifest.version !== rootPackageJson.version) { + throw new Error('TNMSO manifest, plugin package, and repository versions differ.') +} +if (JSON.stringify(manifest) !== JSON.stringify(sourceManifest)) throw new Error('Built and source TNMSO manifests differ.') +if (rootVersions[manifest.version] !== manifest.minAppVersion || pluginVersions[manifest.version] !== manifest.minAppVersion) { + throw new Error('TNMSO versions.json files must map the release to minAppVersion.') +} +if (mainStat.size < 1_024) throw new Error(`main.js is unexpectedly small: ${mainStat.size}`) +if (!mainSource.includes('require("obsidian")')) throw new Error('main.js must externalize the Obsidian API.') + +const archiveName = `tnmso-${manifest.version}.zip` +if (files.includes(archiveName)) { + const archive = unzipSync(new Uint8Array(await readFile(resolve(distDir, archiveName)))) + const archiveFiles = Object.keys(archive).sort() + if (JSON.stringify(archiveFiles) !== JSON.stringify(requiredFiles)) { + throw new Error(`Unexpected TNMSO archive contents: ${archiveFiles.join(', ')}`) + } +} + +console.log(`Validated TNMSO release files for ${manifest.version}`) diff --git a/obsidian-plugin/src/compiler/compiler.test.ts b/obsidian-plugin/src/compiler/compiler.test.ts new file mode 100644 index 00000000..fb592db7 --- /dev/null +++ b/obsidian-plugin/src/compiler/compiler.test.ts @@ -0,0 +1,86 @@ +import {describe, expect, it} from 'bun:test' + +import {compileMdx} from './compiler' + +describe('compileMdx', () => { + it('preserves ordinary Markdown and GFM', () => { + const source = '# Prompt\n\n- [x] Keep **Markdown**\n' + + const result = compileMdx(source) + + expect(result.markdown).toContain('# Prompt') + expect(result.markdown).toContain('- [x] Keep **Markdown**') + expect(result.diagnostics).toEqual([]) + }) + + it('merges scope in settings, YAML, then static export order', () => { + const source = [ + '---', + 'profile:', + ' name: YAML', + '---', + '', + 'export const profile = { name: "Export" }', + '', + 'Hello {profile.name} from {tool.name}.', + '', + ].join('\n') + + const result = compileMdx(source, { + profile: {name: 'Settings'}, + tool: {name: 'TNMSO'}, + }) + + expect(result.markdown).toContain('Hello Export from TNMSO.') + expect(result.markdown).not.toContain('export const') + expect(result.metadata).toMatchObject({profile: {name: 'Export'}}) + }) + + it('includes and excludes known Md components using static conditions', () => { + const source = [ + 'Visible', + '', + 'Hidden', + '', + ].join('\n') + + const result = compileMdx(source, {profile: {enabled: true}}) + + expect(result.markdown).toContain('Visible') + expect(result.markdown).not.toContain('Hidden') + expect(result.markdown).not.toContain(' { + const source = 'Value: {dangerous()}\n' + + const result = compileMdx(source) + + expect(result.markdown).toContain('{dangerous()}') + expect(result.diagnostics.some(diagnostic => ( + diagnostic.code === 'unsupported-expression' && diagnostic.severity === 'warning' + ))).toBeTrue() + }) + + it('preserves unknown components and reports a warning', () => { + const source = 'Body\n' + + const result = compileMdx(source, {profile: {name: 'Example'}}) + + expect(result.markdown).toContain(' ( + diagnostic.code === 'unknown-component' && diagnostic.severity === 'warning' + ))).toBeTrue() + }) + + it('fails open when MDX cannot be parsed', () => { + const source = 'Unclosed\n' + + const result = compileMdx(source) + + expect(result.markdown).toBe(source) + expect(result.diagnostics.some(diagnostic => ( + diagnostic.code === 'parse-error' && diagnostic.severity === 'error' + ))).toBeTrue() + }) +}) diff --git a/obsidian-plugin/src/compiler/compiler.ts b/obsidian-plugin/src/compiler/compiler.ts new file mode 100644 index 00000000..9f255f36 --- /dev/null +++ b/obsidian-plugin/src/compiler/compiler.ts @@ -0,0 +1,442 @@ +import type { + ArrayExpression, + BinaryExpression, + ConditionalExpression, + Expression, + Identifier, + LogicalExpression, + MemberExpression, + ObjectExpression, + Pattern, + Program, + TemplateLiteral, + UnaryExpression, +} from 'estree' +import type {Root} from 'mdast' +import remarkFrontmatter from 'remark-frontmatter' +import remarkGfm from 'remark-gfm' +import remarkMdx from 'remark-mdx' +import remarkParse from 'remark-parse' +import remarkStringify from 'remark-stringify' +import {unified} from 'unified' +import {parse as parseYaml} from 'yaml' + +import type {CompileDiagnostic, CompileResult} from './types' + +interface AstNode { + type: string + value?: string + name?: string | null + children?: AstNode[] + attributes?: MdxAttribute[] + data?: { + estree?: Program + } +} + +interface MdxAttribute { + type: string + name?: string + value?: string | MdxExpressionValue | null +} + +interface MdxExpressionValue { + type: string + value: string + data?: { + estree?: Program + } +} + +type EvaluationResult = + | {ok: true, value: unknown} + | {ok: false, reason: string} + +const BLOCKED_KEYS = new Set(['__proto__', 'constructor', 'prototype']) +const processor = unified() + .use(remarkParse) + .use(remarkGfm) + .use(remarkFrontmatter, ['yaml']) + .use(remarkMdx) + .use(remarkStringify, { + bullet: '-', + fences: true, + }) + +function isRecord(value: unknown): value is Record { + return value != null && typeof value === 'object' && !Array.isArray(value) +} + +function isUnknownArray(value: unknown): value is unknown[] { + return Array.isArray(value) +} + +function isExpression(value: Expression | Pattern): value is Expression { + return !['ArrayPattern', 'AssignmentPattern', 'ObjectPattern', 'RestElement'].includes(value.type) +} + +function cloneSafe(value: unknown): unknown { + if (Array.isArray(value)) { + return value.map(cloneSafe) + } + if (!isRecord(value)) { + return value + } + + const output: Record = {} + for (const [key, child] of Object.entries(value)) { + if (!BLOCKED_KEYS.has(key)) { + output[key] = cloneSafe(child) + } + } + return output +} + +function mergeRecords(...layers: readonly Record[]): Record { + const output: Record = {} + + for (const layer of layers) { + for (const [key, value] of Object.entries(layer)) { + if (BLOCKED_KEYS.has(key)) continue + const current = output[key] + output[key] = isRecord(current) && isRecord(value) + ? mergeRecords(current, value) + : cloneSafe(value) + } + } + + return output +} + +export function mergeScopeLayers(...layers: readonly Record[]): Record { + return mergeRecords(...layers) +} + +function expressionFromProgram(program: Program | undefined): Expression | undefined { + if (program?.body.length !== 1) return undefined + const statement = program.body[0] + return statement?.type === 'ExpressionStatement' ? statement.expression : undefined +} + +function propertyName(node: Identifier | Expression, computed: boolean): EvaluationResult { + if (!computed && node.type === 'Identifier') { + return {ok: true, value: node.name} + } + const evaluated = evaluateExpression(node, {}) + if (!evaluated.ok || (typeof evaluated.value !== 'string' && typeof evaluated.value !== 'number')) { + return {ok: false, reason: 'Property names must be static strings or numbers.'} + } + return evaluated +} + +function evaluateArray(node: ArrayExpression, scope: Record): EvaluationResult { + const values: unknown[] = [] + for (const element of node.elements) { + if (element == null || element.type === 'SpreadElement') { + return {ok: false, reason: 'Array holes and spread elements are not supported.'} + } + const result = evaluateExpression(element, scope) + if (!result.ok) return result + values.push(result.value) + } + return {ok: true, value: values} +} + +function evaluateObject(node: ObjectExpression, scope: Record): EvaluationResult { + const output: Record = {} + for (const entry of node.properties) { + if (entry.type !== 'Property' || entry.kind !== 'init' || entry.method || !isExpression(entry.value)) { + return {ok: false, reason: 'Only static object properties are supported.'} + } + const keyResult = propertyName(entry.key, entry.computed) + if (!keyResult.ok) return keyResult + const key = String(keyResult.value) + if (BLOCKED_KEYS.has(key)) { + return {ok: false, reason: `Blocked property name: ${key}`} + } + const valueResult = evaluateExpression(entry.value, scope) + if (!valueResult.ok) return valueResult + output[key] = valueResult.value + } + return {ok: true, value: output} +} + +function evaluateMember(node: MemberExpression, scope: Record): EvaluationResult { + if (node.object.type === 'Super') { + return {ok: false, reason: 'Super references are not supported.'} + } + const objectResult = evaluateExpression(node.object, scope) + if (!objectResult.ok || objectResult.value == null) { + return {ok: false, reason: objectResult.ok ? 'Cannot read a nullish value.' : objectResult.reason} + } + if (node.property.type === 'PrivateIdentifier') { + return {ok: false, reason: 'Private properties are not supported.'} + } + const keyResult = propertyName(node.property, node.computed) + if (!keyResult.ok) return keyResult + const key = String(keyResult.value) + if (BLOCKED_KEYS.has(key) || (!isRecord(objectResult.value) && !isUnknownArray(objectResult.value))) { + return {ok: false, reason: `Unsafe or unavailable property: ${key}`} + } + if (!Object.hasOwn(objectResult.value, key)) { + return {ok: false, reason: `Unknown property: ${key}`} + } + const value: unknown = isUnknownArray(objectResult.value) + ? objectResult.value[Number(key)] + : objectResult.value[key] + return {ok: true, value} +} + +function evaluateUnary(node: UnaryExpression, scope: Record): EvaluationResult { + const argument = evaluateExpression(node.argument, scope) + if (!argument.ok) return argument + switch (node.operator) { + case '!': return {ok: true, value: !argument.value} + case '+': return {ok: true, value: Number(argument.value)} + case '-': return {ok: true, value: -Number(argument.value)} + case 'typeof': return {ok: true, value: typeof argument.value} + case 'void': return {ok: true, value: undefined} + default: return {ok: false, reason: `Unsupported unary operator: ${node.operator}`} + } +} + +function evaluateBinary(node: BinaryExpression, scope: Record): EvaluationResult { + const left = evaluateExpression(node.left as Expression, scope) + if (!left.ok) return left + const right = evaluateExpression(node.right, scope) + if (!right.ok) return right + + switch (node.operator) { + case '===': return {ok: true, value: left.value === right.value} + case '!==': return {ok: true, value: left.value !== right.value} + case '==': return {ok: true, value: left.value === right.value} + case '!=': return {ok: true, value: left.value !== right.value} + case '<': return {ok: true, value: String(left.value) < String(right.value)} + case '<=': return {ok: true, value: String(left.value) <= String(right.value)} + case '>': return {ok: true, value: String(left.value) > String(right.value)} + case '>=': return {ok: true, value: String(left.value) >= String(right.value)} + default: return {ok: false, reason: `Unsupported binary operator: ${node.operator}`} + } +} + +function evaluateLogical(node: LogicalExpression, scope: Record): EvaluationResult { + const left = evaluateExpression(node.left, scope) + if (!left.ok) return left + if (node.operator === '&&' && !left.value) return left + if (node.operator === '||' && left.value) return left + if (node.operator === '??' && left.value != null) return left + return evaluateExpression(node.right, scope) +} + +function evaluateConditional(node: ConditionalExpression, scope: Record): EvaluationResult { + const test = evaluateExpression(node.test, scope) + if (!test.ok) return test + return evaluateExpression(test.value ? node.consequent : node.alternate, scope) +} + +function evaluateTemplate(node: TemplateLiteral, scope: Record): EvaluationResult { + let output = node.quasis[0]?.value.cooked ?? '' + for (let index = 0; index < node.expressions.length; index += 1) { + const result = evaluateExpression(node.expressions[index] as Expression, scope) + if (!result.ok) return result + output += formatValue(result.value) + output += node.quasis[index + 1]?.value.cooked ?? '' + } + return {ok: true, value: output} +} + +function evaluateExpression(node: Expression, scope: Record): EvaluationResult { + switch (node.type) { + case 'Literal': + return node.value instanceof RegExp + ? {ok: false, reason: 'Regular expressions are not supported.'} + : {ok: true, value: node.value} + case 'Identifier': + return Object.hasOwn(scope, node.name) && !BLOCKED_KEYS.has(node.name) + ? {ok: true, value: scope[node.name]} + : {ok: false, reason: `Unknown identifier: ${node.name}`} + case 'ArrayExpression': return evaluateArray(node, scope) + case 'ObjectExpression': return evaluateObject(node, scope) + case 'MemberExpression': return evaluateMember(node, scope) + case 'UnaryExpression': return evaluateUnary(node, scope) + case 'BinaryExpression': return evaluateBinary(node, scope) + case 'LogicalExpression': return evaluateLogical(node, scope) + case 'ConditionalExpression': return evaluateConditional(node, scope) + case 'TemplateLiteral': return evaluateTemplate(node, scope) + default: return {ok: false, reason: `Unsupported expression type: ${node.type}`} + } +} + +function readYamlMetadata(root: AstNode, diagnostics: CompileDiagnostic[]): Record { + const yamlNode = root.children?.find(node => node.type === 'yaml') + if (yamlNode?.value == null) return {} + + try { + const value: unknown = parseYaml(yamlNode.value) + if (isRecord(value)) return cloneSafe(value) as Record + diagnostics.push({ + severity: 'warning', + code: 'invalid-frontmatter', + message: 'YAML frontmatter must contain an object.', + }) + } catch (error) { + diagnostics.push({ + severity: 'warning', + code: 'invalid-frontmatter', + message: error instanceof Error ? error.message : String(error), + }) + } + return {} +} + +function readExports(root: AstNode, baseScope: Record, diagnostics: CompileDiagnostic[]): Record { + const exports: Record = {} + + for (const node of root.children ?? []) { + if (node.type !== 'mdxjsEsm') continue + const program = node.data?.estree + if (program == null) continue + + for (const statement of program.body) { + if (statement.type === 'ImportDeclaration') continue + if (statement.type === 'ExportDefaultDeclaration' && statement.declaration.type !== 'FunctionDeclaration' && statement.declaration.type !== 'ClassDeclaration') { + const result = evaluateExpression(statement.declaration, mergeRecords(baseScope, exports)) + if (result.ok && isRecord(result.value)) { + Object.assign(exports, cloneSafe(result.value)) + } else { + diagnostics.push({severity: 'warning', code: 'unsupported-export', message: result.ok ? 'Default export must be an object.' : result.reason}) + } + continue + } + if (statement.type === 'ExportNamedDeclaration' && statement.declaration?.type === 'VariableDeclaration' && statement.declaration.kind === 'const') { + for (const declaration of statement.declaration.declarations) { + if (declaration.id.type !== 'Identifier' || declaration.init == null) { + diagnostics.push({severity: 'warning', code: 'unsupported-export', message: 'Only statically named const exports are supported.'}) + continue + } + const result = evaluateExpression(declaration.init, mergeRecords(baseScope, exports)) + if (result.ok) { + exports[declaration.id.name] = cloneSafe(result.value) + } else { + diagnostics.push({severity: 'warning', code: 'unsupported-export', message: result.reason}) + } + } + continue + } + diagnostics.push({severity: 'warning', code: 'unsupported-export', message: 'Executable or re-exported ESM is omitted from preview.'}) + } + } + + return exports +} + +function formatValue(value: unknown): string { + if (value == null) return '' + if (typeof value === 'string') return value + if (typeof value === 'number' || typeof value === 'boolean' || typeof value === 'bigint') return String(value) + return JSON.stringify(value) +} + +function expressionDiagnostic(value: string | undefined, reason: string): CompileDiagnostic { + return { + severity: 'warning', + code: 'unsupported-expression', + message: `${value == null || value === '' ? 'Expression' : `{${value}}`}: ${reason}`, + } +} + +function transformExpression(node: AstNode, scope: Record, diagnostics: CompileDiagnostic[]): AstNode { + const expression = expressionFromProgram(node.data?.estree) + if (expression == null) { + diagnostics.push(expressionDiagnostic(node.value, 'Expression AST is unavailable.')) + return node + } + const result = evaluateExpression(expression, scope) + if (!result.ok) { + diagnostics.push(expressionDiagnostic(node.value, result.reason)) + return node + } + const text = {type: 'text', value: formatValue(result.value)} + return node.type === 'mdxFlowExpression' + ? {type: 'paragraph', children: [text]} + : text +} + +function readWhen(node: AstNode, scope: Record): EvaluationResult { + const attribute = node.attributes?.find(candidate => candidate.name === 'when') + if (attribute == null) return {ok: true, value: true} + if (typeof attribute.value === 'string') return {ok: true, value: attribute.value.length > 0} + if (attribute.value == null) return {ok: true, value: true} + const expression = expressionFromProgram(attribute.value.data?.estree) + return expression == null + ? {ok: false, reason: 'The when expression AST is unavailable.'} + : evaluateExpression(expression, scope) +} + +function transformChildren(nodes: readonly AstNode[], scope: Record, diagnostics: CompileDiagnostic[]): AstNode[] { + const transformed: AstNode[] = [] + + for (const node of nodes) { + if (node.type === 'mdxjsEsm') continue + if (node.type === 'mdxTextExpression' || node.type === 'mdxFlowExpression') { + transformed.push(transformExpression(node, scope, diagnostics)) + continue + } + if (node.type === 'mdxJsxTextElement' || node.type === 'mdxJsxFlowElement') { + if (node.name === 'Md' || node.name === 'Md.Line') { + const when = readWhen(node, scope) + if (!when.ok) { + diagnostics.push(expressionDiagnostic('when', when.reason)) + transformed.push(node) + } else if (when.value) { + transformed.push(...transformChildren(node.children ?? [], scope, diagnostics)) + } + continue + } + diagnostics.push({ + severity: 'warning', + code: 'unknown-component', + message: `Unknown MDX component is preserved: ${node.name ?? ''}`, + }) + transformed.push(node) + continue + } + if (node.children != null) { + transformed.push({...node, children: transformChildren(node.children, scope, diagnostics)}) + } else { + transformed.push(node) + } + } + + return transformed +} + +export function compileMdx(source: string, settingsScope: Record = {}): CompileResult { + const diagnostics: CompileDiagnostic[] = [] + + try { + const root = processor.parse(source) as Root & AstNode + const yamlMetadata = readYamlMetadata(root, diagnostics) + const baseScope = mergeRecords(settingsScope, yamlMetadata) + const exportMetadata = readExports(root, baseScope, diagnostics) + const metadata = mergeRecords(yamlMetadata, exportMetadata) + const scope = mergeRecords(settingsScope, yamlMetadata, exportMetadata) + const transformed = { + ...root, + children: transformChildren(root.children, scope, diagnostics), + } as Root + const markdown = processor.stringify(transformed) + + return {markdown, metadata, diagnostics} + } catch (error) { + return { + markdown: source, + metadata: {}, + diagnostics: [{ + severity: 'error', + code: 'parse-error', + message: error instanceof Error ? error.message : String(error), + }], + } + } +} diff --git a/obsidian-plugin/src/compiler/types.ts b/obsidian-plugin/src/compiler/types.ts new file mode 100644 index 00000000..bfafcb73 --- /dev/null +++ b/obsidian-plugin/src/compiler/types.ts @@ -0,0 +1,16 @@ +export interface TnmsoSettings { + compiledPreviewEnabled: boolean + scope: Record +} + +export interface CompileDiagnostic { + severity: 'warning' | 'error' + code: string + message: string +} + +export interface CompileResult { + markdown: string + metadata: Record + diagnostics: CompileDiagnostic[] +} diff --git a/obsidian-plugin/src/main.ts b/obsidian-plugin/src/main.ts new file mode 100644 index 00000000..e6c11900 --- /dev/null +++ b/obsidian-plugin/src/main.ts @@ -0,0 +1,189 @@ +import { + MarkdownRenderChild, + MarkdownRenderer, + MarkdownView, + Platform, + Plugin, + TFile, + setIcon, +} from 'obsidian' +import type {MarkdownPostProcessorContext} from 'obsidian' + +import {mergeScopeLayers} from './compiler/compiler' +import type {CompileDiagnostic, TnmsoSettings} from './compiler/types' +import {PreviewDiagnosticStore} from './preview/diagnostic-store' +import {processPreviewSection} from './preview/processor' +import {PromptMetadataCache} from './preview/prompt-metadata-cache' +import {normalizeSettings} from './settings' +import {TnmsoSettingTab} from './settings-tab' + +const RENDERED_ATTRIBUTE = 'data-tnmso-rendered' + +function isRecord(value: unknown): value is Record { + return value != null && typeof value === 'object' && !Array.isArray(value) +} + +export default class TnmsoPlugin extends Plugin { + override settings: TnmsoSettings = normalizeSettings(undefined) + + readonly #diagnostics = new PreviewDiagnosticStore() + #metadataCache!: PromptMetadataCache + #statusBarItem?: HTMLElement + + override async onload(): Promise { + this.settings = normalizeSettings(await this.loadData()) + this.#metadataCache = new PromptMetadataCache(async path => { + const file = this.app.vault.getAbstractFileByPath(path) + if (!(file instanceof TFile)) throw new Error(`Prompt file is unavailable: ${path}`) + return this.app.vault.cachedRead(file) + }) + + this.registerExtensions(['mdx'], 'markdown') + this.registerMarkdownPostProcessor(async (element, context) => { + await this.#processSection(element, context) + }) + + this.addCommand({ + id: 'toggle-compiled-preview', + name: 'Toggle compiled prompt preview', + callback: () => { + void this.setPreviewEnabled(!this.settings.compiledPreviewEnabled) + }, + }) + + if (!Platform.isMobile) { + this.#statusBarItem = this.addStatusBarItem() + this.#statusBarItem.addClass('tnmso-status') + this.#statusBarItem.setAttr('role', 'button') + this.#statusBarItem.setAttr('tabindex', '0') + this.#statusBarItem.addEventListener('click', () => { + void this.setPreviewEnabled(!this.settings.compiledPreviewEnabled) + }) + this.#statusBarItem.addEventListener('keydown', event => { + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault() + void this.setPreviewEnabled(!this.settings.compiledPreviewEnabled) + } + }) + } + + this.addSettingTab(new TnmsoSettingTab(this)) + this.registerEvent(this.app.workspace.on('active-leaf-change', () => this.#updateStatusBar())) + this.registerEvent(this.app.vault.on('modify', file => { + this.#invalidate(file.path) + })) + this.registerEvent(this.app.vault.on('delete', file => { + this.#invalidate(file.path) + })) + this.registerEvent(this.app.vault.on('rename', (file, oldPath) => { + this.#metadataCache.rename(oldPath, file.path) + this.#diagnostics.rename(oldPath, file.path) + this.#updateStatusBar() + })) + + this.#updateStatusBar() + } + + async setPreviewEnabled(enabled: boolean): Promise { + this.settings = {...this.settings, compiledPreviewEnabled: enabled} + await this.saveData(this.settings) + this.#diagnostics.clear() + this.#refreshMdxPreviews() + this.#updateStatusBar() + } + + async setScope(scope: Record): Promise { + this.settings = {...this.settings, scope} + await this.saveData(this.settings) + this.#metadataCache.clear() + this.#diagnostics.clear() + this.#refreshMdxPreviews() + this.#updateStatusBar() + } + + async #processSection(element: HTMLElement, context: MarkdownPostProcessorContext): Promise { + const nested = element.closest(`[${RENDERED_ATTRIBUTE}="true"]`) != null + const section = context.getSectionInfo(element) + if (section == null && context.sourcePath.toLowerCase().endsWith('.mdx') && this.settings.compiledPreviewEnabled) { + this.#setDiagnostics(context.sourcePath, 'unavailable', [{ + severity: 'warning', + code: 'section-unavailable', + message: 'Obsidian did not expose source information for this preview section.', + }]) + return + } + if (section == null) return + + const cached = await this.#metadataCache.get(context.sourcePath) + const frontmatter = isRecord(context.frontmatter) ? context.frontmatter : {} + const scope = mergeScopeLayers(this.settings.scope, frontmatter, cached.metadata) + + const result = await processPreviewSection({ + sourcePath: context.sourcePath, + source: section.text, + enabled: this.settings.compiledPreviewEnabled, + nested, + scope, + render: async markdown => { + const detached = element.ownerDocument.body.createDiv() + detached.detach() + detached.setAttr(RENDERED_ATTRIBUTE, 'true') + const child = new MarkdownRenderChild(element) + context.addChild(child) + try { + await MarkdownRenderer.render(this.app, markdown, detached, context.sourcePath, child) + element.setAttr(RENDERED_ATTRIBUTE, 'true') + element.replaceChildren(...detached.childNodes) + } catch (error) { + child.unload() + throw error + } + }, + }) + + this.#setDiagnostics(context.sourcePath, 'metadata', cached.diagnostics) + this.#setDiagnostics(context.sourcePath, `${section.lineStart}:${section.lineEnd}`, result.diagnostics) + } + + #invalidate(path: string): void { + this.#metadataCache.invalidate(path) + this.#diagnostics.invalidate(path) + this.#updateStatusBar() + } + + #setDiagnostics(path: string, section: string, diagnostics: CompileDiagnostic[]): void { + this.#diagnostics.set(path, section, diagnostics) + if (this.app.workspace.getActiveFile()?.path === path) this.#updateStatusBar() + } + + #refreshMdxPreviews(): void { + for (const leaf of this.app.workspace.getLeavesOfType('markdown')) { + if (leaf.view instanceof MarkdownView && leaf.view.file?.extension.toLowerCase() === 'mdx') { + leaf.view.previewMode.rerender(true) + } + } + } + + #updateStatusBar(): void { + const item = this.#statusBarItem + if (item == null) return + const activeFile = this.app.workspace.getActiveFile() + const isMdx = activeFile?.extension.toLowerCase() === 'mdx' + item.toggleClass('tnmso-status--hidden', !isMdx) + if (!isMdx) return + + const diagnostics = this.#diagnostics.get(activeFile.path) + const hasWarnings = diagnostics.length > 0 + const state = !this.settings.compiledPreviewEnabled ? 'off' : hasWarnings ? 'warning' : 'enabled' + item.removeClasses(['tnmso-status--off', 'tnmso-status--warning', 'tnmso-status--enabled']) + item.addClass(`tnmso-status--${state}`) + setIcon(item, state === 'warning' ? 'triangle-alert' : state === 'off' ? 'eye-off' : 'scan-eye') + const label = state === 'warning' + ? `TNMSO preview has ${diagnostics.length} diagnostic(s). Click to disable.` + : state === 'off' + ? 'TNMSO compiled preview is off. Click to enable.' + : 'TNMSO compiled preview is on. Click to disable.' + item.setAttr('aria-label', label) + item.setAttr('title', label) + } +} diff --git a/obsidian-plugin/src/preview/diagnostic-store.test.ts b/obsidian-plugin/src/preview/diagnostic-store.test.ts new file mode 100644 index 00000000..bec007ae --- /dev/null +++ b/obsidian-plugin/src/preview/diagnostic-store.test.ts @@ -0,0 +1,30 @@ +import {describe, expect, it} from 'bun:test' + +import {PreviewDiagnosticStore} from './diagnostic-store' + +describe('PreviewDiagnosticStore', () => { + it('aggregates diagnostics without allowing a clean section to erase another section', () => { + const store = new PreviewDiagnosticStore() + store.set('prompt.mdx', '1:2', [{severity: 'warning', code: 'first', message: 'First'}]) + store.set('prompt.mdx', '3:4', []) + + expect(store.get('prompt.mdx').map(diagnostic => diagnostic.code)).toEqual(['first']) + + store.set('prompt.mdx', '1:2', []) + expect(store.get('prompt.mdx')).toEqual([]) + }) + + it('clears paths on invalidation, rename, and global reset', () => { + const store = new PreviewDiagnosticStore() + const warning = [{severity: 'warning' as const, code: 'warning', message: 'Warning'}] + store.set('old.mdx', '1:1', warning) + store.set('new.mdx', '1:1', warning) + store.rename('old.mdx', 'new.mdx') + expect(store.get('old.mdx')).toEqual([]) + expect(store.get('new.mdx')).toEqual([]) + + store.set('other.mdx', '1:1', warning) + store.clear() + expect(store.get('other.mdx')).toEqual([]) + }) +}) diff --git a/obsidian-plugin/src/preview/diagnostic-store.ts b/obsidian-plugin/src/preview/diagnostic-store.ts new file mode 100644 index 00000000..3daf4329 --- /dev/null +++ b/obsidian-plugin/src/preview/diagnostic-store.ts @@ -0,0 +1,36 @@ +import type {CompileDiagnostic} from '../compiler/types' + +export class PreviewDiagnosticStore { + readonly #paths = new Map>() + + set(path: string, section: string, diagnostics: CompileDiagnostic[]): void { + const sections = this.#paths.get(path) ?? new Map() + if (diagnostics.length === 0) { + sections.delete(section) + } else { + sections.set(section, diagnostics) + } + if (sections.size === 0) { + this.#paths.delete(path) + } else { + this.#paths.set(path, sections) + } + } + + get(path: string): CompileDiagnostic[] { + return [...(this.#paths.get(path)?.values() ?? [])].flat() + } + + invalidate(path: string): void { + this.#paths.delete(path) + } + + rename(oldPath: string, newPath: string): void { + this.invalidate(oldPath) + this.invalidate(newPath) + } + + clear(): void { + this.#paths.clear() + } +} diff --git a/obsidian-plugin/src/preview/processor.test.ts b/obsidian-plugin/src/preview/processor.test.ts new file mode 100644 index 00000000..93b9f51b --- /dev/null +++ b/obsidian-plugin/src/preview/processor.test.ts @@ -0,0 +1,88 @@ +import {describe, expect, it} from 'bun:test' + +import {processPreviewSection} from './processor' + +describe('processPreviewSection', () => { + it('only renders enabled, non-recursive MDX sections', async () => { + const rendered: string[] = [] + const render = (markdown: string): void => { + rendered.push(markdown) + } + + const md = await processPreviewSection({ + sourcePath: 'prompt.md', + source: 'Hello', + enabled: true, + nested: false, + scope: {}, + render, + }) + const disabled = await processPreviewSection({ + sourcePath: 'prompt.mdx', + source: 'Hello', + enabled: false, + nested: false, + scope: {}, + render, + }) + const nested = await processPreviewSection({ + sourcePath: 'prompt.mdx', + source: 'Hello', + enabled: true, + nested: true, + scope: {}, + render, + }) + + expect(md.handled).toBeFalse() + expect(disabled.handled).toBeFalse() + expect(nested.handled).toBeFalse() + expect(rendered).toEqual([]) + }) + + it('compiles and renders supported MDX', async () => { + const rendered: string[] = [] + + const result = await processPreviewSection({ + sourcePath: 'prompt.mdx', + source: 'Hello {profile.name}', + enabled: true, + nested: false, + scope: {profile: {name: 'TNMSO'}}, + render: markdown => { + rendered.push(markdown) + }, + }) + + expect(result.handled).toBeTrue() + expect(rendered[0]).toContain('Hello TNMSO') + }) + + it('fails open on parse and render errors', async () => { + const parseResult = await processPreviewSection({ + sourcePath: 'prompt.mdx', + source: 'Unclosed', + enabled: true, + nested: false, + scope: {}, + render: () => { + throw new Error('must not render invalid MDX') + }, + }) + const renderResult = await processPreviewSection({ + sourcePath: 'prompt.mdx', + source: 'Hello', + enabled: true, + nested: false, + scope: {}, + render: () => { + throw new Error('renderer failed') + }, + }) + + expect(parseResult.handled).toBeFalse() + expect(parseResult.diagnostics.some(diagnostic => diagnostic.code === 'parse-error')).toBeTrue() + expect(renderResult.handled).toBeFalse() + expect(renderResult.diagnostics.some(diagnostic => diagnostic.code === 'render-error')).toBeTrue() + }) +}) diff --git a/obsidian-plugin/src/preview/processor.ts b/obsidian-plugin/src/preview/processor.ts new file mode 100644 index 00000000..cf82101c --- /dev/null +++ b/obsidian-plugin/src/preview/processor.ts @@ -0,0 +1,46 @@ +import {compileMdx} from '../compiler/compiler' +import type {CompileDiagnostic} from '../compiler/types' + +export interface ProcessPreviewSectionOptions { + sourcePath: string + source: string + enabled: boolean + nested: boolean + scope: Record + render: (markdown: string) => Promise | void +} + +export interface ProcessPreviewSectionResult { + handled: boolean + diagnostics: CompileDiagnostic[] +} + +export async function processPreviewSection( + options: ProcessPreviewSectionOptions, +): Promise { + if (!options.enabled || options.nested || !options.sourcePath.toLowerCase().endsWith('.mdx')) { + return {handled: false, diagnostics: []} + } + + const compiled = compileMdx(options.source, options.scope) + if (compiled.diagnostics.some(diagnostic => diagnostic.severity === 'error')) { + return {handled: false, diagnostics: compiled.diagnostics} + } + + try { + await options.render(compiled.markdown) + return {handled: true, diagnostics: compiled.diagnostics} + } catch (error) { + return { + handled: false, + diagnostics: [ + ...compiled.diagnostics, + { + severity: 'error', + code: 'render-error', + message: error instanceof Error ? error.message : String(error), + }, + ], + } + } +} diff --git a/obsidian-plugin/src/preview/prompt-metadata-cache.test.ts b/obsidian-plugin/src/preview/prompt-metadata-cache.test.ts new file mode 100644 index 00000000..48d383c6 --- /dev/null +++ b/obsidian-plugin/src/preview/prompt-metadata-cache.test.ts @@ -0,0 +1,55 @@ +import {describe, expect, it} from 'bun:test' + +import {PromptMetadataCache} from './prompt-metadata-cache' + +describe('PromptMetadataCache', () => { + it('caches static file metadata until invalidated', async () => { + let loads = 0 + const cache = new PromptMetadataCache(async () => { + loads += 1 + return 'export const profile = { name: "TNMSO" }\n' + }) + + const first = await cache.get('prompt.mdx') + const second = await cache.get('prompt.mdx') + cache.invalidate('prompt.mdx') + const third = await cache.get('prompt.mdx') + + expect(first.metadata).toEqual({profile: {name: 'TNMSO'}}) + expect(second).toEqual(first) + expect(third.metadata).toEqual(first.metadata) + expect(loads).toBe(2) + }) + + it('invalidates both paths on rename and all entries on clear', async () => { + let loads = 0 + const cache = new PromptMetadataCache(async path => { + loads += 1 + return `export const path = "${path}"\n` + }) + + await cache.get('old.mdx') + await cache.get('new.mdx') + cache.rename('old.mdx', 'new.mdx') + await cache.get('old.mdx') + await cache.get('new.mdx') + cache.clear() + await cache.get('new.mdx') + + expect(loads).toBe(5) + }) + + it('does not cache body expression diagnostics as metadata diagnostics', async () => { + const cache = new PromptMetadataCache(async () => [ + 'export const profile = { name: "TNMSO" }', + '', + 'Hello {tool.name}', + '', + ].join('\n')) + + const result = await cache.get('prompt.mdx') + + expect(result.metadata).toEqual({profile: {name: 'TNMSO'}}) + expect(result.diagnostics).toEqual([]) + }) +}) diff --git a/obsidian-plugin/src/preview/prompt-metadata-cache.ts b/obsidian-plugin/src/preview/prompt-metadata-cache.ts new file mode 100644 index 00000000..fff33465 --- /dev/null +++ b/obsidian-plugin/src/preview/prompt-metadata-cache.ts @@ -0,0 +1,58 @@ +import {compileMdx} from '../compiler/compiler' +import type {CompileDiagnostic} from '../compiler/types' + +export interface PromptMetadataResult { + metadata: Record + diagnostics: CompileDiagnostic[] +} + +export type PromptSourceLoader = (path: string) => Promise + +const METADATA_DIAGNOSTIC_CODES = new Set([ + 'invalid-frontmatter', + 'parse-error', + 'unsupported-export', +]) + +export class PromptMetadataCache { + readonly #entries = new Map>() + + constructor(private readonly loadSource: PromptSourceLoader) {} + + get(path: string): Promise { + const existing = this.#entries.get(path) + if (existing != null) return existing + + const pending = this.loadSource(path) + .then(source => { + const result = compileMdx(source) + return { + metadata: result.metadata, + diagnostics: result.diagnostics.filter(diagnostic => METADATA_DIAGNOSTIC_CODES.has(diagnostic.code)), + } + }) + .catch(error => ({ + metadata: {}, + diagnostics: [{ + severity: 'error' as const, + code: 'source-read-error', + message: error instanceof Error ? error.message : String(error), + }], + })) + this.#entries.set(path, pending) + return pending + } + + invalidate(path: string): void { + this.#entries.delete(path) + } + + rename(oldPath: string, newPath: string): void { + this.invalidate(oldPath) + this.invalidate(newPath) + } + + clear(): void { + this.#entries.clear() + } +} diff --git a/obsidian-plugin/src/settings-tab.ts b/obsidian-plugin/src/settings-tab.ts new file mode 100644 index 00000000..c515d489 --- /dev/null +++ b/obsidian-plugin/src/settings-tab.ts @@ -0,0 +1,44 @@ +import {PluginSettingTab, Setting} from 'obsidian' + +import type TnmsoPlugin from './main' +import {parseScopeText} from './settings' + +export class TnmsoSettingTab extends PluginSettingTab { + constructor(private readonly plugin: TnmsoPlugin) { + super(plugin.app, plugin) + } + + override display(): void { + this.containerEl.empty() + + new Setting(this.containerEl) + .setName('Compiled prompt preview') + .setDesc('Compile supported prompt syntax safely in reading view.') + .addToggle(toggle => toggle + .setValue(this.plugin.settings.compiledPreviewEnabled) + .onChange(async value => { + await this.plugin.setPreviewEnabled(value) + })) + + const scopeSetting = new Setting(this.containerEl) + .setName('Preview scope') + .setDesc('Variables used to resolve safe prompt property paths.') + .addTextArea(text => { + text + .setValue(JSON.stringify(this.plugin.settings.scope, null, 2)) + .setPlaceholder('{"profile":{"name":"Example"}}') + .onChange(async value => { + const parsed = parseScopeText(value) + if (!parsed.ok) { + scopeSetting.descEl.setText(`Invalid JSON: ${parsed.message}`) + scopeSetting.descEl.addClass('tnmso-setting-error') + return + } + scopeSetting.descEl.setText('Variables used to resolve safe prompt property paths.') + scopeSetting.descEl.removeClass('tnmso-setting-error') + await this.plugin.setScope(parsed.scope) + }) + }) + scopeSetting.controlEl.addClass('tnmso-scope-control') + } +} diff --git a/obsidian-plugin/src/settings.test.ts b/obsidian-plugin/src/settings.test.ts new file mode 100644 index 00000000..60cd4b96 --- /dev/null +++ b/obsidian-plugin/src/settings.test.ts @@ -0,0 +1,26 @@ +import {describe, expect, it} from 'bun:test' + +import {DEFAULT_SETTINGS, normalizeSettings, parseScopeText} from './settings' + +describe('TNMSO settings', () => { + it('defaults compiled preview to enabled', () => { + expect(normalizeSettings(undefined)).toEqual(DEFAULT_SETTINGS) + }) + + it('keeps only valid persisted values', () => { + expect(normalizeSettings({compiledPreviewEnabled: false, scope: {profile: {name: 'User'}}})).toEqual({ + compiledPreviewEnabled: false, + scope: {profile: {name: 'User'}}, + }) + expect(normalizeSettings({compiledPreviewEnabled: 'no', scope: []})).toEqual(DEFAULT_SETTINGS) + }) + + it('parses object scope without accepting arrays or invalid JSON', () => { + expect(parseScopeText('{"tool":{"name":"TNMSO"}}')).toEqual({ + ok: true, + scope: {tool: {name: 'TNMSO'}}, + }) + expect(parseScopeText('[]')).toMatchObject({ok: false}) + expect(parseScopeText('{')).toMatchObject({ok: false}) + }) +}) diff --git a/obsidian-plugin/src/settings.ts b/obsidian-plugin/src/settings.ts new file mode 100644 index 00000000..dd23a062 --- /dev/null +++ b/obsidian-plugin/src/settings.ts @@ -0,0 +1,42 @@ +import type {TnmsoSettings} from './compiler/types' + +export const DEFAULT_SETTINGS: TnmsoSettings = { + compiledPreviewEnabled: true, + scope: {}, +} + +export type ScopeParseResult = + | {ok: true, scope: Record} + | {ok: false, message: string} + +function isRecord(value: unknown): value is Record { + return value != null && typeof value === 'object' && !Array.isArray(value) +} + +function sanitizeRecord(value: Record): Record { + return Object.fromEntries( + Object.entries(value).filter(([key]) => !['__proto__', 'constructor', 'prototype'].includes(key)), + ) +} + +export function normalizeSettings(value: unknown): TnmsoSettings { + if (!isRecord(value)) return {...DEFAULT_SETTINGS} + return { + compiledPreviewEnabled: typeof value.compiledPreviewEnabled === 'boolean' + ? value.compiledPreviewEnabled + : DEFAULT_SETTINGS.compiledPreviewEnabled, + scope: isRecord(value.scope) ? sanitizeRecord(value.scope) : {}, + } +} + +export function parseScopeText(source: string): ScopeParseResult { + try { + const value: unknown = JSON.parse(source) + if (!isRecord(value)) { + return {ok: false, message: 'Scope must be a JSON object.'} + } + return {ok: true, scope: sanitizeRecord(value)} + } catch (error) { + return {ok: false, message: error instanceof Error ? error.message : String(error)} + } +} diff --git a/obsidian-plugin/styles.css b/obsidian-plugin/styles.css new file mode 100644 index 00000000..5c0e9dad --- /dev/null +++ b/obsidian-plugin/styles.css @@ -0,0 +1,39 @@ +.tnmso-status { + align-items: center; + color: var(--text-muted); + cursor: pointer; + display: inline-flex; + min-height: 24px; + min-width: 24px; + justify-content: center; +} + +.tnmso-status:hover, +.tnmso-status:focus-visible, +.tnmso-status--enabled { + color: var(--interactive-accent); +} + +.tnmso-status--warning, +.tnmso-setting-error { + color: var(--text-warning); +} + +.tnmso-status--off { + color: var(--text-faint); +} + +.tnmso-status--hidden { + display: none; +} + +.tnmso-scope-control, +.tnmso-scope-control textarea { + width: min(100%, 520px); +} + +.tnmso-scope-control textarea { + font-family: var(--font-monospace); + min-height: 160px; + resize: vertical; +} diff --git a/obsidian-plugin/tsconfig.json b/obsidian-plugin/tsconfig.json new file mode 100644 index 00000000..afab7c5e --- /dev/null +++ b/obsidian-plugin/tsconfig.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "noUncheckedIndexedAccess": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2022", + "types": ["bun", "node"] + }, + "include": ["src/**/*.ts", "scripts/**/*.ts", "*.ts"] +} diff --git a/obsidian-plugin/versions.json b/obsidian-plugin/versions.json new file mode 100644 index 00000000..01b874bb --- /dev/null +++ b/obsidian-plugin/versions.json @@ -0,0 +1,4 @@ +{ + "2026.10801.0": "1.13.4", + "2026.10805.0": "1.13.4" +} diff --git a/package.json b/package.json index 88eb9bf3..a642d91a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@truenine/memory-sync", - "version": "2026.10801.0", + "version": "2026.10805.0", "description": "Cross-AI-tool prompt synchronisation toolkit (CLI + Tauri desktop GUI) — one ruleset, multi-target adaptation. Monorepo powered by pnpm + Turbo.", "license": "AGPL-3.0-only", "keywords": [ @@ -41,7 +41,7 @@ "rust": ">= 1.88.0" }, "simple-git-hooks": { - "pre-commit": "pnpm tsx .githooks/sync-versions.ts" + "pre-commit": "bun .githooks/sync-versions.ts" }, "packageManager": "pnpm@11.18.0", "devDependencies": { diff --git a/scripts/shared/check-version-surfaces.ts b/scripts/shared/check-version-surfaces.ts index 8ba60a66..9d1a4615 100644 --- a/scripts/shared/check-version-surfaces.ts +++ b/scripts/shared/check-version-surfaces.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env tsx +#!/usr/bin/env bun import {readFileSync, readdirSync} from 'node:fs' import path from 'node:path' import process from 'node:process' @@ -62,6 +62,21 @@ function checkJsonVersion(relativePath: string): void { ensure(version === expectedVersion, `${relativePath} has version ${String(version)}, expected ${expectedVersion}`) } +function checkObsidianReleaseMetadata(): void { + const pluginManifest = readJson('obsidian-plugin/manifest.json') + const rootManifest = readJson('manifest.json') + const pluginVersions = readJson('obsidian-plugin/versions.json') + const rootVersions = readJson('versions.json') + const minAppVersion = pluginManifest.minAppVersion + + ensure(pluginManifest.id === 'tnmso', 'obsidian-plugin/manifest.json must use id=tnmso') + ensure(pluginManifest.version === expectedVersion, `obsidian-plugin/manifest.json expected version ${expectedVersion}`) + ensure(typeof minAppVersion === 'string' && minAppVersion !== '', 'TNMSO minAppVersion is required') + ensure(JSON.stringify(rootManifest) === JSON.stringify(pluginManifest), 'Root manifest.json must mirror the TNMSO manifest') + ensure(pluginVersions[expectedVersion] === minAppVersion, `obsidian-plugin/versions.json must map ${expectedVersion} to ${String(minAppVersion)}`) + ensure(JSON.stringify(rootVersions) === JSON.stringify(pluginVersions), 'Root versions.json must mirror TNMSO versions.json') +} + function checkWorkspaceCargoVersion(relativePath: string, sectionName: string, key = 'version'): void { const value = extractTomlValue(readText(relativePath), sectionName, key) ensure(value === expectedVersion, `${relativePath} has ${sectionName}.${key}=${String(value)}, expected ${expectedVersion}`) @@ -100,7 +115,9 @@ try { checkJsonVersion('mcp/package.json') checkJsonVersion('gui/package.json') checkJsonVersion('doc/package.json') + checkJsonVersion('obsidian-plugin/package.json') checkJsonVersion('gui/src-tauri/tauri.conf.json') + checkObsidianReleaseMetadata() for (const entry of readdirSync(path.join(rootDir, 'cli', 'npm'), {withFileTypes: true})) { if (!entry.isDirectory()) continue diff --git a/sdk/src/domain/output_plans/claude_code_output_plan.rs b/sdk/src/domain/output_plans/claude_code_output_plan.rs index 6c91b173..13582e12 100644 --- a/sdk/src/domain/output_plans/claude_code_output_plan.rs +++ b/sdk/src/domain/output_plans/claude_code_output_plan.rs @@ -722,7 +722,8 @@ fn build_cleanup(workspace: &Workspace, _context: &OutputContext) -> CleanupDecl resolve_project_root_dir(workspace, candidate) .as_ref() .is_some_and(|candidate_root_dir| candidate_root_dir == &project_root_dir) - }) && let Some(child_prompts) = prompt_project.child_memory_prompts.as_ref() { + }) && let Some(child_prompts) = prompt_project.child_memory_prompts.as_ref() + { for child_prompt in child_prompts { delete.push(CleanupTargetDto { path: resolve_relative_path(&child_prompt.dir) diff --git a/sdk/src/domain/output_plans/mod.rs b/sdk/src/domain/output_plans/mod.rs index 66e7d342..469ecd08 100644 --- a/sdk/src/domain/output_plans/mod.rs +++ b/sdk/src/domain/output_plans/mod.rs @@ -215,11 +215,9 @@ mod regression_tests { crate::domain::output_plans::claude_code_output_plan::build_claude_code_output_plan(&context) .unwrap(); assert!( - claude_plan - .output_files - .iter() - .any(|file| file.path == format!("{project_root}/CLAUDE.md") - && file.content == "project root"), + claude_plan.output_files.iter().any( + |file| file.path == format!("{project_root}/CLAUDE.md") && file.content == "project root" + ), "claude project CLAUDE.md must keep project memory when AgentsOutputAdaptor is active" ); assert!( @@ -245,8 +243,7 @@ mod regression_tests { .unwrap(); assert!( opencode_plan.output_files.iter().any(|file| { - file.path == format!("{project_root}/.opencode/AGENTS.md") - && file.content == "project root" + file.path == format!("{project_root}/.opencode/AGENTS.md") && file.content == "project root" }), "opencode project AGENTS.md must keep project memory when AgentsOutputAdaptor is active" ); @@ -269,11 +266,9 @@ mod regression_tests { let codex_plan = crate::domain::output_plans::codex_output_plan::build_codex_output_plan(&context).unwrap(); assert!( - codex_plan - .output_files - .iter() - .any(|file| file.path == format!("{project_root}/AGENTS.md") - && file.content == "project root"), + codex_plan.output_files.iter().any( + |file| file.path == format!("{project_root}/AGENTS.md") && file.content == "project root" + ), "codex project AGENTS.md must keep project memory when AgentsOutputAdaptor is active" ); assert!( diff --git a/sdk/src/domain/output_plans/warp_output_plan.rs b/sdk/src/domain/output_plans/warp_output_plan.rs index d6dd21bc..6ff867f7 100644 --- a/sdk/src/domain/output_plans/warp_output_plan.rs +++ b/sdk/src/domain/output_plans/warp_output_plan.rs @@ -118,12 +118,14 @@ mod tests { .collect::>(); assert!(delete_paths.contains(&workspace_dir.join("WARP.md").to_string_lossy().as_ref())); - assert!(delete_paths.contains( - &workspace_dir - .join("project-a") - .join("WARP.md") - .to_string_lossy() - .as_ref() - )); + assert!( + delete_paths.contains( + &workspace_dir + .join("project-a") + .join("WARP.md") + .to_string_lossy() + .as_ref() + ) + ); } } diff --git a/sdk/src/infra/git_fs.rs b/sdk/src/infra/git_fs.rs index cc050b80..d3cea26d 100644 --- a/sdk/src/infra/git_fs.rs +++ b/sdk/src/infra/git_fs.rs @@ -13,7 +13,15 @@ pub fn resolve_git_info_dir(project_dir: &Path) -> Option { Some(repo.path().join("info")) } -const SKIP_DIRS: &[&str] = &[".git", "node_modules", ".turbo", "dist", "build", "out", ".cache"]; +const SKIP_DIRS: &[&str] = &[ + ".git", + "node_modules", + ".turbo", + "dist", + "build", + "out", + ".cache", +]; /// Walks the filesystem tree under `root_dir` up to `max_depth` deep and returns /// all directories that contain a valid git repository (excluding the root itself). @@ -77,7 +85,12 @@ mod tests { let dot_git = tmp.path().join(".git"); let result = resolve_git_info_dir(tmp.path()); - assert_eq!(result, Some(dot_git.join("info")), "regular repo: {:?}", result); + assert_eq!( + result, + Some(dot_git.join("info")), + "regular repo: {:?}", + result + ); } #[test] @@ -115,7 +128,11 @@ mod tests { fs::write(&dot_git, "gitdir: ../worktrees/feature/.git\n").unwrap(); let result = resolve_git_info_dir(&sub_dir); - assert!(result.is_some(), "relative gitlink should resolve: {:?}", result); + assert!( + result.is_some(), + "relative gitlink should resolve: {:?}", + result + ); let result_path = result.unwrap(); assert_eq!( result_path.file_name().unwrap().to_string_lossy(), @@ -157,7 +174,10 @@ mod tests { let _repo = git2::Repository::init(root).unwrap(); let result = find_all_git_repos(root, 5); - assert!(result.is_empty(), "root should be excluded even when it is a repo: {result:?}"); + assert!( + result.is_empty(), + "root should be excluded even when it is a repo: {result:?}" + ); } #[test] @@ -170,7 +190,10 @@ mod tests { let _repo = git2::Repository::init(&node_modules).unwrap(); let result = find_all_git_repos(root, 5); - assert!(result.is_empty(), "repos inside SKIP_DIRS should not be found: {result:?}"); + assert!( + result.is_empty(), + "repos inside SKIP_DIRS should not be found: {result:?}" + ); } #[test] @@ -183,7 +206,10 @@ mod tests { let _repo = git2::Repository::init(&deep).unwrap(); let result = find_all_git_repos(root, 3); - assert!(result.is_empty(), "depth 3 should not find depth 4 repo: {result:?}"); + assert!( + result.is_empty(), + "depth 3 should not find depth 4 repo: {result:?}" + ); let result = find_all_git_repos(root, 4); assert_eq!(result.len(), 1, "depth 4 should find repo"); diff --git a/sdk/src/infra/md_compiler/expression_eval.rs b/sdk/src/infra/md_compiler/expression_eval.rs index 48ae6acc..457f834a 100644 --- a/sdk/src/infra/md_compiler/expression_eval.rs +++ b/sdk/src/infra/md_compiler/expression_eval.rs @@ -305,7 +305,9 @@ pub fn evaluate_interpolations(text: &str, scope: &EvaluationScope) -> String { while j < text.len() { // Fixes #183: use let-else instead of unwrap() for safer char iteration - let Some(c) = text[j..].chars().next() else { break; }; + let Some(c) = text[j..].chars().next() else { + break; + }; match c { '\'' if !in_double_quote && !in_backtick => in_single_quote = !in_single_quote, '"' if !in_single_quote && !in_backtick => in_double_quote = !in_double_quote, diff --git a/sdk/src/repositories/project_prompt.rs b/sdk/src/repositories/project_prompt.rs index 08843e7c..7e0e9d9b 100644 --- a/sdk/src/repositories/project_prompt.rs +++ b/sdk/src/repositories/project_prompt.rs @@ -29,9 +29,8 @@ const PROJECT_MEMORY_FILE: &str = "agt.mdx"; const SCAN_SKIP_DIRECTORIES: &[&str] = &["node_modules", ".git"]; // Fixes #185: compile regex once via LazyLock instead of per-call -static FRONT_MATTER_REGEX: LazyLock> = LazyLock::new(|| { - regex_lite::Regex::new(r"(?s)^---\r?\n(.*?)\r?\n---(?:(?:\r?\n){1,2}|$)").ok() -}); +static FRONT_MATTER_REGEX: LazyLock> = + LazyLock::new(|| regex_lite::Regex::new(r"(?s)^---\r?\n(.*?)\r?\n---(?:(?:\r?\n){1,2}|$)").ok()); fn extract_front_matter(raw_mdx: &str) -> (Option, Option) { let front_matter_regex = FRONT_MATTER_REGEX.as_ref(); diff --git a/sdk/src/repositories/skill.rs b/sdk/src/repositories/skill.rs index b75b5d51..a43bb20a 100644 --- a/sdk/src/repositories/skill.rs +++ b/sdk/src/repositories/skill.rs @@ -38,9 +38,8 @@ struct CategoryDescriptionFiles { } // Fixes #184: compile regexes once via LazyLock instead of per-call -static MDX_REFERENCE_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r"(!?\[)([^\]]*?)(\]\()([^)]+)(\))").unwrap() -}); +static MDX_REFERENCE_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r"(!?\[)([^\]]*?)(\]\()([^)]+)(\))").unwrap()); fn transform_mdx_references_to_md(content: &str) -> String { let re = &*MDX_REFERENCE_REGEX; @@ -62,9 +61,8 @@ fn transform_mdx_references_to_md(content: &str) -> String { } // Fixes #184: compile regex once via LazyLock -static SKILL_FRONT_MATTER_REGEX: LazyLock> = LazyLock::new(|| { - regex_lite::Regex::new(r"(?s)^---\r?\n(.*?)\r?\n---(?:(?:\r?\n){1,2}|$)").ok() -}); +static SKILL_FRONT_MATTER_REGEX: LazyLock> = + LazyLock::new(|| regex_lite::Regex::new(r"(?s)^---\r?\n(.*?)\r?\n---(?:(?:\r?\n){1,2}|$)").ok()); fn extract_front_matter(raw_mdx: &str) -> (Option, Option) { let front_matter_regex = SKILL_FRONT_MATTER_REGEX.as_ref(); @@ -81,27 +79,20 @@ fn extract_front_matter(raw_mdx: &str) -> (Option, Option) { } // Fixes #184: compile regexes once via LazyLock -static EXPORT_DEFAULT_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r"export\s+default\s*\{([\s\S]*?)\}").unwrap() -}); -static SKILL_DESC_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r#"description\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap() -}); -static NAME_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r#"name\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap() -}); -static DISPLAY_NAME_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r#"displayName\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap() -}); -static KEYWORDS_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r"keywords\s*:\s*\[([^\]]+)\]").unwrap() -}); -static AUTHOR_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r#"author\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap() -}); -static VERSION_REGEX: LazyLock = LazyLock::new(|| { - regex_lite::Regex::new(r#"version\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap() -}); +static EXPORT_DEFAULT_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r"export\s+default\s*\{([\s\S]*?)\}").unwrap()); +static SKILL_DESC_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r#"description\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap()); +static NAME_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r#"name\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap()); +static DISPLAY_NAME_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r#"displayName\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap()); +static KEYWORDS_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r"keywords\s*:\s*\[([^\]]+)\]").unwrap()); +static AUTHOR_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r#"author\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap()); +static VERSION_REGEX: LazyLock = + LazyLock::new(|| regex_lite::Regex::new(r#"version\s*:\s*['\"`]([^'\"`]+)['\"`]"#).unwrap()); fn extract_skill_metadata_from_export(content: &str) -> Value { let mut metadata = serde_json::Map::new(); @@ -167,12 +158,10 @@ fn extract_skill_metadata_from_export(content: &str) -> Value { } // Fixes #184: compile regexes once via LazyLock -static DEFAULT_DESC_REGEX: LazyLock> = LazyLock::new(|| { - regex_lite::Regex::new(r#"description\s*:\s*['"`]([^'"`]+)['"`]"#).ok() -}); -static DESC_EXPORT_DEFAULT_REGEX: LazyLock> = LazyLock::new(|| { - regex_lite::Regex::new(r"export\s+default\s*\{([\s\S]*?)\}").ok() -}); +static DEFAULT_DESC_REGEX: LazyLock> = + LazyLock::new(|| regex_lite::Regex::new(r#"description\s*:\s*['"`]([^'"`]+)['"`]"#).ok()); +static DESC_EXPORT_DEFAULT_REGEX: LazyLock> = + LazyLock::new(|| regex_lite::Regex::new(r"export\s+default\s*\{([\s\S]*?)\}").ok()); static NAMED_EXPORT_DESC_REGEX: LazyLock> = LazyLock::new(|| { regex_lite::Regex::new(r#"export\s+(?:const|let)\s+description\s*=\s*['"`]([^'"`]+)['"`]"#).ok() }); @@ -197,9 +186,8 @@ fn extract_description_from_exports(content: &str) -> Option { } // Fixes #184: compile regex once via LazyLock -static STRIP_FRONT_MATTER_REGEX: LazyLock> = LazyLock::new(|| { - regex_lite::Regex::new(r"(?s)^---\r?\n.*?\r?\n---(?:(?:\r?\n){1,2}|$)").ok() -}); +static STRIP_FRONT_MATTER_REGEX: LazyLock> = + LazyLock::new(|| regex_lite::Regex::new(r"(?s)^---\r?\n.*?\r?\n---(?:(?:\r?\n){1,2}|$)").ok()); fn strip_leading_front_matter(content: &str) -> &str { let front_matter_regex = STRIP_FRONT_MATTER_REGEX.as_ref(); @@ -212,13 +200,13 @@ fn strip_leading_front_matter(content: &str) -> &str { } // Fixes #184: compile regexes once via LazyLock -static STRIP_EXPORT_DEFAULT_REGEX: LazyLock> = LazyLock::new(|| { - regex_lite::Regex::new(r"(?s)^\s*export\s+default\s*\{[\s\S]*?\}\s*;?\s*").ok() -}); +static STRIP_EXPORT_DEFAULT_REGEX: LazyLock> = + LazyLock::new(|| regex_lite::Regex::new(r"(?s)^\s*export\s+default\s*\{[\s\S]*?\}\s*;?\s*").ok()); static STRIP_NAMED_EXPORT_REGEX: LazyLock> = LazyLock::new(|| { regex_lite::Regex::new( r#"(?m)^\s*export\s+(?:const|let)\s+description\s*=\s*['"`][^'"`]+['"`]\s*;?\s*$\n?"#, - ).ok() + ) + .ok() }); fn strip_leading_export_statements(content: &str) -> String { diff --git a/sdk/src/services/clean_service.rs b/sdk/src/services/clean_service.rs index 40a86b29..0ef5b67e 100644 --- a/sdk/src/services/clean_service.rs +++ b/sdk/src/services/clean_service.rs @@ -25,7 +25,7 @@ pub fn clean(options: MemorySyncCommandOptions) -> Result Result Result Result<(), String> { let hooks_dir = format!("{}/hooks", git_dir_path); let hook_content = r#"#!/bin/sh # Version sync hook - auto-installed by memory-sync-xtask -exec tsx "$PWD/.githooks/sync-versions.ts" "$1" +exec bun "$PWD/.githooks/sync-versions.ts" "$1" "#; std::fs::create_dir_all(&hooks_dir).map_err(|e| format!("Failed to create hooks dir: {}", e))?; From 6c73b275299ce835df2ce00bf10be2a23f531090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E6=97=A5=E5=A4=A9?= Date: Thu, 6 Aug 2026 00:22:03 +0800 Subject: [PATCH 2/5] fix(ci): restore release gate checks --- .github/actions/setup-rust/action.yml | 2 +- doc/app/docs/[[...mdxPath]]/layout.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/setup-rust/action.yml b/.github/actions/setup-rust/action.yml index b178482a..14bbec2b 100644 --- a/.github/actions/setup-rust/action.yml +++ b/.github/actions/setup-rust/action.yml @@ -26,7 +26,7 @@ runs: uses: dtolnay/rust-toolchain@stable with: toolchain: ${{ inputs.rust-version }} - components: rustfmt + components: rustfmt,clippy targets: ${{ inputs.targets }} - name: Cache cargo diff --git a/doc/app/docs/[[...mdxPath]]/layout.tsx b/doc/app/docs/[[...mdxPath]]/layout.tsx index 571999f0..ee369d1f 100644 --- a/doc/app/docs/[[...mdxPath]]/layout.tsx +++ b/doc/app/docs/[[...mdxPath]]/layout.tsx @@ -4,7 +4,7 @@ import {DocsSectionNav} from '../../../components/docs-section-nav' import {isDocSectionName} from '../../../lib/docs-sections' import {siteConfig, withBasePath} from '../../../lib/site' -type PageMapItem = { +interface PageMapItem { readonly name?: string readonly route?: string readonly title?: string @@ -15,7 +15,7 @@ function DocsSidebar({pageMap}: {readonly pageMap: readonly PageMapItem[]}) { return (