From 726603276be8fc2c2571fa00a3e5900fb12ed5ea Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 23 Feb 2026 20:19:22 +0000 Subject: [PATCH 01/17] =?UTF-8?q?feat:=20implement=20Phase=201=20=E2=80=94?= =?UTF-8?q?=20extension=20scaffold,=20language=20promotion,=20TextMate=20g?= =?UTF-8?q?rammar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bootstraps the Hexfield Text VS Code extension with all Phase 1 deliverables: - package.json: extension manifest declaring the hexfield-markdown language ID, wiring the TextMate grammar, activation events (onLanguage:markdown + onStartupFinished), esbuild/TypeScript/ESLint/Prettier toolchain - tsconfig.json: strict TypeScript config targeting ES2022 / Node16 modules - esbuild.js: production + watch build script (output: dist/extension.js) - language-configuration.json: bracket/autoclosing pairs mirroring markdown - syntaxes/hexfield-deck.tmLanguage.json: TextMate grammar scoped exclusively to hexfield-markdown; covers project tags (#word), due date brackets ([YYYY-MM-DD]), priority markers (!!!/!!/!), time estimates (est:Xh/Xm), in-progress checkbox ([/]), and frontmatter keys; includes text.html.markdown to preserve all built-in markdown features - src/extension.ts: activate() registers listeners for onDidOpenTextDocument, onDidChangeTextDocument, and onDidChangeActiveTextEditor; reads YAML frontmatter, calls setTextDocumentLanguage to promote/demote between markdown and hexfield-markdown based on type: hexfield-planner - src/decorators/: Phase 2 stubs (DueDateDecorator) to establish directory structure for dynamic due date proximity coloring - .eslintrc.json, .prettierrc, .vscodeignore, .gitignore: project tooling config https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- .eslintrc.json | 19 +++++ .gitignore | 5 ++ .prettierrc | 7 ++ .vscodeignore | 11 +++ esbuild.js | 34 +++++++++ language-configuration.json | 27 +++++++ package.json | 67 ++++++++++++++++ src/decorators/dueDateDecorator.ts | 20 +++++ src/decorators/index.ts | 2 + src/extension.ts | 101 +++++++++++++++++++++++++ syntaxes/hexfield-deck.tmLanguage.json | 86 +++++++++++++++++++++ tsconfig.json | 15 ++++ 12 files changed, 394 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 .vscodeignore create mode 100644 esbuild.js create mode 100644 language-configuration.json create mode 100644 package.json create mode 100644 src/decorators/dueDateDecorator.ts create mode 100644 src/decorators/index.ts create mode 100644 src/extension.ts create mode 100644 syntaxes/hexfield-deck.tmLanguage.json create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..5c6f12b --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2022, + "sourceType": "module", + "project": "./tsconfig.json" + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/explicit-function-return-type": "warn", + "no-console": "warn" + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b9a017 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +*.vsix +out/ +.DS_Store diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..4cbc711 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": true, + "trailingComma": "all", + "printWidth": 100, + "tabWidth": 2 +} diff --git a/.vscodeignore b/.vscodeignore new file mode 100644 index 0000000..61eafd2 --- /dev/null +++ b/.vscodeignore @@ -0,0 +1,11 @@ +.vscode/** +src/** +node_modules/** +.eslintrc.json +.prettierrc +tsconfig.json +esbuild.js +*.map +.gitignore +**/*.ts +!dist/** diff --git a/esbuild.js b/esbuild.js new file mode 100644 index 0000000..e0262ff --- /dev/null +++ b/esbuild.js @@ -0,0 +1,34 @@ +// @ts-check +const esbuild = require('esbuild'); + +const production = process.argv.includes('--production'); +const watch = process.argv.includes('--watch'); + +/** @type {import('esbuild').BuildOptions} */ +const buildOptions = { + entryPoints: ['src/extension.ts'], + bundle: true, + outfile: 'dist/extension.js', + external: ['vscode'], + format: 'cjs', + platform: 'node', + target: 'node18', + sourcemap: !production, + minify: production, +}; + +async function main() { + if (watch) { + const ctx = await esbuild.context(buildOptions); + await ctx.watch(); + console.log('Watching for changes…'); + } else { + await esbuild.build(buildOptions); + console.log(production ? 'Production build complete.' : 'Development build complete.'); + } +} + +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/language-configuration.json b/language-configuration.json new file mode 100644 index 0000000..d056028 --- /dev/null +++ b/language-configuration.json @@ -0,0 +1,27 @@ +{ + "comments": {}, + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + "autoClosingPairs": [ + { "open": "{", "close": "}" }, + { "open": "[", "close": "]" }, + { "open": "(", "close": ")" }, + { "open": "`", "close": "`", "notIn": ["string"] }, + { "open": "*", "close": "*", "notIn": ["string"] }, + { "open": "_", "close": "_", "notIn": ["string"] } + ], + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["`", "`"], + ["*", "*"], + ["_", "_"], + ["\"", "\""], + ["'", "'"] + ], + "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\$\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\<\\>\\?\\/\\s]+)" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a137e6d --- /dev/null +++ b/package.json @@ -0,0 +1,67 @@ +{ + "name": "hexfield-text", + "displayName": "Hexfield Text", + "description": "Inline syntax colorization for Hexfield Deck planner files in VS Code", + "version": "0.1.0", + "publisher": "jimblom", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/jimblom/hexfield-text.git" + }, + "bugs": { + "url": "https://github.com/jimblom/hexfield-text/issues" + }, + "engines": { + "vscode": "^1.75.0" + }, + "categories": ["Other"], + "keywords": ["markdown", "kanban", "hexfield", "task board", "syntax highlighting"], + "activationEvents": [ + "onLanguage:markdown", + "onStartupFinished" + ], + "main": "./dist/extension.js", + "contributes": { + "languages": [ + { + "id": "hexfield-markdown", + "aliases": ["Hexfield Markdown", "hexfield-markdown"], + "configuration": "./language-configuration.json" + } + ], + "grammars": [ + { + "language": "hexfield-markdown", + "scopeName": "text.hexfield.markdown", + "path": "./syntaxes/hexfield-deck.tmLanguage.json", + "embeddedLanguages": { + "meta.embedded.block.html": "html", + "meta.embedded.block.javascript": "javascript", + "meta.embedded.block.css": "css" + } + } + ] + }, + "scripts": { + "build": "node esbuild.js --production", + "watch": "node esbuild.js --watch", + "package": "vsce package --no-dependencies", + "lint": "eslint src --ext .ts", + "format": "prettier --write \"src/**/*.ts\"" + }, + "devDependencies": { + "@types/vscode": "^1.75.0", + "@types/node": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^6.0.0", + "@typescript-eslint/parser": "^6.0.0", + "@vscode/vsce": "^2.0.0", + "esbuild": "^0.20.0", + "eslint": "^8.0.0", + "prettier": "^3.0.0", + "typescript": "^5.0.0" + }, + "volta": { + "node": "20.11.0" + } +} diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts new file mode 100644 index 0000000..9906ad0 --- /dev/null +++ b/src/decorators/dueDateDecorator.ts @@ -0,0 +1,20 @@ +// Phase 2 — Dynamic due date proximity colorization via the Decoration API. +// +// The decorator scans hexfield-markdown documents for [YYYY-MM-DD] tokens, +// computes proximity relative to today, and applies one of four colors that +// mirror Hexfield Deck's board badge colors exactly: +// +// Overdue (date < today) → Red (#F44747) +// Today → Orange (#CE9178) +// Within 3 days → Yellow (#CCA700) +// Future → Gray (#858585) +// +// The decorator is debounced at 500ms and re-runs on every document change. + +import * as vscode from 'vscode'; + +export class DueDateDecorator { + dispose(): void { + // Phase 2: clean up TextEditorDecorationType instances + } +} diff --git a/src/decorators/index.ts b/src/decorators/index.ts new file mode 100644 index 0000000..a39bd31 --- /dev/null +++ b/src/decorators/index.ts @@ -0,0 +1,2 @@ +// Phase 2: Due date proximity colorization +export { DueDateDecorator } from './dueDateDecorator'; diff --git a/src/extension.ts b/src/extension.ts new file mode 100644 index 0000000..3f1eb1e --- /dev/null +++ b/src/extension.ts @@ -0,0 +1,101 @@ +import * as vscode from 'vscode'; + +const HEXFIELD_LANGUAGE_ID = 'hexfield-markdown'; +const MARKDOWN_LANGUAGE_ID = 'markdown'; + +/** + * Matches the YAML frontmatter block at the very start of a file. + * Captures the block body (everything between the opening and closing ---). + */ +const FRONTMATTER_RE = /\A---\r?\n([\s\S]*?)\r?\n---/; + +/** + * Matches the `type: hexfield-planner` line anywhere within a frontmatter block body. + */ +const HEXFIELD_TYPE_RE = /^type:\s*hexfield-planner\s*$/m; + +/** + * Returns true when the document has `type: hexfield-planner` in its YAML frontmatter. + * Only the first 2 KB are scanned — frontmatter is always at the top of the file. + */ +function hasHexfieldFrontmatter(document: vscode.TextDocument): boolean { + if (!document.fileName.endsWith('.md')) { + return false; + } + const head = document.getText().slice(0, 2048); + const match = FRONTMATTER_RE.exec(head); + if (!match) { + return false; + } + return HEXFIELD_TYPE_RE.test(match[1]); +} + +/** + * Promotes a markdown document to the hexfield-markdown language ID when the + * file contains `type: hexfield-planner` frontmatter. + */ +async function promoteIfHexfield(document: vscode.TextDocument): Promise { + if (document.languageId !== MARKDOWN_LANGUAGE_ID) { + return; + } + if (hasHexfieldFrontmatter(document)) { + try { + await vscode.languages.setTextDocumentLanguage(document, HEXFIELD_LANGUAGE_ID); + } catch { + // Document may have been closed or is not promotable — ignore silently. + } + } +} + +/** + * Demotes a hexfield-markdown document back to markdown when the + * `type: hexfield-planner` frontmatter field has been removed. + */ +async function demoteIfNotHexfield(document: vscode.TextDocument): Promise { + if (document.languageId !== HEXFIELD_LANGUAGE_ID) { + return; + } + if (!hasHexfieldFrontmatter(document)) { + try { + await vscode.languages.setTextDocumentLanguage(document, MARKDOWN_LANGUAGE_ID); + } catch { + // Document may have been closed — ignore silently. + } + } +} + +export function activate(context: vscode.ExtensionContext): void { + // Process any .md documents that are already open when the extension activates. + for (const document of vscode.workspace.textDocuments) { + promoteIfHexfield(document); + } + + // Promote freshly opened markdown files. + context.subscriptions.push(vscode.workspace.onDidOpenTextDocument(promoteIfHexfield)); + + // Re-evaluate language ID when document content changes (e.g., frontmatter added/removed). + context.subscriptions.push( + vscode.workspace.onDidChangeTextDocument((event) => { + const { document } = event; + if (document.languageId === MARKDOWN_LANGUAGE_ID) { + promoteIfHexfield(document); + } else if (document.languageId === HEXFIELD_LANGUAGE_ID) { + demoteIfNotHexfield(document); + } + }), + ); + + // Catch files that were already open when VS Code started but the extension had + // not yet activated — they appear via onDidChangeActiveTextEditor. + context.subscriptions.push( + vscode.window.onDidChangeActiveTextEditor((editor) => { + if (editor) { + promoteIfHexfield(editor.document); + } + }), + ); +} + +export function deactivate(): void { + // Nothing to clean up — all disposables are tracked via context.subscriptions. +} diff --git a/syntaxes/hexfield-deck.tmLanguage.json b/syntaxes/hexfield-deck.tmLanguage.json new file mode 100644 index 0000000..397cc8c --- /dev/null +++ b/syntaxes/hexfield-deck.tmLanguage.json @@ -0,0 +1,86 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Hexfield Markdown", + "scopeName": "text.hexfield.markdown", + "patterns": [ + { "include": "#frontmatter" }, + { "include": "#hexfield-inline" }, + { "include": "text.html.markdown" } + ], + "repository": { + "frontmatter": { + "name": "meta.frontmatter.hexfield", + "begin": "\\A(---)", + "end": "^(---|\\.\\.\\.)", + "beginCaptures": { + "1": { "name": "punctuation.definition.tag.yaml" } + }, + "endCaptures": { + "1": { "name": "punctuation.definition.tag.yaml" } + }, + "patterns": [ + { + "comment": "Recognized Hexfield Deck frontmatter keys", + "match": "^(type|week|year|quarter|tags|startDate|endDate)(?=\\s*:)", + "captures": { + "1": { "name": "keyword.other.hexfield.frontmatter" } + } + } + ] + }, + + "hexfield-inline": { + "patterns": [ + { "include": "#in-progress-checkbox" }, + { "include": "#due-date" }, + { "include": "#estimate" }, + { "include": "#priority-high" }, + { "include": "#priority-med" }, + { "include": "#priority-low" }, + { "include": "#project-tag" } + ] + }, + + "in-progress-checkbox": { + "comment": "In-progress checkbox [/] — orange", + "match": "\\[/\\]", + "name": "markup.changed.hexfield.checkbox" + }, + + "due-date": { + "comment": "ISO date bracket [YYYY-MM-DD] — default gray; overridden by Decoration API", + "match": "\\[\\d{4}-\\d{2}-\\d{2}\\]", + "name": "string.quoted.hexfield.date" + }, + + "estimate": { + "comment": "Time estimate est:Xh or est:Xm (fractional supported) — teal", + "match": "\\best:\\d+(?:\\.\\d+)?[hm]\\b", + "name": "constant.numeric.hexfield.estimate" + }, + + "priority-high": { + "comment": "Priority HIGH !!! — red", + "match": "(? Date: Tue, 24 Feb 2026 02:07:39 +0000 Subject: [PATCH 02/17] =?UTF-8?q?feat:=20implement=20Phase=202=20=E2=80=94?= =?UTF-8?q?=20dynamic=20due=20date=20proximity=20decorator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the DueDateDecorator class and wires it into the extension activation to provide runtime date-proximity colorization that mirrors Hexfield Deck's board badge colors exactly. DueDateDecorator (src/decorators/dueDateDecorator.ts): - Scans documents for [YYYY-MM-DD] tokens using a global regex - Computes proximity of each date to today (evaluated at call time, never stale) - Buckets dates into four proximity categories: overdue (date < today) → Red (#F44747) today (date === today) → Orange (#CE9178) soon (1–3 days from now) → Yellow (#CCA700) future (> 3 days from now) → Gray (#858585) - Holds four TextEditorDecorationType instances (one per bucket) - Implements vscode.Disposable — all decoration types cleaned up on deactivation extension.ts updates: - Imports and instantiates DueDateDecorator; registers it in context.subscriptions - Decorates the active editor immediately on activation if already hexfield-markdown - Calls decorator.decorate() after language promotion so dates color on first open - Debounces re-decoration at 500ms on onDidChangeTextDocument (per spec) - Calls decorator.decorate() on onDidChangeActiveTextEditor for tab switches - Fixes FRONTMATTER_RE: \A is not a valid JS regex anchor; corrected to ^ with no multiline flag (anchors to start of the sliced string head) https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- src/decorators/dueDateDecorator.ts | 111 ++++++++++++++++++++++++++--- src/extension.ts | 77 +++++++++++++++----- 2 files changed, 158 insertions(+), 30 deletions(-) diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts index 9906ad0..e1caf9c 100644 --- a/src/decorators/dueDateDecorator.ts +++ b/src/decorators/dueDateDecorator.ts @@ -1,20 +1,109 @@ -// Phase 2 — Dynamic due date proximity colorization via the Decoration API. +// Dynamic due date proximity colorization via the VS Code Decoration API. // -// The decorator scans hexfield-markdown documents for [YYYY-MM-DD] tokens, -// computes proximity relative to today, and applies one of four colors that -// mirror Hexfield Deck's board badge colors exactly: +// Scans hexfield-markdown documents for [YYYY-MM-DD] tokens, computes proximity +// relative to today, and applies one of four colors that mirror Hexfield Deck's +// board badge colors exactly: // -// Overdue (date < today) → Red (#F44747) -// Today → Orange (#CE9178) -// Within 3 days → Yellow (#CCA700) -// Future → Gray (#858585) +// Overdue (date < today) → Red (#F44747) +// Today (date === today) → Orange (#CE9178) +// Soon (1–3 days from now) → Yellow (#CCA700) +// Future (> 3 days from now) → Gray (#858585) // -// The decorator is debounced at 500ms and re-runs on every document change. +// The decorator is debounced at 500ms by the caller and re-runs on every +// document change. All TextEditorDecorationType instances are disposed when +// the extension deactivates. import * as vscode from 'vscode'; -export class DueDateDecorator { +/** Matches `[YYYY-MM-DD]` anywhere in a document. Capture group 1 is the date string. */ +const DATE_BRACKET_RE = /\[(\d{4}-\d{2}-\d{2})\]/g; + +type Proximity = 'overdue' | 'today' | 'soon' | 'future'; + +/** Colors mirror Hexfield Deck board badge colors exactly. */ +const PROXIMITY_COLORS: Record = { + overdue: '#F44747', // Red + today: '#CE9178', // Orange + soon: '#CCA700', // Yellow + future: '#858585', // Gray +}; + +/** + * Computes proximity of an ISO date string (YYYY-MM-DD) relative to today. + * Today's date is evaluated at call time so decorations always reflect the + * current calendar day — no stale state across midnight. + */ +function getProximity(dateStr: string): Proximity { + const today = new Date(); + today.setHours(0, 0, 0, 0); + + const [year, month, day] = dateStr.split('-').map(Number); + const due = new Date(year, month - 1, day); + + const diffDays = Math.round((due.getTime() - today.getTime()) / 86_400_000); + + if (diffDays < 0) return 'overdue'; + if (diffDays === 0) return 'today'; + if (diffDays <= 3) return 'soon'; + return 'future'; +} + +/** + * Scans hexfield-markdown documents for `[YYYY-MM-DD]` tokens and applies + * proximity-based foreground color decorations. Implements vscode.Disposable + * so the four TextEditorDecorationType instances are cleaned up on deactivation. + */ +export class DueDateDecorator implements vscode.Disposable { + private readonly decorationTypes: Record; + + constructor() { + this.decorationTypes = { + overdue: vscode.window.createTextEditorDecorationType({ + color: PROXIMITY_COLORS.overdue, + }), + today: vscode.window.createTextEditorDecorationType({ + color: PROXIMITY_COLORS.today, + }), + soon: vscode.window.createTextEditorDecorationType({ + color: PROXIMITY_COLORS.soon, + }), + future: vscode.window.createTextEditorDecorationType({ + color: PROXIMITY_COLORS.future, + }), + }; + } + + /** + * Applies due date proximity decorations to the given editor. + * Safe to call on any editor — silently no-ops if no date tokens are found. + */ + decorate(editor: vscode.TextEditor): void { + const buckets: Record = { + overdue: [], + today: [], + soon: [], + future: [], + }; + + const text = editor.document.getText(); + DATE_BRACKET_RE.lastIndex = 0; + + let match: RegExpExecArray | null; + while ((match = DATE_BRACKET_RE.exec(text)) !== null) { + const proximity = getProximity(match[1]); + const start = editor.document.positionAt(match.index); + const end = editor.document.positionAt(match.index + match[0].length); + buckets[proximity].push(new vscode.Range(start, end)); + } + + for (const prox of Object.keys(buckets) as Proximity[]) { + editor.setDecorations(this.decorationTypes[prox], buckets[prox]); + } + } + dispose(): void { - // Phase 2: clean up TextEditorDecorationType instances + for (const type of Object.values(this.decorationTypes)) { + type.dispose(); + } } } diff --git a/src/extension.ts b/src/extension.ts index 3f1eb1e..5044bc8 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,13 +1,15 @@ import * as vscode from 'vscode'; +import { DueDateDecorator } from './decorators'; const HEXFIELD_LANGUAGE_ID = 'hexfield-markdown'; const MARKDOWN_LANGUAGE_ID = 'markdown'; /** * Matches the YAML frontmatter block at the very start of a file. - * Captures the block body (everything between the opening and closing ---). + * No multiline flag — ^ anchors to the start of the string (the sliced head). + * Capture group 1 is the block body between the opening and closing ---. */ -const FRONTMATTER_RE = /\A---\r?\n([\s\S]*?)\r?\n---/; +const FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---/; /** * Matches the `type: hexfield-planner` line anywhere within a frontmatter block body. @@ -32,24 +34,37 @@ function hasHexfieldFrontmatter(document: vscode.TextDocument): boolean { /** * Promotes a markdown document to the hexfield-markdown language ID when the - * file contains `type: hexfield-planner` frontmatter. + * file contains `type: hexfield-planner` frontmatter. After promotion, immediately + * applies due date decorations if the document is visible. */ -async function promoteIfHexfield(document: vscode.TextDocument): Promise { +async function promoteIfHexfield( + document: vscode.TextDocument, + decorator: DueDateDecorator, +): Promise { if (document.languageId !== MARKDOWN_LANGUAGE_ID) { return; } - if (hasHexfieldFrontmatter(document)) { - try { - await vscode.languages.setTextDocumentLanguage(document, HEXFIELD_LANGUAGE_ID); - } catch { - // Document may have been closed or is not promotable — ignore silently. + if (!hasHexfieldFrontmatter(document)) { + return; + } + try { + const promoted = await vscode.languages.setTextDocumentLanguage( + document, + HEXFIELD_LANGUAGE_ID, + ); + // Apply decorations immediately after promotion so dates are colored on first open. + const editor = vscode.window.visibleTextEditors.find((e) => e.document === promoted); + if (editor) { + decorator.decorate(editor); } + } catch { + // Document may have been closed or is not promotable — ignore silently. } } /** * Demotes a hexfield-markdown document back to markdown when the - * `type: hexfield-planner` frontmatter field has been removed. + * `type: hexfield-planner` frontmatter field has been removed or changed. */ async function demoteIfNotHexfield(document: vscode.TextDocument): Promise { if (document.languageId !== HEXFIELD_LANGUAGE_ID) { @@ -65,32 +80,56 @@ async function demoteIfNotHexfield(document: vscode.TextDocument): Promise } export function activate(context: vscode.ExtensionContext): void { - // Process any .md documents that are already open when the extension activates. + const decorator = new DueDateDecorator(); + context.subscriptions.push(decorator); + + // Decorate the active editor immediately if it's already hexfield-markdown + // (e.g., extension activated after the file was already open and promoted). + const activeEditor = vscode.window.activeTextEditor; + if (activeEditor?.document.languageId === HEXFIELD_LANGUAGE_ID) { + decorator.decorate(activeEditor); + } + + // Process any .md documents already open when the extension activates. for (const document of vscode.workspace.textDocuments) { - promoteIfHexfield(document); + promoteIfHexfield(document, decorator); } // Promote freshly opened markdown files. - context.subscriptions.push(vscode.workspace.onDidOpenTextDocument(promoteIfHexfield)); + context.subscriptions.push( + vscode.workspace.onDidOpenTextDocument((doc) => promoteIfHexfield(doc, decorator)), + ); + + // Debounce timer for re-decorating on content change (500ms, per spec). + let debounceTimer: ReturnType | undefined; - // Re-evaluate language ID when document content changes (e.g., frontmatter added/removed). + // Re-evaluate language ID and re-apply decorations when document content changes. context.subscriptions.push( vscode.workspace.onDidChangeTextDocument((event) => { const { document } = event; if (document.languageId === MARKDOWN_LANGUAGE_ID) { - promoteIfHexfield(document); + promoteIfHexfield(document, decorator); } else if (document.languageId === HEXFIELD_LANGUAGE_ID) { demoteIfNotHexfield(document); + const editor = vscode.window.visibleTextEditors.find((e) => e.document === document); + if (editor) { + clearTimeout(debounceTimer); + debounceTimer = setTimeout(() => decorator.decorate(editor), 500); + } } }), ); - // Catch files that were already open when VS Code started but the extension had - // not yet activated — they appear via onDidChangeActiveTextEditor. + // Decorate and/or promote when the user switches to a different editor tab. context.subscriptions.push( vscode.window.onDidChangeActiveTextEditor((editor) => { - if (editor) { - promoteIfHexfield(editor.document); + if (!editor) { + return; + } + if (editor.document.languageId === HEXFIELD_LANGUAGE_ID) { + decorator.decorate(editor); + } else { + promoteIfHexfield(editor.document, decorator); } }), ); From 905fb0a28060d055acc6147a0e0e1381ed697b86 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Feb 2026 02:27:47 +0000 Subject: [PATCH 03/17] ci: add GitHub Actions workflow for lint, type-check, build, and package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds .github/workflows/ci.yml that runs on every push to main and claude/** branches and on pull requests to main. Enforces project standards and produces a downloadable .vsix artifact for beta distribution. Steps: 1. pnpm/action-setup@v4 — installs pnpm 9 2. actions/setup-node@v4 — pins Node 20.11.0 (matches Volta config) 3. pnpm install — installs all devDependencies 4. format:check — prettier --check to verify formatting without modifying files 5. lint — eslint across src/ 6. typecheck — tsc --noEmit to catch type errors without emitting files 7. build — esbuild production bundle → dist/extension.js 8. package — vsce package --no-dependencies → hexfield-text-.vsix 9. Upload artifact — stored for 30 days, downloadable by any repo collaborator Also adds two scripts to package.json: typecheck: tsc --noEmit (used by CI step 6 and convenient locally) format:check: prettier --check (CI-safe counterpart to format --write) https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- .github/workflows/ci.yml | 58 ++++++++++++++++++++++++++++++++++++++++ package.json | 4 ++- 2 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..13678a8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +name: CI + +on: + push: + branches: + - main + - 'claude/**' + pull_request: + branches: + - main + +jobs: + ci: + name: Lint · type-check · build · package + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + version: 9 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20.11.0' + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Check formatting + run: pnpm format:check + + - name: Lint + run: pnpm lint + + - name: Type-check + run: pnpm typecheck + + - name: Build + run: pnpm build + + - name: Package (.vsix) + run: pnpm package + + - name: Upload .vsix artifact + uses: actions/upload-artifact@v4 + with: + name: hexfield-text-${{ github.sha }} + path: '*.vsix' + retention-days: 30 + if-no-files-found: error diff --git a/package.json b/package.json index a137e6d..b9bd558 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,10 @@ "build": "node esbuild.js --production", "watch": "node esbuild.js --watch", "package": "vsce package --no-dependencies", + "typecheck": "tsc --noEmit", "lint": "eslint src --ext .ts", - "format": "prettier --write \"src/**/*.ts\"" + "format": "prettier --write \"src/**/*.ts\"", + "format:check": "prettier --check \"src/**/*.ts\"" }, "devDependencies": { "@types/vscode": "^1.75.0", From 2262dd072c9473bde8aa872fed2d2f56c1ff8fe7 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Feb 2026 02:42:23 +0000 Subject: [PATCH 04/17] fix(ci): fix failing setup-node cache + auto-commit lockfile on first run Two problems with the previous workflow: 1. `cache: 'pnpm'` in actions/setup-node@v4 requires pnpm-lock.yaml to exist in the repo (it hashes it for the cache key). Without it the step errors: "Dependencies file is not found ... for pnpm". Removed that option and replaced it with explicit pnpm store path caching via actions/cache@v4, which gracefully falls back when no lockfile exists yet. 2. No lockfile was committed, so installs were non-deterministic and the store cache had no stable key. Added a "Commit lockfile if newly generated" step: after the first `pnpm install` on GitHub Actions generates pnpm-lock.yaml, the step commits and pushes it back to the branch under github-actions[bot]. Commits from that bot do not re-trigger CI, so there is no loop. Subsequent runs will have a locked, cacheable install. permissions bumped to contents: write on the job (needed for the bot push). https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13678a8..89b9a13 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: name: Lint · type-check · build · package runs-on: ubuntu-latest permissions: - contents: read + contents: write # write needed to commit pnpm-lock.yaml on first bootstrap run steps: - name: Checkout @@ -29,11 +29,39 @@ jobs: uses: actions/setup-node@v4 with: node-version: '20.11.0' - cache: 'pnpm' + # No cache: 'pnpm' here — that requires pnpm-lock.yaml to already exist. + # We cache the pnpm store directly below, which works with or without a lockfile. + + - name: Get pnpm store path + id: pnpm-store + run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT" + + - name: Cache pnpm store + uses: actions/cache@v4 + with: + path: ${{ steps.pnpm-store.outputs.path }} + key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm- - name: Install dependencies run: pnpm install + # On the first push after bootstrapping there is no lockfile in the repo. + # pnpm install generates one; this step commits it back so future runs get + # a fully deterministic, cacheable install. github-actions[bot] commits do + # not re-trigger CI, so there is no infinite loop. + - name: Commit lockfile if newly generated + if: github.event_name == 'push' + run: | + if ! git ls-files --error-unmatch pnpm-lock.yaml > /dev/null 2>&1; then + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git add pnpm-lock.yaml + git commit -m "chore: commit generated pnpm-lock.yaml" + git push + fi + - name: Check formatting run: pnpm format:check From 556572ca803dc6b32ef38cac9030f203f7d05f51 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 24 Feb 2026 02:42:48 +0000 Subject: [PATCH 05/17] chore: commit generated pnpm-lock.yaml --- pnpm-lock.yaml | 2751 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2751 insertions(+) create mode 100644 pnpm-lock.yaml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..ca9bd44 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2751 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@types/node': + specifier: ^18.0.0 + version: 18.19.130 + '@types/vscode': + specifier: ^1.75.0 + version: 1.109.0 + '@typescript-eslint/eslint-plugin': + specifier: ^6.0.0 + version: 6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': + specifier: ^6.0.0 + version: 6.21.0(eslint@8.57.1)(typescript@5.9.3) + '@vscode/vsce': + specifier: ^2.0.0 + version: 2.32.0 + esbuild: + specifier: ^0.20.0 + version: 0.20.2 + eslint: + specifier: ^8.0.0 + version: 8.57.1 + prettier: + specifier: ^3.0.0 + version: 3.8.1 + typescript: + specifier: ^5.0.0 + version: 5.9.3 + +packages: + + '@azure/abort-controller@2.1.2': + resolution: {integrity: sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==} + engines: {node: '>=18.0.0'} + + '@azure/core-auth@1.10.1': + resolution: {integrity: sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==} + engines: {node: '>=20.0.0'} + + '@azure/core-client@1.10.1': + resolution: {integrity: sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==} + engines: {node: '>=20.0.0'} + + '@azure/core-rest-pipeline@1.22.2': + resolution: {integrity: sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==} + engines: {node: '>=20.0.0'} + + '@azure/core-tracing@1.3.1': + resolution: {integrity: sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==} + engines: {node: '>=20.0.0'} + + '@azure/core-util@1.13.1': + resolution: {integrity: sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==} + engines: {node: '>=20.0.0'} + + '@azure/identity@4.13.0': + resolution: {integrity: sha512-uWC0fssc+hs1TGGVkkghiaFkkS7NkTxfnCH+Hdg+yTehTpMcehpok4PgUKKdyCH+9ldu6FhiHRv84Ntqj1vVcw==} + engines: {node: '>=20.0.0'} + + '@azure/logger@1.3.0': + resolution: {integrity: sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==} + engines: {node: '>=20.0.0'} + + '@azure/msal-browser@4.29.0': + resolution: {integrity: sha512-/f3eHkSNUTl6DLQHm+bKecjBKcRQxbd/XLx8lvSYp8Nl/HRyPuIPOijt9Dt0sH50/SxOwQ62RnFCmFlGK+bR/w==} + engines: {node: '>=0.8.0'} + + '@azure/msal-common@15.15.0': + resolution: {integrity: sha512-/n+bN0AKlVa+AOcETkJSKj38+bvFs78BaP4rNtv3MJCmPH0YrHiskMRe74OhyZ5DZjGISlFyxqvf9/4QVEi2tw==} + engines: {node: '>=0.8.0'} + + '@azure/msal-node@3.8.8': + resolution: {integrity: sha512-+f1VrJH1iI517t4zgmuhqORja0bL6LDQXfBqkjuMmfTYXTQQnh1EvwwxO3UbKLT05N0obF72SRHFrC1RBDv5Gg==} + engines: {node: '>=16'} + + '@esbuild/aix-ppc64@0.20.2': + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.20.2': + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.20.2': + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.20.2': + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.20.2': + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.20.2': + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.20.2': + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.20.2': + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.20.2': + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.20.2': + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.20.2': + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.20.2': + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.20.2': + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.20.2': + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.20.2': + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.20.2': + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.20.2': + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.20.2': + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.20.2': + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.20.2': + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.20.2': + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.20.2': + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.20.2': + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} + + '@types/vscode@1.109.0': + resolution: {integrity: sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw==} + + '@typescript-eslint/eslint-plugin@6.21.0': + resolution: {integrity: sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@6.21.0': + resolution: {integrity: sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@6.21.0': + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typescript-eslint/type-utils@6.21.0': + resolution: {integrity: sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@6.21.0': + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typescript-eslint/typescript-estree@6.21.0': + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@6.21.0': + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + + '@typescript-eslint/visitor-keys@6.21.0': + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + + '@typespec/ts-http-runtime@0.3.3': + resolution: {integrity: sha512-91fp6CAAJSRtH5ja95T1FHSKa8aPW9/Zw6cta81jlZTUw/+Vq8jM/AfF/14h2b71wwR84JUTW/3Y8QPhDAawFA==} + engines: {node: '>=20.0.0'} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@vscode/vsce-sign-alpine-arm64@2.0.6': + resolution: {integrity: sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==} + cpu: [arm64] + os: [alpine] + + '@vscode/vsce-sign-alpine-x64@2.0.6': + resolution: {integrity: sha512-YoAGlmdK39vKi9jA18i4ufBbd95OqGJxRvF3n6ZbCyziwy3O+JgOpIUPxv5tjeO6gQfx29qBivQ8ZZTUF2Ba0w==} + cpu: [x64] + os: [alpine] + + '@vscode/vsce-sign-darwin-arm64@2.0.6': + resolution: {integrity: sha512-5HMHaJRIQuozm/XQIiJiA0W9uhdblwwl2ZNDSSAeXGO9YhB9MH5C4KIHOmvyjUnKy4UCuiP43VKpIxW1VWP4tQ==} + cpu: [arm64] + os: [darwin] + + '@vscode/vsce-sign-darwin-x64@2.0.6': + resolution: {integrity: sha512-25GsUbTAiNfHSuRItoQafXOIpxlYj+IXb4/qarrXu7kmbH94jlm5sdWSCKrrREs8+GsXF1b+l3OB7VJy5jsykw==} + cpu: [x64] + os: [darwin] + + '@vscode/vsce-sign-linux-arm64@2.0.6': + resolution: {integrity: sha512-cfb1qK7lygtMa4NUl2582nP7aliLYuDEVpAbXJMkDq1qE+olIw/es+C8j1LJwvcRq1I2yWGtSn3EkDp9Dq5FdA==} + cpu: [arm64] + os: [linux] + + '@vscode/vsce-sign-linux-arm@2.0.6': + resolution: {integrity: sha512-UndEc2Xlq4HsuMPnwu7420uqceXjs4yb5W8E2/UkaHBB9OWCwMd3/bRe/1eLe3D8kPpxzcaeTyXiK3RdzS/1CA==} + cpu: [arm] + os: [linux] + + '@vscode/vsce-sign-linux-x64@2.0.6': + resolution: {integrity: sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==} + cpu: [x64] + os: [linux] + + '@vscode/vsce-sign-win32-arm64@2.0.6': + resolution: {integrity: sha512-ivM/MiGIY0PJNZBoGtlRBM/xDpwbdlCWomUWuLmIxbi1Cxe/1nooYrEQoaHD8ojVRgzdQEUzMsRbyF5cJJgYOg==} + cpu: [arm64] + os: [win32] + + '@vscode/vsce-sign-win32-x64@2.0.6': + resolution: {integrity: sha512-mgth9Kvze+u8CruYMmhHw6Zgy3GRX2S+Ed5oSokDEK5vPEwGGKnmuXua9tmFhomeAnhgJnL4DCna3TiNuGrBTQ==} + cpu: [x64] + os: [win32] + + '@vscode/vsce-sign@2.0.9': + resolution: {integrity: sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==} + + '@vscode/vsce@2.32.0': + resolution: {integrity: sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==} + engines: {node: '>= 16'} + hasBin: true + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + azure-devops-node-api@12.5.0: + resolution: {integrity: sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + cheerio-select@2.1.0: + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} + + cheerio@1.2.0: + resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} + engines: {node: '>=20.18.1'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + cockatiel@3.2.1: + resolution: {integrity: sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==} + engines: {node: '>=16'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@6.2.1: + resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} + engines: {node: '>= 6'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-select@5.2.2: + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + + domutils@3.2.2: + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + encoding-sniffer@0.2.1: + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + entities@2.1.0: + resolution: {integrity: sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.57.1: + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + hasBin: true + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} + engines: {node: '>=12', npm: '>=6'} + + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} + + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} + + keytar@7.9.0: + resolution: {integrity: sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + linkify-it@3.0.3: + resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + markdown-it@12.3.2: + resolution: {integrity: sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdurl@1.0.1: + resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimatch@3.1.3: + resolution: {integrity: sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==} + + minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-abi@3.87.0: + resolution: {integrity: sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==} + engines: {node: '>=10'} + + node-addon-api@4.3.0: + resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-semver@1.1.1: + resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} + + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} + + parse5-parser-stream@7.1.2: + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + deprecated: No longer maintained. Please contact the author of the relevant native addon; alternatives are available. + hasBin: true + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.15.0: + resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + + read@1.0.7: + resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} + engines: {node: '>=0.8'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.4.4: + resolution: {integrity: sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==} + engines: {node: '>=11.0.0'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + tar-fs@2.1.4: + resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-api-utils@1.4.3: + resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + tunnel@0.0.6: + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + typed-rest-client@1.8.11: + resolution: {integrity: sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + uc.micro@1.0.6: + resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} + + underscore@1.13.8: + resolution: {integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@7.22.0: + resolution: {integrity: sha512-RqslV2Us5BrllB+JeiZnK4peryVTndy9Dnqq62S3yYRRTj0tFQCwEniUy2167skdGOy3vqRzEvl1Dm4sV2ReDg==} + engines: {node: '>=20.18.1'} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-join@4.0.1: + resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yazl@2.5.1: + resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@azure/abort-controller@2.1.2': + dependencies: + tslib: 2.8.1 + + '@azure/core-auth@1.10.1': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-util': 1.13.1 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@azure/core-client@1.10.1': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.10.1 + '@azure/core-rest-pipeline': 1.22.2 + '@azure/core-tracing': 1.3.1 + '@azure/core-util': 1.13.1 + '@azure/logger': 1.3.0 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@azure/core-rest-pipeline@1.22.2': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.10.1 + '@azure/core-tracing': 1.3.1 + '@azure/core-util': 1.13.1 + '@azure/logger': 1.3.0 + '@typespec/ts-http-runtime': 0.3.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@azure/core-tracing@1.3.1': + dependencies: + tslib: 2.8.1 + + '@azure/core-util@1.13.1': + dependencies: + '@azure/abort-controller': 2.1.2 + '@typespec/ts-http-runtime': 0.3.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@azure/identity@4.13.0': + dependencies: + '@azure/abort-controller': 2.1.2 + '@azure/core-auth': 1.10.1 + '@azure/core-client': 1.10.1 + '@azure/core-rest-pipeline': 1.22.2 + '@azure/core-tracing': 1.3.1 + '@azure/core-util': 1.13.1 + '@azure/logger': 1.3.0 + '@azure/msal-browser': 4.29.0 + '@azure/msal-node': 3.8.8 + open: 10.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@azure/logger@1.3.0': + dependencies: + '@typespec/ts-http-runtime': 0.3.3 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@azure/msal-browser@4.29.0': + dependencies: + '@azure/msal-common': 15.15.0 + + '@azure/msal-common@15.15.0': {} + + '@azure/msal-node@3.8.8': + dependencies: + '@azure/msal-common': 15.15.0 + jsonwebtoken: 9.0.3 + uuid: 8.3.2 + + '@esbuild/aix-ppc64@0.20.2': + optional: true + + '@esbuild/android-arm64@0.20.2': + optional: true + + '@esbuild/android-arm@0.20.2': + optional: true + + '@esbuild/android-x64@0.20.2': + optional: true + + '@esbuild/darwin-arm64@0.20.2': + optional: true + + '@esbuild/darwin-x64@0.20.2': + optional: true + + '@esbuild/freebsd-arm64@0.20.2': + optional: true + + '@esbuild/freebsd-x64@0.20.2': + optional: true + + '@esbuild/linux-arm64@0.20.2': + optional: true + + '@esbuild/linux-arm@0.20.2': + optional: true + + '@esbuild/linux-ia32@0.20.2': + optional: true + + '@esbuild/linux-loong64@0.20.2': + optional: true + + '@esbuild/linux-mips64el@0.20.2': + optional: true + + '@esbuild/linux-ppc64@0.20.2': + optional: true + + '@esbuild/linux-riscv64@0.20.2': + optional: true + + '@esbuild/linux-s390x@0.20.2': + optional: true + + '@esbuild/linux-x64@0.20.2': + optional: true + + '@esbuild/netbsd-x64@0.20.2': + optional: true + + '@esbuild/openbsd-x64@0.20.2': + optional: true + + '@esbuild/sunos-x64@0.20.2': + optional: true + + '@esbuild/win32-arm64@0.20.2': + optional: true + + '@esbuild/win32-ia32@0.20.2': + optional: true + + '@esbuild/win32-x64@0.20.2': + optional: true + + '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': + dependencies: + eslint: 8.57.1 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.14.0 + debug: 4.4.3 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.3 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.57.1': {} + + '@humanwhocodes/config-array@0.13.0': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.4.3 + minimatch: 3.1.3 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + + '@types/json-schema@7.0.15': {} + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + + '@types/semver@7.7.1': {} + + '@types/vscode@1.109.0': {} + + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 6.21.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/type-utils': 6.21.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.3 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + semver: 7.7.4 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.3 + eslint: 8.57.1 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@6.21.0': + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + + '@typescript-eslint/type-utils@6.21.0(eslint@8.57.1)(typescript@5.9.3)': + dependencies: + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3) + '@typescript-eslint/utils': 6.21.0(eslint@8.57.1)(typescript@5.9.3) + debug: 4.4.3 + eslint: 8.57.1 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@6.21.0': {} + + '@typescript-eslint/typescript-estree@6.21.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.7.4 + ts-api-utils: 1.4.3(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@6.21.0(eslint@8.57.1)(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.1 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.9.3) + eslint: 8.57.1 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@6.21.0': + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + + '@typespec/ts-http-runtime@0.3.3': + dependencies: + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + tslib: 2.8.1 + transitivePeerDependencies: + - supports-color + + '@ungap/structured-clone@1.3.0': {} + + '@vscode/vsce-sign-alpine-arm64@2.0.6': + optional: true + + '@vscode/vsce-sign-alpine-x64@2.0.6': + optional: true + + '@vscode/vsce-sign-darwin-arm64@2.0.6': + optional: true + + '@vscode/vsce-sign-darwin-x64@2.0.6': + optional: true + + '@vscode/vsce-sign-linux-arm64@2.0.6': + optional: true + + '@vscode/vsce-sign-linux-arm@2.0.6': + optional: true + + '@vscode/vsce-sign-linux-x64@2.0.6': + optional: true + + '@vscode/vsce-sign-win32-arm64@2.0.6': + optional: true + + '@vscode/vsce-sign-win32-x64@2.0.6': + optional: true + + '@vscode/vsce-sign@2.0.9': + optionalDependencies: + '@vscode/vsce-sign-alpine-arm64': 2.0.6 + '@vscode/vsce-sign-alpine-x64': 2.0.6 + '@vscode/vsce-sign-darwin-arm64': 2.0.6 + '@vscode/vsce-sign-darwin-x64': 2.0.6 + '@vscode/vsce-sign-linux-arm': 2.0.6 + '@vscode/vsce-sign-linux-arm64': 2.0.6 + '@vscode/vsce-sign-linux-x64': 2.0.6 + '@vscode/vsce-sign-win32-arm64': 2.0.6 + '@vscode/vsce-sign-win32-x64': 2.0.6 + + '@vscode/vsce@2.32.0': + dependencies: + '@azure/identity': 4.13.0 + '@vscode/vsce-sign': 2.0.9 + azure-devops-node-api: 12.5.0 + chalk: 2.4.2 + cheerio: 1.2.0 + cockatiel: 3.2.1 + commander: 6.2.1 + form-data: 4.0.5 + glob: 7.2.3 + hosted-git-info: 4.1.0 + jsonc-parser: 3.3.1 + leven: 3.1.0 + markdown-it: 12.3.2 + mime: 1.6.0 + minimatch: 3.1.3 + parse-semver: 1.1.1 + read: 1.0.7 + semver: 7.7.4 + tmp: 0.2.5 + typed-rest-client: 1.8.11 + url-join: 4.0.1 + xml2js: 0.5.0 + yauzl: 2.10.0 + yazl: 2.5.1 + optionalDependencies: + keytar: 7.9.0 + transitivePeerDependencies: + - supports-color + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@7.1.4: {} + + ajv@6.14.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ansi-regex@5.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + array-union@2.1.0: {} + + asynckit@0.4.0: {} + + azure-devops-node-api@12.5.0: + dependencies: + tunnel: 0.0.6 + typed-rest-client: 1.8.11 + + balanced-match@1.0.2: {} + + base64-js@1.5.1: + optional: true + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + optional: true + + boolbase@1.0.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + optional: true + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.2.2 + css-what: 6.2.2 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.2.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.1 + htmlparser2: 10.1.0 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 7.22.0 + whatwg-mimetype: 4.0.0 + + chownr@1.1.4: + optional: true + + cockatiel@3.2.1: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@6.2.1: {} + + concat-map@0.0.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-what@6.2.2: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + optional: true + + deep-extend@0.6.0: + optional: true + + deep-is@0.1.4: {} + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + define-lazy-prop@3.0.0: {} + + delayed-stream@1.0.0: {} + + detect-libc@2.1.2: + optional: true + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domelementtype@2.3.0: {} + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + encoding-sniffer@0.2.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + optional: true + + entities@2.1.0: {} + + entities@4.5.0: {} + + entities@6.0.1: {} + + entities@7.0.1: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.20.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint@8.57.1: + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.12.2 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.3.0 + ajv: 6.14.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.3 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@9.6.1: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 3.4.3 + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + expand-template@2.0.3: + optional: true + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatted@3.3.3: {} + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + fs-constants@1.0.0: + optional: true + + fs.realpath@1.0.0: {} + + function-bind@1.1.2: {} + + 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 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + github-from-package@0.0.0: + optional: true + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.3 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graphemer@1.4.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hosted-git-info@4.1.0: + dependencies: + lru-cache: 6.0.0 + + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: + optional: true + + ignore@5.3.2: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + + ini@1.3.8: + optional: true + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + json-buffer@3.0.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + jsonc-parser@3.3.1: {} + + jsonwebtoken@9.0.3: + dependencies: + jws: 4.0.1 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.7.4 + + jwa@2.0.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.1: + dependencies: + jwa: 2.0.1 + safe-buffer: 5.2.1 + + keytar@7.9.0: + dependencies: + node-addon-api: 4.3.0 + prebuild-install: 7.1.3 + optional: true + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + leven@3.1.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + linkify-it@3.0.3: + dependencies: + uc.micro: 1.0.6 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + + lodash.merge@4.6.2: {} + + lodash.once@4.1.1: {} + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + markdown-it@12.3.2: + dependencies: + argparse: 2.0.1 + entities: 2.1.0 + linkify-it: 3.0.3 + mdurl: 1.0.1 + uc.micro: 1.0.6 + + math-intrinsics@1.1.0: {} + + mdurl@1.0.1: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mimic-response@3.1.0: + optional: true + + minimatch@3.1.3: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.3: + dependencies: + brace-expansion: 2.0.2 + + minimist@1.2.8: + optional: true + + mkdirp-classic@0.5.3: + optional: true + + ms@2.1.3: {} + + mute-stream@0.0.8: {} + + napi-build-utils@2.0.0: + optional: true + + natural-compare@1.4.0: {} + + node-abi@3.87.0: + dependencies: + semver: 7.7.4 + optional: true + + node-addon-api@4.3.0: + optional: true + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + object-inspect@1.13.4: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + open@10.2.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-semver@1.1.1: + dependencies: + semver: 5.7.2 + + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.3.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.3.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-type@4.0.0: {} + + pend@1.2.0: {} + + picomatch@2.3.1: {} + + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.1.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.87.0 + pump: 3.0.3 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.4 + tunnel-agent: 0.6.0 + optional: true + + prelude-ls@1.2.1: {} + + prettier@3.8.1: {} + + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + optional: true + + punycode@2.3.1: {} + + qs@6.15.0: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + rc@1.2.8: + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + optional: true + + read@1.0.7: + dependencies: + mute-stream: 0.0.8 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + optional: true + + resolve-from@4.0.0: {} + + reusify@1.1.0: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + run-applescript@7.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-buffer@5.2.1: {} + + safer-buffer@2.1.2: {} + + sax@1.4.4: {} + + semver@5.7.2: {} + + semver@7.7.4: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + simple-concat@1.0.1: + optional: true + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + optional: true + + slash@3.0.0: {} + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-json-comments@2.0.1: + optional: true + + strip-json-comments@3.1.1: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + tar-fs@2.1.4: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.3 + tar-stream: 2.2.0 + optional: true + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + optional: true + + text-table@0.2.0: {} + + tmp@0.2.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-api-utils@1.4.3(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + tslib@2.8.1: {} + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + optional: true + + tunnel@0.0.6: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + typed-rest-client@1.8.11: + dependencies: + qs: 6.15.0 + tunnel: 0.0.6 + underscore: 1.13.8 + + typescript@5.9.3: {} + + uc.micro@1.0.6: {} + + underscore@1.13.8: {} + + undici-types@5.26.5: {} + + undici@7.22.0: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-join@4.0.1: {} + + util-deprecate@1.0.2: + optional: true + + uuid@8.3.2: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + wrappy@1.0.2: {} + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.1 + + xml2js@0.5.0: + dependencies: + sax: 1.4.4 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + yallist@4.0.0: {} + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yazl@2.5.1: + dependencies: + buffer-crc32: 0.2.13 + + yocto-queue@0.1.0: {} From ac736673f22734d20c278c618b6877c108b299d5 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Feb 2026 02:53:55 +0000 Subject: [PATCH 06/17] fix(lint): disable base no-unused-vars; fix prettier alignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two lint/format failures: 1. .eslintrc.json — eslint:recommended enables no-unused-vars as an error. When combined with @typescript-eslint/no-unused-vars the base rule also runs, but it does not understand TypeScript type-only constructs (e.g. `type Proximity = ...` used solely in type positions). The standard fix is to turn the base rule off and let @typescript-eslint/no-unused-vars handle everything — it is type-aware and handles the same cases correctly. 2. dueDateDecorator.ts — PROXIMITY_COLORS used hand-aligned comment padding (extra spaces before //) to keep the comments in a visual column. Prettier normalises all inline comments to a single space, so prettier --check rejected the file. Removed the alignment spaces. https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- .eslintrc.json | 1 + src/decorators/dueDateDecorator.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 5c6f12b..14dee55 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,6 +12,7 @@ "plugin:@typescript-eslint/recommended" ], "rules": { + "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "@typescript-eslint/explicit-function-return-type": "warn", "no-console": "warn" diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts index e1caf9c..4057375 100644 --- a/src/decorators/dueDateDecorator.ts +++ b/src/decorators/dueDateDecorator.ts @@ -23,9 +23,9 @@ type Proximity = 'overdue' | 'today' | 'soon' | 'future'; /** Colors mirror Hexfield Deck board badge colors exactly. */ const PROXIMITY_COLORS: Record = { overdue: '#F44747', // Red - today: '#CE9178', // Orange - soon: '#CCA700', // Yellow - future: '#858585', // Gray + today: '#CE9178', // Orange + soon: '#CCA700', // Yellow + future: '#858585', // Gray }; /** From 2a6d57ad498acaa88edb5d6b6c9b117dfcd18d5d Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Feb 2026 03:09:57 +0000 Subject: [PATCH 07/17] fix(lint): add env:node and disable no-undef MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit eslint:recommended enables no-undef as an error. When combined with the TypeScript ESLint parser, Node.js globals like setTimeout and clearTimeout are not always recognised as defined — the scope manager's ambient global handling is not guaranteed for all TypeScript/tseslint version combinations. Two targeted fixes (both recommended by the TypeScript ESLint docs): - "env": { "node": true } — explicitly tells ESLint that Node.js globals (setTimeout, clearTimeout, process, Buffer, etc.) are in scope - "no-undef": "off" — TypeScript itself enforces undefined-variable checks with stricter accuracy; running the base ESLint rule in a TypeScript project is redundant and prone to false positives https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- .eslintrc.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.eslintrc.json b/.eslintrc.json index 14dee55..19b0561 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,6 +6,9 @@ "sourceType": "module", "project": "./tsconfig.json" }, + "env": { + "node": true + }, "plugins": ["@typescript-eslint"], "extends": [ "eslint:recommended", @@ -13,6 +16,7 @@ ], "rules": { "no-unused-vars": "off", + "no-undef": "off", "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "@typescript-eslint/explicit-function-return-type": "warn", "no-console": "warn" From d42fb405fabf2e2f2a5a2f90092aa4936dd6a248 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Feb 2026 04:08:11 +0000 Subject: [PATCH 08/17] fix(format): collapse setTextDocumentLanguage call to one line Prettier collapses multi-line function calls when the single-line version fits within printWidth (100). The call: vscode.languages.setTextDocumentLanguage(document, HEXFIELD_LANGUAGE_ID) is exactly 100 characters at its indentation level, so Prettier keeps it on one line. The multi-line form I had written did not match Prettier's output, causing the format:check step to fail. https://claude.ai/code/session_01B6NVinrGSL5KzskFxSi31G --- src/extension.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 5044bc8..c37c495 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -48,10 +48,7 @@ async function promoteIfHexfield( return; } try { - const promoted = await vscode.languages.setTextDocumentLanguage( - document, - HEXFIELD_LANGUAGE_ID, - ); + const promoted = await vscode.languages.setTextDocumentLanguage(document, HEXFIELD_LANGUAGE_ID); // Apply decorations immediately after promotion so dates are colored on first open. const editor = vscode.window.visibleTextEditors.find((e) => e.document === promoted); if (editor) { From c4ef2d30a4a2fb66a81f76070e50389549f37320 Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Fri, 27 Feb 2026 16:10:40 -0700 Subject: [PATCH 09/17] fix(grammar): use injection grammar so inline patterns fire within markdown scopes Top-level include of text.html.markdown claimed entire list items before hexfield-inline patterns could match within them. Split into two grammar files: hexfield-deck.tmLanguage.json retains frontmatter + markdown embedding; hexfield-inline-injection.tmLanguage.json uses injectionSelector L:text.hexfield.markdown to run within already-tokenized markdown scopes. Co-Authored-By: Claude Sonnet 4.6 --- syntaxes/hexfield-deck.tmLanguage.json | 55 ------------------- .../hexfield-inline-injection.tmLanguage.json | 52 ++++++++++++++++++ 2 files changed, 52 insertions(+), 55 deletions(-) create mode 100644 syntaxes/hexfield-inline-injection.tmLanguage.json diff --git a/syntaxes/hexfield-deck.tmLanguage.json b/syntaxes/hexfield-deck.tmLanguage.json index 397cc8c..5c00ca2 100644 --- a/syntaxes/hexfield-deck.tmLanguage.json +++ b/syntaxes/hexfield-deck.tmLanguage.json @@ -4,7 +4,6 @@ "scopeName": "text.hexfield.markdown", "patterns": [ { "include": "#frontmatter" }, - { "include": "#hexfield-inline" }, { "include": "text.html.markdown" } ], "repository": { @@ -27,60 +26,6 @@ } } ] - }, - - "hexfield-inline": { - "patterns": [ - { "include": "#in-progress-checkbox" }, - { "include": "#due-date" }, - { "include": "#estimate" }, - { "include": "#priority-high" }, - { "include": "#priority-med" }, - { "include": "#priority-low" }, - { "include": "#project-tag" } - ] - }, - - "in-progress-checkbox": { - "comment": "In-progress checkbox [/] — orange", - "match": "\\[/\\]", - "name": "markup.changed.hexfield.checkbox" - }, - - "due-date": { - "comment": "ISO date bracket [YYYY-MM-DD] — default gray; overridden by Decoration API", - "match": "\\[\\d{4}-\\d{2}-\\d{2}\\]", - "name": "string.quoted.hexfield.date" - }, - - "estimate": { - "comment": "Time estimate est:Xh or est:Xm (fractional supported) — teal", - "match": "\\best:\\d+(?:\\.\\d+)?[hm]\\b", - "name": "constant.numeric.hexfield.estimate" - }, - - "priority-high": { - "comment": "Priority HIGH !!! — red", - "match": "(? Date: Fri, 27 Feb 2026 16:10:55 -0700 Subject: [PATCH 10/17] =?UTF-8?q?feat:=20Phase=203=20=E2=80=94=20full=20de?= =?UTF-8?q?corator=20coverage,=20configurable=20colors,=20dev=20setup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decorator: - Expand DueDateDecorator to cover all inline tokens via Decoration API (project tags, priorities HIGH/MED/LOW, time estimates, in-progress checkbox) so colors are absolute and not overridden by active theme - Project tags get pill styling: colored border with borderRadius - hexToRgba helper derives pill border color from configured tag color - All 10 token colors (6 static + 4 due-date proximity) user-configurable via hexfield-text.colors.* settings; changes apply live without reload Extension: - onDidChangeConfiguration watcher rebuilds decoration types on color change - Add onLanguage:hexfield-markdown activation event Package: - contributes.configuration with all 10 color settings - Bump version to 1.0.0 Dev: - .vscode/launch.json, tasks.json, settings.json, extensions.json - examples/weekly-planner.md for manual testing - CHANGELOG.md with v0.1.0, v0.2.0, v1.0.0 entries - .vscodeignore excludes dev/source files from VSIX Co-Authored-By: Claude Sonnet 4.6 --- .vscode/extensions.json | 7 + .vscode/launch.json | 17 ++ .vscode/settings.json | 47 ++++++ .vscode/tasks.json | 12 ++ .vscodeignore | 3 + CHANGELOG.md | 42 +++++ USER_GUIDE.md | 39 +++-- examples/weekly-planner.md | 105 ++++++++++++ package.json | 65 +++++++- src/decorators/dueDateDecorator.ts | 247 +++++++++++++++++++++-------- src/extension.ts | 15 ++ 11 files changed, 517 insertions(+), 82 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 .vscode/tasks.json create mode 100644 CHANGELOG.md create mode 100644 examples/weekly-planner.md diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..8535846 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "editorconfig.editorconfig" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..6eb97b8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ], + "outFiles": [ + "${workspaceFolder}/dist/**/*.js" + ], + "preLaunchTask": "pnpm: build" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..47b887f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,47 @@ +{ + // Editor + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "explicit" + }, + "editor.tabSize": 4, + "editor.insertSpaces": true, + + // Files + "files.eol": "\n", + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + "files.exclude": { + "**/.git": true, + "**/node_modules": true, + "**/dist": true, + "**/*.tsbuildinfo": true + }, + + // TypeScript + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true, + + // Search + "search.exclude": { + "**/node_modules": true, + "**/dist": true, + "**/pnpm-lock.yaml": true + }, + + // Hexfield Text — token color defaults for development + // These ensure grammar scopes render correctly regardless of active theme. + "editor.tokenColorCustomizations": { + "textMateRules": [ + { "scope": "entity.name.tag.hexfield", "settings": { "foreground": "#569CD6" } }, + { "scope": "string.quoted.hexfield.date", "settings": { "foreground": "#858585" } }, + { "scope": "keyword.operator.hexfield.priority.high", "settings": { "foreground": "#F44747" } }, + { "scope": "keyword.operator.hexfield.priority.medium", "settings": { "foreground": "#CCA700" } }, + { "scope": "keyword.operator.hexfield.priority.low", "settings": { "foreground": "#89D185" } }, + { "scope": "constant.numeric.hexfield.estimate", "settings": { "foreground": "#4EC9B0" } }, + { "scope": "markup.changed.hexfield.checkbox", "settings": { "foreground": "#CE9178" } }, + { "scope": "keyword.other.hexfield.frontmatter", "settings": { "foreground": "#C586C0" } } + ] + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..30bdcd6 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "command": "pnpm build", + "group": "build", + "label": "pnpm: build", + "problemMatcher": ["$esbuild"] + } + ] +} diff --git a/.vscodeignore b/.vscodeignore index 61eafd2..eaac8db 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -1,11 +1,14 @@ .vscode/** src/** node_modules/** +examples/** .eslintrc.json .prettierrc tsconfig.json esbuild.js +pnpm-lock.yaml *.map .gitignore **/*.ts !dist/** +IMPLEMENTATION_PLAN.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..25653f5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to Hexfield Text are documented here. Dates are in `YYYY-MM-DD` format. + +--- + +## [1.0.0] — 2026-02-27 + +### Added + +- **User-configurable due date colors** — `hexfield-text.colors.dueDateOverdue`, `dueDateToday`, `dueDateSoon`, `dueDateFuture` settings in VS Code preferences +- Due date decorator rebuilds automatically when color settings change (no reload needed) +- Extension published to VS Code Marketplace as `jimblom.hexfield-text` + +--- + +## [0.2.0] — 2026-02-24 + +### Added + +- **Decoration API** — dynamic due date proximity coloring (`[YYYY-MM-DD]` tokens) +- Four proximity buckets: overdue → red, today → orange, within 3 days → yellow, future → gray +- Colors mirror Hexfield Deck board badge colors exactly +- Debounced re-decoration (500ms) on every document change +- Language de-promotion — removing `type: hexfield-planner` from frontmatter while a file is open immediately reverts colorization + +--- + +## [0.1.0] — 2026-02-23 + +### Added + +- Initial release +- Custom language ID (`hexfield-markdown`) promoted from `.md` files containing `type: hexfield-planner` in YAML frontmatter +- TextMate grammar (`hexfield-deck.tmLanguage.json`) scoped to `hexfield-markdown` only: + - Project tags (`#tag`) — blue + - Due date brackets (`[YYYY-MM-DD]`) — default gray (overridden by Decoration API) + - Priority HIGH / MED / LOW (`!!!` / `!!` / `!`) — red / yellow / green + - Time estimates (`est:Xh`, `est:Xm`) — teal + - In-progress checkbox (`[/]`) — orange + - Frontmatter keys (`type`, `week`, `year`, `quarter`, `tags`, `startDate`, `endDate`) — purple +- Zero false-positive colorization on regular markdown files diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 2ff592c..77083b9 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -187,28 +187,35 @@ Due date brackets (`[YYYY-MM-DD]`) are colorized by the Decoration API at runtim ## Configuration -> Token color configuration is planned for v1.0.0 (Phase 3). The settings listed here describe the intended behavior. +All token colors are applied by the Decoration API and are fully user-configurable. In VS Code Settings (`Ctrl+,`), search for **hexfield-text** to access: -In VS Code Settings (`Ctrl+,`), search for **hexfield-text** to access: +| Setting | Default | Token | +|---|---|---| +| `hexfield-text.colors.projectTag` | `#569CD6` | `#project-tag` | +| `hexfield-text.colors.priorityHigh` | `#F44747` | `!!!` | +| `hexfield-text.colors.priorityMed` | `#CCA700` | `!!` | +| `hexfield-text.colors.priorityLow` | `#89D185` | `!` | +| `hexfield-text.colors.timeEstimate` | `#4EC9B0` | `est:2h` / `est:30m` | +| `hexfield-text.colors.inProgressCheckbox` | `#CE9178` | `[/]` | +| `hexfield-text.colors.dueDateOverdue` | `#F44747` | `[YYYY-MM-DD]` — overdue | +| `hexfield-text.colors.dueDateToday` | `#CE9178` | `[YYYY-MM-DD]` — today | +| `hexfield-text.colors.dueDateSoon` | `#CCA700` | `[YYYY-MM-DD]` — within 3 days | +| `hexfield-text.colors.dueDateFuture` | `#858585` | `[YYYY-MM-DD]` — future | + +All colors override the active VS Code theme — they match the Hexfield Deck board palette exactly. Changes take effect immediately with no reload needed. + +### Frontmatter Key Colors + +Frontmatter keys (`type`, `week`, `year`, etc.) are colored by the TextMate grammar and follow your active theme. To override them, add to your `settings.json`: ```json -{ - "hexfield-text.colors.projectTag": "#569CD6", - "hexfield-text.colors.priorityHigh": "#F44747", - "hexfield-text.colors.priorityMed": "#CCA700", - "hexfield-text.colors.priorityLow": "#89D185", - "hexfield-text.colors.timeEstimate": "#4EC9B0", - "hexfield-text.colors.inProgressCheckbox": "#CE9178", - "hexfield-text.colors.frontmatterKey": "#C586C0", - "hexfield-text.colors.dueDateOverdue": "#F44747", - "hexfield-text.colors.dueDateToday": "#CE9178", - "hexfield-text.colors.dueDateSoon": "#CCA700", - "hexfield-text.colors.dueDateFuture": "#858585" +"editor.tokenColorCustomizations": { + "textMateRules": [ + { "scope": "keyword.other.hexfield.frontmatter", "settings": { "foreground": "#C586C0" } } + ] } ``` -All settings have defaults matching the values in the Token Reference above. Any setting left unset uses the default. - --- ## How Scoping Works diff --git a/examples/weekly-planner.md b/examples/weekly-planner.md new file mode 100644 index 0000000..f90fc37 --- /dev/null +++ b/examples/weekly-planner.md @@ -0,0 +1,105 @@ +--- +type: hexfield-planner +week: 7 +year: 2026 +tags: [planner, weekly] +quarter: Q1 +startDate: 2026-02-09 +endDate: 2026-02-15 +--- + +## Monday, February 9, 2026 + +- [x] Morning standup — discuss experiment results #deep13 +- [x] Fix Hexfield Viewscreen rendering glitch #hexfield [2026-02-09] !! + - [x] Reproduce on the bridge + - [x] Check viewport calculations + - The viewscreen keeps showing reruns of _Manos: The Hands of Fate_ +- [x] Rewire the Satellite of Love's nacelle couplings #deep13 est:3h +- [x] Review Joel's Invention Exchange submission !!! + +## Tuesday, February 10, 2026 + +- [/] Ship **parser v1** #hexfield [2026-02-10] !!! est:4h + - [/] Write frontmatter tests + - [x] Wire up barrel exports + - [x] Delete placeholder test + - [ ] Review [parser ADR](https://github.com/jimblom/Hexfield-Deck/tree/main/docs/decisions) +- [x] Calibrate Cambot's _focus module_ #sol +- [x] File expense report for RAM chips due:2026-02-10 + +## Wednesday, February 11, 2026 + +- [x] Pair with Crow on the snack bar refactor #sol est:2h + Tom Servo insists we use a monorepo for the snack dispensers +- [ ] Draft ADR for Gizmonic communication protocol #deep13 !! +- [/] Update Time Chasers pace algorithm #time-chasers + +## Thursday, February 12, 2026 + +- [ ] Run full regression on Hexfield parser #hexfield est:1h +- [/] Movie sign prep — queue up _Space Mutiny_ est:2h + - [/] Cue [Big McLargehuge](https://en.wikipedia.org/wiki/Space_Mutiny) name list + - [ ] Prep riff notes + - [x] ~~Book the theater~~ (Crow already did it) + - [ ] Test theater seat actuators +- [ ] Restock Deep Ape supplies + +## Friday, February 13, 2026 + +- [ ] Sprint retro #hexfield +- [ ] Deploy Hexfield Deck beta to the SOL bridge #hexfield [2026-02-13] !!! est:2h +- [/] Write quarterly OKR draft + - [/] Key Result 1: Launch Hexfield Deck + - [ ] Key Result 2: Survive another movie + +## Saturday, February 14, 2026 + +- [ ] Date night on the Satellite of Love 💕 + Dinner reservations at the Tubular Boobular Joy cafe + +## Sunday, February 15, 2026 + +- [ ] Implement drag-and-drop card reordering #hexfield !!! +- [ ] Weekly review and planning + +## Backlog + +### Now + +- [ ] Fix Joel's escape pod hatch — keeps jamming #sol !! est:1h +- [ ] Add Obsidian plugin scaffold #hexfield +- [ ] Write **release notes** for [Hexfield Deck v0.4.0](https://github.com/jimblom/Hexfield-Deck/releases) #hexfield + - [ ] Document `marked` inline rendering support + - [x] ~~Draft changelog entry~~ (moved to PR description) + - [ ] Add _before/after_ screenshots + +### Next 2 Weeks + +- [ ] Investigate Tom Servo's hoverskirt power drain #sol est:4h +- [ ] Set up CI pipeline for Hexfield Deck #hexfield !! +- [ ] Catalog all MST3K movie inventory #sol + +### This Month + +- [ ] Design card detail panel UI #hexfield est:8h +- [ ] Annual Satellite of Love safety inspection #sol +- [ ] Migrate Deep 13 experiments to new container host #deep13 + +## This Quarter + +- [ ] Launch Hexfield Deck v1.0 #hexfield [2026-03-31] !!! +- [ ] Complete Time Chasers MVP #time-chasers +- [ ] Publish MST3K episode guide API #deep13 est:20h + +## This Year + +- [ ] Obsidian plugin general availability #hexfield +- [ ] Present at VS Code Conf — "Markdown-Powered Kanban" #hexfield +- [ ] Build Code Name: Diamond Head secrets manager + +## Parking Lot + +- [ ] Rewrite Gizmonic comm protocol in Rust +- [ ] Tom Servo's screenplay — find a publisher +- [ ] Investigate wormhole-based CI/CD (Dr. Forrester's suggestion) diff --git a/package.json b/package.json index b9bd558..649b23b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "hexfield-text", "displayName": "Hexfield Text", "description": "Inline syntax colorization for Hexfield Deck planner files in VS Code", - "version": "0.1.0", + "version": "1.0.0", "publisher": "jimblom", "license": "MIT", "repository": { @@ -19,6 +19,7 @@ "keywords": ["markdown", "kanban", "hexfield", "task board", "syntax highlighting"], "activationEvents": [ "onLanguage:markdown", + "onLanguage:hexfield-markdown", "onStartupFinished" ], "main": "./dist/extension.js", @@ -40,8 +41,68 @@ "meta.embedded.block.javascript": "javascript", "meta.embedded.block.css": "css" } + }, + { + "scopeName": "hexfield.markdown.inline", + "path": "./syntaxes/hexfield-inline-injection.tmLanguage.json", + "injectTo": ["text.hexfield.markdown"] + } + ], + "configuration": { + "title": "Hexfield Text", + "properties": { + "hexfield-text.colors.projectTag": { + "type": "string", + "default": "#569CD6", + "markdownDescription": "Foreground color for project tags (`#hexfield`, `#deep13`, etc.)." + }, + "hexfield-text.colors.priorityHigh": { + "type": "string", + "default": "#F44747", + "markdownDescription": "Foreground color for HIGH priority markers (`!!!`)." + }, + "hexfield-text.colors.priorityMed": { + "type": "string", + "default": "#CCA700", + "markdownDescription": "Foreground color for MED priority markers (`!!`)." + }, + "hexfield-text.colors.priorityLow": { + "type": "string", + "default": "#89D185", + "markdownDescription": "Foreground color for LOW priority markers (`!`)." + }, + "hexfield-text.colors.timeEstimate": { + "type": "string", + "default": "#4EC9B0", + "markdownDescription": "Foreground color for time estimates (`est:2h`, `est:30m`)." + }, + "hexfield-text.colors.inProgressCheckbox": { + "type": "string", + "default": "#CE9178", + "markdownDescription": "Foreground color for in-progress checkboxes (`[/]`)." + }, + "hexfield-text.colors.dueDateOverdue": { + "type": "string", + "default": "#F44747", + "markdownDescription": "Foreground color for **overdue** due dates (date < today). Accepts any CSS color string (e.g. `#F44747`, `rgb(244,71,71)`)." + }, + "hexfield-text.colors.dueDateToday": { + "type": "string", + "default": "#CE9178", + "markdownDescription": "Foreground color for due dates that fall **today**." + }, + "hexfield-text.colors.dueDateSoon": { + "type": "string", + "default": "#CCA700", + "markdownDescription": "Foreground color for due dates **within the next 3 days**." + }, + "hexfield-text.colors.dueDateFuture": { + "type": "string", + "default": "#858585", + "markdownDescription": "Foreground color for due dates **more than 3 days** in the future." + } } - ] + } }, "scripts": { "build": "node esbuild.js --production", diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts index 4057375..6257ec5 100644 --- a/src/decorators/dueDateDecorator.ts +++ b/src/decorators/dueDateDecorator.ts @@ -1,109 +1,228 @@ -// Dynamic due date proximity colorization via the VS Code Decoration API. +// Hexfield inline token colorization via the VS Code Decoration API. // -// Scans hexfield-markdown documents for [YYYY-MM-DD] tokens, computes proximity -// relative to today, and applies one of four colors that mirror Hexfield Deck's -// board badge colors exactly: +// Handles two categories of tokens: // -// Overdue (date < today) → Red (#F44747) -// Today (date === today) → Orange (#CE9178) -// Soon (1–3 days from now) → Yellow (#CCA700) -// Future (> 3 days from now) → Gray (#858585) +// STATIC tokens — fixed color regardless of context: +// Project tag #project → Blue (#569CD6) +// Priority HIGH !!! → Red (#F44747) +// Priority MED !! → Yellow (#CCA700) +// Priority LOW ! → Green (#89D185) +// Time estimate est:2h / est:30m → Teal (#4EC9B0) +// In-progress [/] → Orange (#CE9178) // -// The decorator is debounced at 500ms by the caller and re-runs on every -// document change. All TextEditorDecorationType instances are disposed when -// the extension deactivates. +// DYNAMIC tokens — color computed at runtime relative to today: +// Due date [YYYY-MM-DD]: +// Overdue (date < today) → Red (#F44747) +// Today (date === today) → Orange (#CE9178) +// Soon (1–3 days from now) → Yellow (#CCA700) +// Future (> 3 days from now) → Gray (#858585) +// +// Using the Decoration API for all tokens ensures colors are absolute and +// not overridden by the active VS Code theme. +// +// All TextEditorDecorationType instances are disposed on deactivation or +// when colors are refreshed from configuration. import * as vscode from 'vscode'; -/** Matches `[YYYY-MM-DD]` anywhere in a document. Capture group 1 is the date string. */ -const DATE_BRACKET_RE = /\[(\d{4}-\d{2}-\d{2})\]/g; +// --------------------------------------------------------------------------- +// Static token types +// --------------------------------------------------------------------------- + +type StaticToken = 'projectTag' | 'priorityHigh' | 'priorityMed' | 'priorityLow' | 'estimate' | 'inProgressCheckbox'; + +const STATIC_DEFAULTS: Record = { + projectTag: '#569CD6', // Blue + priorityHigh: '#F44747', // Red + priorityMed: '#CCA700', // Yellow + priorityLow: '#89D185', // Green + estimate: '#4EC9B0', // Teal + inProgressCheckbox: '#CE9178', // Orange +}; + +const STATIC_CONFIG_KEYS: Record = { + projectTag: 'projectTag', + priorityHigh: 'priorityHigh', + priorityMed: 'priorityMed', + priorityLow: 'priorityLow', + estimate: 'timeEstimate', + inProgressCheckbox: 'inProgressCheckbox', +}; + +/** Each regex must use the global flag so lastIndex can be reset between calls. */ +const STATIC_PATTERNS: Record = { + projectTag: /(? = { +const PROXIMITY_DEFAULTS: Record = { overdue: '#F44747', // Red today: '#CE9178', // Orange soon: '#CCA700', // Yellow future: '#858585', // Gray }; -/** - * Computes proximity of an ISO date string (YYYY-MM-DD) relative to today. - * Today's date is evaluated at call time so decorations always reflect the - * current calendar day — no stale state across midnight. - */ +const PROXIMITY_CONFIG_KEYS: Record = { + overdue: 'dueDateOverdue', + today: 'dueDateToday', + soon: 'dueDateSoon', + future: 'dueDateFuture', +}; + +const DATE_BRACKET_RE = /\[(\d{4}-\d{2}-\d{2})\]/g; + function getProximity(dateStr: string): Proximity { const today = new Date(); today.setHours(0, 0, 0, 0); - const [year, month, day] = dateStr.split('-').map(Number); const due = new Date(year, month - 1, day); - const diffDays = Math.round((due.getTime() - today.getTime()) / 86_400_000); - if (diffDays < 0) return 'overdue'; if (diffDays === 0) return 'today'; if (diffDays <= 3) return 'soon'; return 'future'; } +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +function readConfig(section: string, key: string, fallback: string): string { + return vscode.workspace.getConfiguration(section).get(key, fallback) || fallback; +} + /** - * Scans hexfield-markdown documents for `[YYYY-MM-DD]` tokens and applies - * proximity-based foreground color decorations. Implements vscode.Disposable - * so the four TextEditorDecorationType instances are cleaned up on deactivation. + * Converts a #rrggbb hex color to an rgba() string with the given alpha. + * Returns the original string unchanged for any format it can't parse. + */ +function hexToRgba(hex: string, alpha: number): string { + const h = hex.replace('#', ''); + if (h.length !== 6) return hex; + const r = parseInt(h.slice(0, 2), 16); + const g = parseInt(h.slice(2, 4), 16); + const b = parseInt(h.slice(4, 6), 16); + return `rgba(${r}, ${g}, ${b}, ${alpha})`; +} + +function createStaticTypes(): Record { + const cfg = 'hexfield-text.colors'; + + // Project tag gets pill styling: colored foreground, semi-transparent tinted + // background, rounded border. before/after thin spaces add visual padding. + // Note: before/after don't support borderRadius, so we use a small radius + // on the main range only — the overall shape reads clearly as a tag chip. + const tagColor = readConfig(cfg, STATIC_CONFIG_KEYS.projectTag, STATIC_DEFAULTS.projectTag); + const tagBorder = hexToRgba(tagColor, 0.4); + + const result = {} as Record; + + result.projectTag = vscode.window.createTextEditorDecorationType({ + color: tagColor, + borderRadius: '4px', + border: `1px solid ${tagBorder}`, + }); + + // All other static tokens — foreground color only. + for (const token of Object.keys(STATIC_DEFAULTS).filter((k) => k !== 'projectTag') as StaticToken[]) { + result[token] = vscode.window.createTextEditorDecorationType({ + color: readConfig(cfg, STATIC_CONFIG_KEYS[token], STATIC_DEFAULTS[token]), + }); + } + + return result; +} + +function createProximityTypes(): Record { + const cfg = 'hexfield-text.colors'; + const result = {} as Record; + for (const prox of Object.keys(PROXIMITY_DEFAULTS) as Proximity[]) { + result[prox] = vscode.window.createTextEditorDecorationType({ + color: readConfig(cfg, PROXIMITY_CONFIG_KEYS[prox], PROXIMITY_DEFAULTS[prox]), + }); + } + return result; +} + +// --------------------------------------------------------------------------- +// Decorator +// --------------------------------------------------------------------------- + +/** + * Applies all Hexfield inline token decorations to hexfield-markdown editors. + * Implements vscode.Disposable so all decoration types are cleaned up on + * deactivation or color refresh. + * + * Call `refreshColors()` after a `hexfield-text.colors` configuration change, + * then re-decorate any visible editors. */ export class DueDateDecorator implements vscode.Disposable { - private readonly decorationTypes: Record; + private staticTypes: Record; + private proximityTypes: Record; constructor() { - this.decorationTypes = { - overdue: vscode.window.createTextEditorDecorationType({ - color: PROXIMITY_COLORS.overdue, - }), - today: vscode.window.createTextEditorDecorationType({ - color: PROXIMITY_COLORS.today, - }), - soon: vscode.window.createTextEditorDecorationType({ - color: PROXIMITY_COLORS.soon, - }), - future: vscode.window.createTextEditorDecorationType({ - color: PROXIMITY_COLORS.future, - }), - }; + this.staticTypes = createStaticTypes(); + this.proximityTypes = createProximityTypes(); } - /** - * Applies due date proximity decorations to the given editor. - * Safe to call on any editor — silently no-ops if no date tokens are found. - */ - decorate(editor: vscode.TextEditor): void { - const buckets: Record = { - overdue: [], - today: [], - soon: [], - future: [], - }; + /** Rebuild all decoration types from current configuration. */ + refreshColors(): void { + for (const t of Object.values(this.staticTypes)) t.dispose(); + for (const t of Object.values(this.proximityTypes)) t.dispose(); + this.staticTypes = createStaticTypes(); + this.proximityTypes = createProximityTypes(); + } + /** Scan the document and apply all Hexfield token decorations to the editor. */ + decorate(editor: vscode.TextEditor): void { const text = editor.document.getText(); - DATE_BRACKET_RE.lastIndex = 0; - let match: RegExpExecArray | null; - while ((match = DATE_BRACKET_RE.exec(text)) !== null) { - const proximity = getProximity(match[1]); - const start = editor.document.positionAt(match.index); - const end = editor.document.positionAt(match.index + match[0].length); - buckets[proximity].push(new vscode.Range(start, end)); + // --- Static tokens --- + const staticRanges = {} as Record; + for (const token of Object.keys(STATIC_PATTERNS) as StaticToken[]) { + staticRanges[token] = []; + const re = STATIC_PATTERNS[token]; + re.lastIndex = 0; + let m: RegExpExecArray | null; + while ((m = re.exec(text)) !== null) { + staticRanges[token].push(new vscode.Range( + editor.document.positionAt(m.index), + editor.document.positionAt(m.index + m[0].length), + )); + } + editor.setDecorations(this.staticTypes[token], staticRanges[token]); } - for (const prox of Object.keys(buckets) as Proximity[]) { - editor.setDecorations(this.decorationTypes[prox], buckets[prox]); + // --- Due date proximity tokens --- + const proximityRanges = {} as Record; + for (const prox of Object.keys(PROXIMITY_DEFAULTS) as Proximity[]) { + proximityRanges[prox] = []; + } + DATE_BRACKET_RE.lastIndex = 0; + let m: RegExpExecArray | null; + while ((m = DATE_BRACKET_RE.exec(text)) !== null) { + const prox = getProximity(m[1]); + proximityRanges[prox].push(new vscode.Range( + editor.document.positionAt(m.index), + editor.document.positionAt(m.index + m[0].length), + )); + } + for (const prox of Object.keys(proximityRanges) as Proximity[]) { + editor.setDecorations(this.proximityTypes[prox], proximityRanges[prox]); } } dispose(): void { - for (const type of Object.values(this.decorationTypes)) { - type.dispose(); - } + for (const t of Object.values(this.staticTypes)) t.dispose(); + for (const t of Object.values(this.proximityTypes)) t.dispose(); } } diff --git a/src/extension.ts b/src/extension.ts index c37c495..4f57a92 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -130,6 +130,21 @@ export function activate(context: vscode.ExtensionContext): void { } }), ); + + // Rebuild decoration types and re-decorate when the user changes due date color settings. + context.subscriptions.push( + vscode.workspace.onDidChangeConfiguration((event) => { + if (!event.affectsConfiguration('hexfield-text.colors')) { + return; + } + decorator.refreshColors(); + for (const editor of vscode.window.visibleTextEditors) { + if (editor.document.languageId === HEXFIELD_LANGUAGE_ID) { + decorator.decorate(editor); + } + } + }), + ); } export function deactivate(): void { From 8fe81a02622f150ab184eb3f2d735e5585ee582b Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Fri, 27 Feb 2026 21:21:53 -0700 Subject: [PATCH 11/17] fix(format): run prettier on dueDateDecorator.ts Co-Authored-By: Claude Sonnet 4.6 --- src/decorators/dueDateDecorator.ts | 32 ++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts index 6257ec5..547f1ac 100644 --- a/src/decorators/dueDateDecorator.ts +++ b/src/decorators/dueDateDecorator.ts @@ -29,7 +29,13 @@ import * as vscode from 'vscode'; // Static token types // --------------------------------------------------------------------------- -type StaticToken = 'projectTag' | 'priorityHigh' | 'priorityMed' | 'priorityLow' | 'estimate' | 'inProgressCheckbox'; +type StaticToken = + | 'projectTag' + | 'priorityHigh' + | 'priorityMed' + | 'priorityLow' + | 'estimate' + | 'inProgressCheckbox'; const STATIC_DEFAULTS: Record = { projectTag: '#569CD6', // Blue @@ -133,7 +139,9 @@ function createStaticTypes(): Record k !== 'projectTag') as StaticToken[]) { + for (const token of Object.keys(STATIC_DEFAULTS).filter( + (k) => k !== 'projectTag', + ) as StaticToken[]) { result[token] = vscode.window.createTextEditorDecorationType({ color: readConfig(cfg, STATIC_CONFIG_KEYS[token], STATIC_DEFAULTS[token]), }); @@ -194,10 +202,12 @@ export class DueDateDecorator implements vscode.Disposable { re.lastIndex = 0; let m: RegExpExecArray | null; while ((m = re.exec(text)) !== null) { - staticRanges[token].push(new vscode.Range( - editor.document.positionAt(m.index), - editor.document.positionAt(m.index + m[0].length), - )); + staticRanges[token].push( + new vscode.Range( + editor.document.positionAt(m.index), + editor.document.positionAt(m.index + m[0].length), + ), + ); } editor.setDecorations(this.staticTypes[token], staticRanges[token]); } @@ -211,10 +221,12 @@ export class DueDateDecorator implements vscode.Disposable { let m: RegExpExecArray | null; while ((m = DATE_BRACKET_RE.exec(text)) !== null) { const prox = getProximity(m[1]); - proximityRanges[prox].push(new vscode.Range( - editor.document.positionAt(m.index), - editor.document.positionAt(m.index + m[0].length), - )); + proximityRanges[prox].push( + new vscode.Range( + editor.document.positionAt(m.index), + editor.document.positionAt(m.index + m[0].length), + ), + ); } for (const prox of Object.keys(proximityRanges) as Proximity[]) { editor.setDecorations(this.proximityTypes[prox], proximityRanges[prox]); From 694724464ec898ba8778306cf2146a4c94d12123 Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Fri, 27 Feb 2026 21:26:25 -0700 Subject: [PATCH 12/17] feat: migrate color settings to shared hexfield.colors.* namespace Renames all hexfield-text.colors.* configuration keys to hexfield.colors.* so Hexfield Deck can adopt the same namespace and both extensions share a single settings group (per jimblom/Hexfield-Deck#19). Breaking change: users with customized colors need to rename their settings.json keys accordingly. Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 8 ++++++++ USER_GUIDE.md | 20 ++++++++++---------- package.json | 22 +++++++++++----------- src/decorators/dueDateDecorator.ts | 4 ++-- src/extension.ts | 2 +- 5 files changed, 32 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25653f5..29771e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to Hexfield Text are documented here. Dates are in `YYYY-MM- --- +## [1.0.1] — 2026-02-27 + +### Changed + +- **Breaking:** color settings migrated from `hexfield-text.colors.*` to the shared `hexfield.colors.*` namespace. If you have customized colors, rename the keys in your `settings.json` (e.g. `hexfield-text.colors.projectTag` → `hexfield.colors.projectTag`). This aligns with Hexfield Deck's upcoming adoption of the same namespace so both extensions share one settings group. + +--- + ## [1.0.0] — 2026-02-27 ### Added diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 77083b9..759fbfe 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -191,16 +191,16 @@ All token colors are applied by the Decoration API and are fully user-configurab | Setting | Default | Token | |---|---|---| -| `hexfield-text.colors.projectTag` | `#569CD6` | `#project-tag` | -| `hexfield-text.colors.priorityHigh` | `#F44747` | `!!!` | -| `hexfield-text.colors.priorityMed` | `#CCA700` | `!!` | -| `hexfield-text.colors.priorityLow` | `#89D185` | `!` | -| `hexfield-text.colors.timeEstimate` | `#4EC9B0` | `est:2h` / `est:30m` | -| `hexfield-text.colors.inProgressCheckbox` | `#CE9178` | `[/]` | -| `hexfield-text.colors.dueDateOverdue` | `#F44747` | `[YYYY-MM-DD]` — overdue | -| `hexfield-text.colors.dueDateToday` | `#CE9178` | `[YYYY-MM-DD]` — today | -| `hexfield-text.colors.dueDateSoon` | `#CCA700` | `[YYYY-MM-DD]` — within 3 days | -| `hexfield-text.colors.dueDateFuture` | `#858585` | `[YYYY-MM-DD]` — future | +| `hexfield.colors.projectTag` | `#569CD6` | `#project-tag` | +| `hexfield.colors.priorityHigh` | `#F44747` | `!!!` | +| `hexfield.colors.priorityMed` | `#CCA700` | `!!` | +| `hexfield.colors.priorityLow` | `#89D185` | `!` | +| `hexfield.colors.timeEstimate` | `#4EC9B0` | `est:2h` / `est:30m` | +| `hexfield.colors.inProgressCheckbox` | `#CE9178` | `[/]` | +| `hexfield.colors.dueDateOverdue` | `#F44747` | `[YYYY-MM-DD]` — overdue | +| `hexfield.colors.dueDateToday` | `#CE9178` | `[YYYY-MM-DD]` — today | +| `hexfield.colors.dueDateSoon` | `#CCA700` | `[YYYY-MM-DD]` — within 3 days | +| `hexfield.colors.dueDateFuture` | `#858585` | `[YYYY-MM-DD]` — future | All colors override the active VS Code theme — they match the Hexfield Deck board palette exactly. Changes take effect immediately with no reload needed. diff --git a/package.json b/package.json index 649b23b..77d488f 100644 --- a/package.json +++ b/package.json @@ -49,54 +49,54 @@ } ], "configuration": { - "title": "Hexfield Text", + "title": "Hexfield", "properties": { - "hexfield-text.colors.projectTag": { + "hexfield.colors.projectTag": { "type": "string", "default": "#569CD6", "markdownDescription": "Foreground color for project tags (`#hexfield`, `#deep13`, etc.)." }, - "hexfield-text.colors.priorityHigh": { + "hexfield.colors.priorityHigh": { "type": "string", "default": "#F44747", "markdownDescription": "Foreground color for HIGH priority markers (`!!!`)." }, - "hexfield-text.colors.priorityMed": { + "hexfield.colors.priorityMed": { "type": "string", "default": "#CCA700", "markdownDescription": "Foreground color for MED priority markers (`!!`)." }, - "hexfield-text.colors.priorityLow": { + "hexfield.colors.priorityLow": { "type": "string", "default": "#89D185", "markdownDescription": "Foreground color for LOW priority markers (`!`)." }, - "hexfield-text.colors.timeEstimate": { + "hexfield.colors.timeEstimate": { "type": "string", "default": "#4EC9B0", "markdownDescription": "Foreground color for time estimates (`est:2h`, `est:30m`)." }, - "hexfield-text.colors.inProgressCheckbox": { + "hexfield.colors.inProgressCheckbox": { "type": "string", "default": "#CE9178", "markdownDescription": "Foreground color for in-progress checkboxes (`[/]`)." }, - "hexfield-text.colors.dueDateOverdue": { + "hexfield.colors.dueDateOverdue": { "type": "string", "default": "#F44747", "markdownDescription": "Foreground color for **overdue** due dates (date < today). Accepts any CSS color string (e.g. `#F44747`, `rgb(244,71,71)`)." }, - "hexfield-text.colors.dueDateToday": { + "hexfield.colors.dueDateToday": { "type": "string", "default": "#CE9178", "markdownDescription": "Foreground color for due dates that fall **today**." }, - "hexfield-text.colors.dueDateSoon": { + "hexfield.colors.dueDateSoon": { "type": "string", "default": "#CCA700", "markdownDescription": "Foreground color for due dates **within the next 3 days**." }, - "hexfield-text.colors.dueDateFuture": { + "hexfield.colors.dueDateFuture": { "type": "string", "default": "#858585", "markdownDescription": "Foreground color for due dates **more than 3 days** in the future." diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts index 547f1ac..de028d8 100644 --- a/src/decorators/dueDateDecorator.ts +++ b/src/decorators/dueDateDecorator.ts @@ -121,7 +121,7 @@ function hexToRgba(hex: string, alpha: number): string { } function createStaticTypes(): Record { - const cfg = 'hexfield-text.colors'; + const cfg = 'hexfield.colors'; // Project tag gets pill styling: colored foreground, semi-transparent tinted // background, rounded border. before/after thin spaces add visual padding. @@ -151,7 +151,7 @@ function createStaticTypes(): Record { - const cfg = 'hexfield-text.colors'; + const cfg = 'hexfield.colors'; const result = {} as Record; for (const prox of Object.keys(PROXIMITY_DEFAULTS) as Proximity[]) { result[prox] = vscode.window.createTextEditorDecorationType({ diff --git a/src/extension.ts b/src/extension.ts index 4f57a92..31be33a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -134,7 +134,7 @@ export function activate(context: vscode.ExtensionContext): void { // Rebuild decoration types and re-decorate when the user changes due date color settings. context.subscriptions.push( vscode.workspace.onDidChangeConfiguration((event) => { - if (!event.affectsConfiguration('hexfield-text.colors')) { + if (!event.affectsConfiguration('hexfield.colors')) { return; } decorator.refreshColors(); From 74156688287f54fe7b9e7621fc796fb5b1ab638c Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Sat, 28 Feb 2026 12:55:13 -0700 Subject: [PATCH 13/17] feat: per-project tag coloring from hexfield-deck.projects config Project tags (#name) now read hexfield-deck.projects..color to apply a per-project pill border color, matching Hexfield Deck's tag color system. Tags without a configured color fall back to the default hexfield.colors.projectTag value. Per-project TextEditorDecorationType instances are cached by color and lazily created on first use. They are disposed on refreshColors() and on extension deactivation. The onDidChangeConfiguration watcher now also reacts to hexfield-deck.projects changes, triggering a re-decorate so tag colors update live when project config changes in Hexfield Deck. Co-Authored-By: Claude Sonnet 4.6 --- src/decorators/dueDateDecorator.ts | 96 ++++++++++++++++++++++++++---- src/extension.ts | 12 +++- 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/src/decorators/dueDateDecorator.ts b/src/decorators/dueDateDecorator.ts index de028d8..7a91ce3 100644 --- a/src/decorators/dueDateDecorator.ts +++ b/src/decorators/dueDateDecorator.ts @@ -3,7 +3,8 @@ // Handles two categories of tokens: // // STATIC tokens — fixed color regardless of context: -// Project tag #project → Blue (#569CD6) +// Project tag #project → Blue (#569CD6) by default; overridden +// per-project by hexfield-deck.projects config // Priority HIGH !!! → Red (#F44747) // Priority MED !! → Yellow (#CCA700) // Priority LOW ! → Green (#89D185) @@ -20,6 +21,10 @@ // Using the Decoration API for all tokens ensures colors are absolute and // not overridden by the active VS Code theme. // +// Per-project tag colors are read from the hexfield-deck.projects configuration +// (shared with Hexfield Deck). Each unique project color gets its own cached +// TextEditorDecorationType; types are lazily created and disposed on refresh. +// // All TextEditorDecorationType instances are disposed on deactivation or // when colors are refreshed from configuration. @@ -99,6 +104,24 @@ function getProximity(dateStr: string): Proximity { return 'future'; } +// --------------------------------------------------------------------------- +// Per-project config (shared with Hexfield Deck) +// --------------------------------------------------------------------------- + +interface ProjectConfig { + color?: string; + url?: string; + style?: 'border' | 'fill' | 'both'; +} + +function getProjectsConfig(): Record { + return ( + vscode.workspace + .getConfiguration('hexfield-deck') + .get>('projects') ?? {} + ); +} + // --------------------------------------------------------------------------- // Helpers // --------------------------------------------------------------------------- @@ -120,6 +143,15 @@ function hexToRgba(hex: string, alpha: number): string { return `rgba(${r}, ${g}, ${b}, ${alpha})`; } +/** Creates a pill-border decoration type for a given project color. */ +function createProjectDecorationType(color: string): vscode.TextEditorDecorationType { + return vscode.window.createTextEditorDecorationType({ + color, + borderRadius: '4px', + border: `1px solid ${hexToRgba(color, 0.4)}`, + }); +} + function createStaticTypes(): Record { const cfg = 'hexfield.colors'; @@ -170,22 +202,27 @@ function createProximityTypes(): Record; private proximityTypes: Record; + /** Decoration types keyed by project color — lazily created, disposed on refresh. */ + private projectTypes = new Map(); constructor() { this.staticTypes = createStaticTypes(); this.proximityTypes = createProximityTypes(); } - /** Rebuild all decoration types from current configuration. */ + /** Rebuild static/proximity decoration types from current hexfield.colors config. */ refreshColors(): void { for (const t of Object.values(this.staticTypes)) t.dispose(); for (const t of Object.values(this.proximityTypes)) t.dispose(); + for (const t of this.projectTypes.values()) t.dispose(); + this.projectTypes.clear(); this.staticTypes = createStaticTypes(); this.proximityTypes = createProximityTypes(); } @@ -194,22 +231,60 @@ export class DueDateDecorator implements vscode.Disposable { decorate(editor: vscode.TextEditor): void { const text = editor.document.getText(); - // --- Static tokens --- - const staticRanges = {} as Record; - for (const token of Object.keys(STATIC_PATTERNS) as StaticToken[]) { - staticRanges[token] = []; + // --- Static tokens (all except projectTag, which is handled below) --- + for (const token of (Object.keys(STATIC_PATTERNS) as StaticToken[]).filter( + (k) => k !== 'projectTag', + )) { + const ranges: vscode.Range[] = []; const re = STATIC_PATTERNS[token]; re.lastIndex = 0; let m: RegExpExecArray | null; while ((m = re.exec(text)) !== null) { - staticRanges[token].push( + ranges.push( new vscode.Range( editor.document.positionAt(m.index), editor.document.positionAt(m.index + m[0].length), ), ); } - editor.setDecorations(this.staticTypes[token], staticRanges[token]); + editor.setDecorations(this.staticTypes[token], ranges); + } + + // --- Project tags --- + // Tags with a color in hexfield-deck.projects get a per-project pill border. + // Tags without a config entry fall back to the default projectTag decoration. + const projectsConfig = getProjectsConfig(); + const defaultTagRanges: vscode.Range[] = []; + const colorBuckets = new Map(); + + const tagRe = STATIC_PATTERNS.projectTag; + tagRe.lastIndex = 0; + let tm: RegExpExecArray | null; + while ((tm = tagRe.exec(text)) !== null) { + const name = tm[0].slice(1); // strip leading # + const color = projectsConfig[name]?.color; + const range = new vscode.Range( + editor.document.positionAt(tm.index), + editor.document.positionAt(tm.index + tm[0].length), + ); + if (color) { + if (!colorBuckets.has(color)) colorBuckets.set(color, []); + colorBuckets.get(color)!.push(range); + } else { + defaultTagRanges.push(range); + } + } + + // Clear all cached project decorations before re-applying (handles color changes). + for (const type of this.projectTypes.values()) { + editor.setDecorations(type, []); + } + editor.setDecorations(this.staticTypes.projectTag, defaultTagRanges); + for (const [color, ranges] of colorBuckets) { + if (!this.projectTypes.has(color)) { + this.projectTypes.set(color, createProjectDecorationType(color)); + } + editor.setDecorations(this.projectTypes.get(color)!, ranges); } // --- Due date proximity tokens --- @@ -236,5 +311,6 @@ export class DueDateDecorator implements vscode.Disposable { dispose(): void { for (const t of Object.values(this.staticTypes)) t.dispose(); for (const t of Object.values(this.proximityTypes)) t.dispose(); + for (const t of this.projectTypes.values()) t.dispose(); } } diff --git a/src/extension.ts b/src/extension.ts index 31be33a..babf2fe 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -131,13 +131,19 @@ export function activate(context: vscode.ExtensionContext): void { }), ); - // Rebuild decoration types and re-decorate when the user changes due date color settings. + // Rebuild decoration types and re-decorate when color or project config changes. + // hexfield.colors changes require a full refreshColors() to rebuild static types. + // hexfield-deck.projects changes only need a re-decorate to apply new tag colors. context.subscriptions.push( vscode.workspace.onDidChangeConfiguration((event) => { - if (!event.affectsConfiguration('hexfield.colors')) { + const colorsChanged = event.affectsConfiguration('hexfield.colors'); + const projectsChanged = event.affectsConfiguration('hexfield-deck.projects'); + if (!colorsChanged && !projectsChanged) { return; } - decorator.refreshColors(); + if (colorsChanged) { + decorator.refreshColors(); + } for (const editor of vscode.window.visibleTextEditors) { if (editor.document.languageId === HEXFIELD_LANGUAGE_ID) { decorator.decorate(editor); From a78029c8ddd8366d42137e48f23e084d77ddc22d Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Sat, 28 Feb 2026 12:59:08 -0700 Subject: [PATCH 14/17] Pulling back target version for now. --- package.json | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 77d488f..dde2cb9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "hexfield-text", "displayName": "Hexfield Text", "description": "Inline syntax colorization for Hexfield Deck planner files in VS Code", - "version": "1.0.0", + "version": "0.1.0", "publisher": "jimblom", "license": "MIT", "repository": { @@ -15,8 +15,16 @@ "engines": { "vscode": "^1.75.0" }, - "categories": ["Other"], - "keywords": ["markdown", "kanban", "hexfield", "task board", "syntax highlighting"], + "categories": [ + "Other" + ], + "keywords": [ + "markdown", + "kanban", + "hexfield", + "task board", + "syntax highlighting" + ], "activationEvents": [ "onLanguage:markdown", "onLanguage:hexfield-markdown", @@ -27,7 +35,10 @@ "languages": [ { "id": "hexfield-markdown", - "aliases": ["Hexfield Markdown", "hexfield-markdown"], + "aliases": [ + "Hexfield Markdown", + "hexfield-markdown" + ], "configuration": "./language-configuration.json" } ], @@ -45,7 +56,9 @@ { "scopeName": "hexfield.markdown.inline", "path": "./syntaxes/hexfield-inline-injection.tmLanguage.json", - "injectTo": ["text.hexfield.markdown"] + "injectTo": [ + "text.hexfield.markdown" + ] } ], "configuration": { From 474c9731599128d8487a478c02933e2a29a482a8 Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Sat, 28 Feb 2026 13:05:11 -0700 Subject: [PATCH 15/17] docs: add Hexfield ecosystem section to README and USER_GUIDE Frames Hexfield Text as one component in a growing ecosystem anchored to a shared file format and shared configuration namespace. Documents the design principles (independently installable, loosely coupled, same file different views) and the current component roster alongside a reference for Hexfield Deck to mirror. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 31 +++++++++++++++++++++++++++++-- USER_GUIDE.md | 12 +++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 03de344..ff2a332 100644 --- a/README.md +++ b/README.md @@ -116,11 +116,38 @@ See the [Hexfield Deck User Guide](https://github.com/jimblom/Hexfield-Deck/blob --- +## 🛰️ The Hexfield Ecosystem + +Hexfield Text is one component in a growing family of tools built around the Hexfield planner file format. Each component does one thing and composes cleanly with the others — no hard dependencies, no mandatory install order. + +### The connective tissue + +Every Hexfield component is anchored to the same two things: + +**The file format** — a plain markdown file with `type: hexfield-planner` in its YAML frontmatter. That single field is what identifies a Hexfield file. Any component can detect it, none of them own it. + +**The shared configuration namespace** — `hexfield.colors.*` for token colors, `hexfield-deck.projects.*` for per-project settings. Components contribute to and read from the same VS Code settings keys. Configure colors once; every installed component responds. + +### Current components + +| Component | What it does | +|---|---| +| **[Hexfield Deck](https://github.com/jimblom/Hexfield-Deck)** | Kanban board view — renders your planner file as a visual task board with card drag-and-drop, project filtering, and badge coloring | +| **Hexfield Text** _(this extension)_ | Editor view — colorizes planner metadata inline so the source file reflects the same visual language as the board | + +### Design principles + +- **Independently installable.** Each component works without the others present. Hexfield Text colorizes tags even if Hexfield Deck isn't installed; it just uses the default color. +- **Loosely coupled.** Components communicate through shared VS Code settings, not direct APIs or shared code. A new component can join the ecosystem by reading the same config keys. +- **Same file, different views.** A planner file is just a markdown file. Every component is a different lens on the same data — board view, editor view, and whatever comes next. + +--- + ## 🎬 About the Name -**Hexfield Text** is part of the Hexfield product family, named after the **Hexfield Viewscreen** on the Satellite of Love from _Mystery Science Theater 3000_ — the ship's iconic hexagonal display and communication screen. +Hexfield is named after the **Hexfield Viewscreen** on the Satellite of Love from _Mystery Science Theater 3000_ — the ship's iconic hexagonal display and communication screen. Each component is a different panel on that display. -**Hexfield Deck** is the board view. **Hexfield Text** is the editor layer of the same interface — the source-level view of your planner data, brought to visual life. +**Hexfield Deck** is the board. **Hexfield Text** is the editor. The Satellite of Love runs on more than one screen. --- diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 759fbfe..0866729 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -280,7 +280,13 @@ This should not happen with correct usage. If it does: --- -## Related +## The Hexfield Ecosystem -- [Hexfield Deck](https://github.com/jimblom/Hexfield-Deck) — The companion kanban board extension -- [Hexfield Deck User Guide](https://github.com/jimblom/Hexfield-Deck/blob/main/USER_GUIDE.md) — Full planner file format reference +Hexfield Text is one component in a family of tools built around the Hexfield planner file format. Components share a configuration namespace (`hexfield.colors.*`, `hexfield-deck.projects.*`) and are independently installable — each works without the others present. + +| Component | Role | +|---|---| +| **[Hexfield Deck](https://github.com/jimblom/Hexfield-Deck)** | Kanban board view of your planner file | +| **Hexfield Text** | Inline colorization in the markdown editor | + +See the [Hexfield Deck User Guide](https://github.com/jimblom/Hexfield-Deck/blob/main/USER_GUIDE.md) for the complete planner file format reference. From ca89ba2dd36f300cab01125ffd38bf032af3a29c Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Sat, 28 Feb 2026 20:01:01 -0700 Subject: [PATCH 16/17] chore: bump to v1.0.0, consolidate CHANGELOG for release Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 62 ++++++++++++++++++++++++++++------------------------ package.json | 2 +- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29771e1..c0dc350 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,47 +4,51 @@ All notable changes to Hexfield Text are documented here. Dates are in `YYYY-MM- --- -## [1.0.1] — 2026-02-27 +## [1.0.0] — 2026-02-28 -### Changed +Initial public release. -- **Breaking:** color settings migrated from `hexfield-text.colors.*` to the shared `hexfield.colors.*` namespace. If you have customized colors, rename the keys in your `settings.json` (e.g. `hexfield-text.colors.projectTag` → `hexfield.colors.projectTag`). This aligns with Hexfield Deck's upcoming adoption of the same namespace so both extensions share one settings group. +### Added ---- +- **Language promotion** — `.md` files with `type: hexfield-planner` in their YAML frontmatter are promoted to the `hexfield-markdown` language mode. Removing or changing the field reverts immediately — no VS Code reload needed. -## [1.0.0] — 2026-02-27 +- **TextMate grammar** — an injection grammar colorizes Hexfield tokens inside markdown list items, paragraphs, and other block-level scopes where a top-level grammar include cannot reach: + - Project tags (`#project`) + - Priority markers (`!!!` / `!!` / `!`) + - Time estimates (`est:2h`, `est:30m`) + - In-progress checkbox (`[/]`) + - Frontmatter keys (`type`, `week`, `year`, `quarter`, `tags`, `startDate`, `endDate`) -### Added +- **Decoration API — theme-independent token colors** — all inline tokens are colored via VS Code's Decoration API rather than relying on theme scope mappings. Colors are absolute; no theme (Dracula, One Dark, etc.) can override them: + - Project tags — blue pill border (`#569CD6` default) + - Priority HIGH / MED / LOW — red / yellow / green + - Time estimates — teal + - In-progress checkbox (`[/]`) — orange + - Due dates — dynamically colored by proximity to today: + - Overdue → red (`#F44747`) + - Today → orange (`#CE9178`) + - Within 3 days → yellow (`#CCA700`) + - Future → gray (`#858585`) -- **User-configurable due date colors** — `hexfield-text.colors.dueDateOverdue`, `dueDateToday`, `dueDateSoon`, `dueDateFuture` settings in VS Code preferences -- Due date decorator rebuilds automatically when color settings change (no reload needed) -- Extension published to VS Code Marketplace as `jimblom.hexfield-text` +- **Per-project tag colors** — `#project-tag` tokens read `hexfield-deck.projects..color` from VS Code settings. Each project renders in its configured color with a matching pill border. Tags without a configured color fall back to the `hexfield.colors.projectTag` default. ---- +- **Shared configuration namespace** — all 10 token colors are user-configurable under `hexfield.colors.*`. This namespace is shared with Hexfield Deck; configure colors once and every installed Hexfield component responds. Changes take effect live with no reload. -## [0.2.0] — 2026-02-24 +- **Ecosystem documentation** — README and User Guide document the Hexfield component model: the shared file format, shared configuration architecture, and design principles for independently-installable components. -### Added - -- **Decoration API** — dynamic due date proximity coloring (`[YYYY-MM-DD]` tokens) -- Four proximity buckets: overdue → red, today → orange, within 3 days → yellow, future → gray -- Colors mirror Hexfield Deck board badge colors exactly -- Debounced re-decoration (500ms) on every document change -- Language de-promotion — removing `type: hexfield-planner` from frontmatter while a file is open immediately reverts colorization +- Published to VS Code Marketplace as `jimblom.hexfield-text`. --- -## [0.1.0] — 2026-02-23 +## Development milestones (pre-release) -### Added +### [0.2.0] — 2026-02-24 -- Initial release -- Custom language ID (`hexfield-markdown`) promoted from `.md` files containing `type: hexfield-planner` in YAML frontmatter -- TextMate grammar (`hexfield-deck.tmLanguage.json`) scoped to `hexfield-markdown` only: - - Project tags (`#tag`) — blue - - Due date brackets (`[YYYY-MM-DD]`) — default gray (overridden by Decoration API) - - Priority HIGH / MED / LOW (`!!!` / `!!` / `!`) — red / yellow / green - - Time estimates (`est:Xh`, `est:Xm`) — teal - - In-progress checkbox (`[/]`) — orange - - Frontmatter keys (`type`, `week`, `year`, `quarter`, `tags`, `startDate`, `endDate`) — purple +- Decoration API for dynamic due date proximity coloring +- Debounced re-decoration (500ms) on document change +- Language de-promotion when frontmatter field is removed + +### [0.1.0] — 2026-02-23 + +- Extension scaffold, language promotion logic, TextMate grammar - Zero false-positive colorization on regular markdown files diff --git a/package.json b/package.json index dde2cb9..5bc4576 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "hexfield-text", "displayName": "Hexfield Text", "description": "Inline syntax colorization for Hexfield Deck planner files in VS Code", - "version": "0.1.0", + "version": "1.0.0", "publisher": "jimblom", "license": "MIT", "repository": { From 7e61ca7c840aa5d42664df2664d3c2149d290d66 Mon Sep 17 00:00:00 2001 From: Jim Lindblom Date: Sun, 1 Mar 2026 21:12:17 -0700 Subject: [PATCH 17/17] chore: set version to 0.1.0 for initial release Co-Authored-By: Claude Sonnet 4.6 --- CHANGELOG.md | 16 +--------------- package.json | 2 +- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0dc350..9d5b606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to Hexfield Text are documented here. Dates are in `YYYY-MM- --- -## [1.0.0] — 2026-02-28 +## [0.1.0] — 2026-03-01 Initial public release. @@ -38,17 +38,3 @@ Initial public release. - Published to VS Code Marketplace as `jimblom.hexfield-text`. ---- - -## Development milestones (pre-release) - -### [0.2.0] — 2026-02-24 - -- Decoration API for dynamic due date proximity coloring -- Debounced re-decoration (500ms) on document change -- Language de-promotion when frontmatter field is removed - -### [0.1.0] — 2026-02-23 - -- Extension scaffold, language promotion logic, TextMate grammar -- Zero false-positive colorization on regular markdown files diff --git a/package.json b/package.json index 5bc4576..dde2cb9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "hexfield-text", "displayName": "Hexfield Text", "description": "Inline syntax colorization for Hexfield Deck planner files in VS Code", - "version": "1.0.0", + "version": "0.1.0", "publisher": "jimblom", "license": "MIT", "repository": {