diff --git a/main.ts b/main.ts index 2fe7693..f544fd4 100644 --- a/main.ts +++ b/main.ts @@ -1,26 +1,19 @@ -import { App, Editor, Plugin, PluginSettingTab, Setting } from "obsidian"; - -interface AutoCloseTagsSettings { - excludedTags: string; - cursorPosition: "between" | "after"; - ignoreInCodeBlocks: boolean; - ignoreInlineCode: boolean; -} - -const DEFAULT_SETTINGS: AutoCloseTagsSettings = { - excludedTags: "", - cursorPosition: "between", - ignoreInCodeBlocks: false, - ignoreInlineCode: true, -}; +import { Editor, Plugin } from "obsidian"; +import { AutoCloseTagsSettings } from "./src/types"; +import { SettingsManager } from "./src/settings"; +import { TagProcessor } from "./src/tag-processor"; +import { AutoCloseTagsSettingTab } from "./src/settings-tab"; export default class AutoCloseTags extends Plugin { private allowAutoClose: boolean = false; - settings: AutoCloseTagsSettings; - private lastProcessedPosition: { line: number; ch: number } | null = null; + private settingsManager: SettingsManager; + private tagProcessor: TagProcessor; async onload() { - await this.loadSettings(); + this.settingsManager = new SettingsManager(this); + await this.settingsManager.loadSettings(); + + this.tagProcessor = new TagProcessor(this.settingsManager.settings); this.registerDomEvent(document, "paste", () => { this.allowAutoClose = true; @@ -54,12 +47,12 @@ export default class AutoCloseTags extends Plugin { handleTyping(editor: Editor) { const cursor = editor.getCursor(); - const line = editor.getLine(cursor.line); + const lastPos = this.tagProcessor.getLastProcessedPosition(); if ( - this.lastProcessedPosition && - this.lastProcessedPosition.line === cursor.line && - this.lastProcessedPosition.ch === cursor.ch + lastPos && + lastPos.line === cursor.line && + lastPos.ch === cursor.ch ) { return; } @@ -67,305 +60,32 @@ export default class AutoCloseTags extends Plugin { if (!this.allowAutoClose) return; this.allowAutoClose = false; - if (cursor.ch === 0 || line[cursor.ch - 1] !== ">") { - return; - } - - const beforeCursor = line.slice(0, cursor.ch); - - const tagMatch = beforeCursor.match(/<([a-zA-Z][\w\-]*)\s*([^>]*)>$/); - - if ( - !tagMatch || - beforeCursor.endsWith("/>") || - beforeCursor.endsWith(" t.trim().toLowerCase()) - .filter((t) => t.length > 0); - - if (excluded.includes(tag.toLowerCase())) return; - - if ( - (this.settings.ignoreInCodeBlocks && - this.isInCodeBlock(editor, cursor.line)) || - (this.settings.ignoreInlineCode && - this.isInInlineCode(line, cursor.ch)) - ) { - return; - } - - const closingTag = ``; - const insertPos = { line: cursor.line, ch: cursor.ch }; - - this.lastProcessedPosition = { line: cursor.line, ch: cursor.ch }; - - editor.replaceRange(closingTag, insertPos); - - if (this.settings.cursorPosition === "between") { - editor.setCursor({ line: cursor.line, ch: cursor.ch }); - } else { - editor.setCursor({ - line: cursor.line, - ch: cursor.ch + closingTag.length, - }); - } - - setTimeout(() => { - this.lastProcessedPosition = null; - }, 100); - } - - hasMatchingClosingTag( - editor: Editor, - tagName: string, - fromLine: number, - fromCh: number - ): boolean { - const content = editor.getValue(); - const lines = content.split("\n"); - - let openCount = 1; - - for (let i = fromLine; i < lines.length; i++) { - const line = lines[i]; - const searchFrom = i === fromLine ? fromCh : 0; - const searchLine = line.slice(searchFrom); - - const openMatches = [ - ...searchLine.matchAll( - new RegExp(`<${tagName}(?:\\s[^>]*)?>`, "gi") - ), - ]; - openCount += openMatches.length; - - const closeMatches = [ - ...searchLine.matchAll(new RegExp(``, "gi")), - ]; - openCount -= closeMatches.length; - - if (openCount <= 0) { - return true; - } - } - - return false; - } - - insertClosingTag(editor: Editor) { - const content = editor.getValue(); - const lines = content.split("\n"); - - const excluded = this.settings.excludedTags - .split(",") - .map((t) => t.trim().toLowerCase()) - .filter((t) => t.length > 0); - - const openTags: { tag: string; line: number }[] = []; - const closeTags: string[] = []; - - let insideCodeBlock = false; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - - if (line.trim().startsWith("```")) { - insideCodeBlock = !insideCodeBlock; - continue; - } - - if (this.settings.ignoreInCodeBlocks && insideCodeBlock) continue; - - const openMatches = [ - ...line.matchAll(/<([a-zA-Z][\w\-]*)\s*([^>]*?)>/g), - ]; - for (const match of openMatches) { - const raw = match[0]; - const tag = match[1].toLowerCase(); - const matchIndex = match.index ?? 0; - - if (excluded.includes(tag)) continue; - if (this.isSelfClosing(raw)) continue; - if ( - this.settings.ignoreInlineCode && - this.isInInlineCode(line, matchIndex) - ) - continue; - - openTags.push({ tag, line: i }); - } - - const closeMatches = [...line.matchAll(/<\/([a-zA-Z][\w\-]*)>/g)]; - for (const match of closeMatches) { - const matchIndex = match.index ?? 0; - if ( - this.settings.ignoreInlineCode && - this.isInInlineCode(line, matchIndex) - ) - continue; - closeTags.push(match[1].toLowerCase()); - } - } - - for (const closeTag of closeTags) { - const openIndex = openTags.findLastIndex( - (openTag) => openTag.tag === closeTag - ); - if (openIndex !== -1) { - openTags.splice(openIndex, 1); - } - } - - if (openTags.length === 0) { - return; - } - - const tagToClose = openTags[openTags.length - 1].tag; - const closingTag = ``; - const cursor = editor.getCursor(); - - editor.replaceRange(closingTag, cursor); - - if (this.settings.cursorPosition === "after") { - editor.setCursor({ - line: cursor.line, - ch: cursor.ch + closingTag.length, - }); - } else { - editor.setCursor(cursor); - } - } - - isSelfClosing(tag: string): boolean { - if (/\/\s*>$/.test(tag)) return true; - - const voidElements = [ - "area", - "base", - "br", - "col", - "embed", - "hr", - "img", - "input", - "link", - "meta", - "source", - "track", - "wbr", - ]; - - const tagName = tag.match(/<([a-zA-Z][\w\-]*)/)?.[1]?.toLowerCase(); - return tagName ? voidElements.includes(tagName) : false; - } - - isInCodeBlock(editor: Editor, line: number): boolean { - let inCodeBlock = false; - for (let i = 0; i <= line; i++) { - const currentLine = editor.getLine(i); - if (currentLine && currentLine.trim().startsWith("```")) { - inCodeBlock = !inCodeBlock; - } - } - return inCodeBlock; - } - - isInInlineCode(line: string, index: number): boolean { - const before = line.slice(0, index); - const backticks = (before.match(/`/g) || []).length; - return backticks % 2 === 1; - } - - async loadSettings() { - this.settings = Object.assign( - {}, - DEFAULT_SETTINGS, - await this.loadData() + this.tagProcessor.autoCloseTag( + editor, + this.settingsManager.getExcludedTags() ); } - async saveSettings() { - await this.saveData(this.settings); - } -} - -/* ---------------------------- Settings Tab ---------------------------- */ -class AutoCloseTagsSettingTab extends PluginSettingTab { - plugin: AutoCloseTags; - - constructor(app: App, plugin: AutoCloseTags) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - const { containerEl } = this; - containerEl.empty(); - - new Setting(containerEl) - .setName("Excluded tags") - .setDesc( - "Comma-separated list of tags that should not be auto-closed (e.g., div, span, i)." - ) - .addText((text) => - text - .setPlaceholder("e.g., div, span, i") - .setValue(this.plugin.settings.excludedTags) - .onChange(async (value) => { - this.plugin.settings.excludedTags = value; - await this.plugin.saveSettings(); - }) - ); - - new Setting(containerEl) - .setName("Cursor position after auto-close") - .setDesc("Where to place the cursor after auto-closing a tag.") - .addDropdown((dropdown) => - dropdown - .addOption("between", "Between tags") - .addOption("after", "After closing tag") - .setValue(this.plugin.settings.cursorPosition) - .onChange(async (value: "between" | "after") => { - this.plugin.settings.cursorPosition = value; - await this.plugin.saveSettings(); - }) - ); - - new Setting(containerEl) - .setName("Ignore fenced code blocks") - .setDesc( - "Avoid auto-closing tags inside Markdown code blocks (``` blocks)." - ) - .addToggle((toggle) => - toggle - .setValue(this.plugin.settings.ignoreInCodeBlocks) - .onChange(async (value) => { - this.plugin.settings.ignoreInCodeBlocks = value; - await this.plugin.saveSettings(); - }) - ); - - new Setting(containerEl) - .setName("Ignore inline code") - .setDesc( - "Avoid auto-closing tags inside inline code spans (e.g., `
`)." - ) - .addToggle((toggle) => - toggle - .setValue(this.plugin.settings.ignoreInlineCode) - .onChange(async (value) => { - this.plugin.settings.ignoreInlineCode = value; - await this.plugin.saveSettings(); - }) - ); + insertClosingTag(editor: Editor) { + this.tagProcessor.insertClosingTag( + editor, + this.settingsManager.getExcludedTags() + ); + } + + getSettings(): AutoCloseTagsSettings { + return this.settingsManager.settings; + } + + updateSetting( + key: K, + value: AutoCloseTagsSettings[K] + ): void { + this.settingsManager.settings[key] = value; + this.tagProcessor.updateSettings(this.settingsManager.settings); + } + + async saveSettings(): Promise { + await this.settingsManager.saveSettings(); } } diff --git a/package-lock.json b/package-lock.json index bb3f2dc..729a461 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { - "name": "obsidian-sample-plugin", - "version": "1.0.0", + "name": "auto-close-tags", + "version": "1.1.2", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "obsidian-sample-plugin", - "version": "1.0.0", + "name": "auto-close-tags", + "version": "1.1.2", "license": "MIT", "devDependencies": { "@types/node": "^16.11.6", @@ -24,16 +24,18 @@ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "node_modules/@codemirror/view": { - "version": "6.37.2", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.37.2.tgz", - "integrity": "sha512-XD3LdgQpxQs5jhOOZ2HRVT+Rj59O4Suc7g2ULvZ+Yi8eCkickrkZ5JFuoDhs2ST1mNI5zSsNYgR3NGa4OUrbnw==", + "version": "6.38.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz", + "integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", @@ -50,6 +52,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -66,6 +69,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -82,6 +86,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" @@ -98,6 +103,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -114,6 +120,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -130,6 +137,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -146,6 +154,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" @@ -162,6 +171,7 @@ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -178,6 +188,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -194,6 +205,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -210,6 +222,7 @@ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -226,6 +239,7 @@ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -242,6 +256,7 @@ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -258,6 +273,7 @@ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -274,6 +290,7 @@ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -290,6 +307,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -306,6 +324,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" @@ -322,6 +341,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" @@ -338,6 +358,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" @@ -354,6 +375,7 @@ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -370,6 +392,7 @@ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -386,6 +409,7 @@ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -399,6 +423,7 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -418,6 +443,7 @@ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -428,6 +454,7 @@ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ajv": "^6.12.4", @@ -452,6 +479,7 @@ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -463,6 +491,7 @@ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", @@ -478,6 +507,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "peer": true, "engines": { "node": ">=12.22" @@ -493,6 +523,7 @@ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", "deprecated": "Use @eslint/object-schema instead", "dev": true, + "license": "BSD-3-Clause", "peer": true }, "node_modules/@marijn/find-cluster-break": { @@ -500,6 +531,7 @@ "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@nodelib/fs.scandir": { @@ -507,6 +539,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -520,6 +553,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -529,6 +563,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -542,6 +577,7 @@ "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", "dev": true, + "license": "MIT", "dependencies": { "@types/tern": "*" } @@ -550,25 +586,29 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { "version": "16.18.126", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/tern": { "version": "0.23.9", "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*" } @@ -578,6 +618,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/scope-manager": "5.29.0", "@typescript-eslint/type-utils": "5.29.0", @@ -611,6 +652,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/scope-manager": "5.29.0", "@typescript-eslint/types": "5.29.0", @@ -638,6 +680,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.29.0", "@typescript-eslint/visitor-keys": "5.29.0" @@ -655,6 +698,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/utils": "5.29.0", "debug": "^4.3.4", @@ -681,6 +725,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -694,6 +739,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "@typescript-eslint/types": "5.29.0", "@typescript-eslint/visitor-keys": "5.29.0", @@ -721,6 +767,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", "dev": true, + "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.9", "@typescript-eslint/scope-manager": "5.29.0", @@ -745,6 +792,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", "dev": true, + "license": "MIT", "dependencies": { "@typescript-eslint/types": "5.29.0", "eslint-visitor-keys": "^3.3.0" @@ -762,6 +810,7 @@ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/acorn": { @@ -769,6 +818,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "license": "MIT", "peer": true, "bin": { "acorn": "bin/acorn" @@ -782,6 +832,7 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peer": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -792,6 +843,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -809,6 +861,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -819,6 +872,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "color-convert": "^2.0.1" @@ -835,6 +889,7 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, + "license": "Python-2.0", "peer": true }, "node_modules/array-union": { @@ -842,6 +897,7 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -851,6 +907,7 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/brace-expansion": { @@ -858,6 +915,7 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0", @@ -869,6 +927,7 @@ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -881,6 +940,7 @@ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -893,6 +953,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -903,6 +964,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-styles": "^4.1.0", @@ -920,6 +982,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "color-name": "~1.1.4" @@ -933,6 +996,7 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/concat-map": { @@ -940,6 +1004,7 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/crelt": { @@ -947,6 +1012,7 @@ "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/cross-spawn": { @@ -954,6 +1020,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "path-key": "^3.1.0", @@ -969,6 +1036,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.3" }, @@ -986,6 +1054,7 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/dir-glob": { @@ -993,6 +1062,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -1005,6 +1075,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "peer": true, "dependencies": { "esutils": "^2.0.2" @@ -1019,6 +1090,7 @@ "integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, @@ -1055,6 +1127,7 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -1069,6 +1142,7 @@ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -1125,6 +1199,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -1138,6 +1213,7 @@ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -1156,6 +1232,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10" } @@ -1165,6 +1242,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -1177,6 +1255,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "esrecurse": "^4.3.0", @@ -1194,6 +1273,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -1204,6 +1284,7 @@ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "acorn": "^8.9.0", @@ -1222,6 +1303,7 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "peer": true, "dependencies": { "estraverse": "^5.1.0" @@ -1235,6 +1317,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=4.0" @@ -1245,6 +1328,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -1257,6 +1341,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1266,6 +1351,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -1275,6 +1361,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "engines": { "node": ">=0.10.0" @@ -1285,6 +1372,7 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fast-glob": { @@ -1292,6 +1380,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -1308,6 +1397,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -1320,6 +1410,7 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fast-levenshtein": { @@ -1327,6 +1418,7 @@ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/fastq": { @@ -1334,6 +1426,7 @@ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -1343,6 +1436,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "flat-cache": "^3.0.4" @@ -1356,6 +1450,7 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1368,6 +1463,7 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "locate-path": "^6.0.0", @@ -1385,6 +1481,7 @@ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "flatted": "^3.2.9", @@ -1400,6 +1497,7 @@ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/fs.realpath": { @@ -1407,13 +1505,15 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/glob": { "version": "7.2.3", @@ -1421,6 +1521,7 @@ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -1442,6 +1543,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -1455,6 +1557,7 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "type-fest": "^0.20.2" @@ -1471,6 +1574,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -1491,6 +1595,7 @@ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/has-flag": { @@ -1498,6 +1603,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1508,6 +1614,7 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -1517,6 +1624,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "parent-module": "^1.0.0", @@ -1534,6 +1642,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.8.19" @@ -1545,6 +1654,7 @@ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "once": "^1.3.0", @@ -1556,6 +1666,7 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/is-extglob": { @@ -1563,6 +1674,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1572,6 +1684,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -1584,6 +1697,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -1593,6 +1707,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1603,6 +1718,7 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/js-yaml": { @@ -1610,6 +1726,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "argparse": "^2.0.1" @@ -1623,6 +1740,7 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/json-schema-traverse": { @@ -1630,6 +1748,7 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/json-stable-stringify-without-jsonify": { @@ -1637,6 +1756,7 @@ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/keyv": { @@ -1644,6 +1764,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "json-buffer": "3.0.1" @@ -1654,6 +1775,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1", @@ -1668,6 +1790,7 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "p-locate": "^5.0.0" @@ -1684,6 +1807,7 @@ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/merge2": { @@ -1691,6 +1815,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -1700,6 +1825,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -1713,6 +1839,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -1726,6 +1853,7 @@ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -1734,13 +1862,15 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/obsidian": { @@ -1748,6 +1878,7 @@ "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz", "integrity": "sha512-h4bWwNFAGRXlMlMAzdEiIM2ppTGlrh7uGOJS6w4gClrsjc+ei/3YAtU2VdFUlCiPuTHpY4aBpFJJW75S1Tl/JA==", "dev": true, + "license": "MIT", "dependencies": { "@types/codemirror": "5.60.8", "moment": "2.29.4" @@ -1762,6 +1893,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "wrappy": "1" @@ -1772,6 +1904,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "deep-is": "^0.1.3", @@ -1790,6 +1923,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "yocto-queue": "^0.1.0" @@ -1806,6 +1940,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "p-limit": "^3.0.2" @@ -1822,6 +1957,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "callsites": "^3.0.0" @@ -1835,6 +1971,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1845,6 +1982,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -1855,6 +1993,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1865,6 +2004,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -1874,6 +2014,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -1886,6 +2027,7 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 0.8.0" @@ -1896,6 +2038,7 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6" @@ -1919,13 +2062,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -1938,6 +2083,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=4" @@ -1948,6 +2094,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -1959,6 +2106,7 @@ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "glob": "^7.1.3" @@ -1989,6 +2137,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -1998,6 +2147,7 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -2010,6 +2160,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "shebang-regex": "^3.0.0" @@ -2023,6 +2174,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -2033,6 +2185,7 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -2042,6 +2195,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-regex": "^5.0.1" @@ -2055,6 +2209,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -2068,6 +2223,7 @@ "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/supports-color": { @@ -2075,6 +2231,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "has-flag": "^4.0.0" @@ -2088,6 +2245,7 @@ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/to-regex-range": { @@ -2095,6 +2253,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -2106,13 +2265,15 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^1.8.1" }, @@ -2127,13 +2288,15 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "dev": true, + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "prelude-ls": "^1.2.1" @@ -2147,6 +2310,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "peer": true, "engines": { "node": ">=10" @@ -2160,6 +2324,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2173,6 +2338,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "peer": true, "dependencies": { "punycode": "^2.1.0" @@ -2183,6 +2349,7 @@ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/which": { @@ -2190,6 +2357,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "isexe": "^2.0.0" @@ -2206,6 +2374,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -2216,6 +2385,7 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/yocto-queue": { @@ -2223,6 +2393,7 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=10" diff --git a/src/settings-tab.ts b/src/settings-tab.ts new file mode 100644 index 0000000..330bb15 --- /dev/null +++ b/src/settings-tab.ts @@ -0,0 +1,73 @@ +import { App, PluginSettingTab, Setting } from "obsidian"; +import AutoCloseTags from "../main"; + +export class AutoCloseTagsSettingTab extends PluginSettingTab { + plugin: AutoCloseTags; + + constructor(app: App, plugin: AutoCloseTags) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + const { containerEl } = this; + containerEl.empty(); + + new Setting(containerEl) + .setName("Excluded tags") + .setDesc( + "Comma-separated list of tags that should not be auto-closed (e.g., div, span, i)." + ) + .addText((text) => + text + .setPlaceholder("e.g., div, span, i") + .setValue(this.plugin.getSettings().excludedTags) + .onChange(async (value) => { + this.plugin.updateSetting("excludedTags", value); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("Cursor position after auto-close") + .setDesc("Where to place the cursor after auto-closing a tag.") + .addDropdown((dropdown) => + dropdown + .addOption("between", "Between tags") + .addOption("after", "After closing tag") + .setValue(this.plugin.getSettings().cursorPosition) + .onChange(async (value: "between" | "after") => { + this.plugin.updateSetting("cursorPosition", value); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("Ignore fenced code blocks") + .setDesc( + "Avoid auto-closing tags inside Markdown code blocks (``` blocks)." + ) + .addToggle((toggle) => + toggle + .setValue(this.plugin.getSettings().ignoreInCodeBlocks) + .onChange(async (value) => { + this.plugin.updateSetting("ignoreInCodeBlocks", value); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("Ignore inline code") + .setDesc( + "Avoid auto-closing tags inside inline code spans (e.g., `
`)." + ) + .addToggle((toggle) => + toggle + .setValue(this.plugin.getSettings().ignoreInlineCode) + .onChange(async (value) => { + this.plugin.updateSetting("ignoreInlineCode", value); + await this.plugin.saveSettings(); + }) + ); + } +} diff --git a/src/settings.ts b/src/settings.ts new file mode 100644 index 0000000..b6073b6 --- /dev/null +++ b/src/settings.ts @@ -0,0 +1,31 @@ +import { Plugin } from "obsidian"; +import { AutoCloseTagsSettings, DEFAULT_SETTINGS } from "./types"; + +export class SettingsManager { + private plugin: Plugin; + public settings: AutoCloseTagsSettings; + + constructor(plugin: Plugin) { + this.plugin = plugin; + this.settings = { ...DEFAULT_SETTINGS }; + } + + async loadSettings(): Promise { + this.settings = Object.assign( + {}, + DEFAULT_SETTINGS, + await this.plugin.loadData() + ); + } + + async saveSettings(): Promise { + await this.plugin.saveData(this.settings); + } + + getExcludedTags(): string[] { + return this.settings.excludedTags + .split(",") + .map((t) => t.trim().toLowerCase()) + .filter((t) => t.length > 0); + } +} diff --git a/src/tag-detector.ts b/src/tag-detector.ts new file mode 100644 index 0000000..630e76f --- /dev/null +++ b/src/tag-detector.ts @@ -0,0 +1,102 @@ +import { Editor } from "obsidian"; +import { AutoCloseTagsSettings } from "./types"; + +export class TagDetector { + private settings: AutoCloseTagsSettings; + + constructor(settings: AutoCloseTagsSettings) { + this.settings = settings; + } + + updateSettings(settings: AutoCloseTagsSettings): void { + this.settings = settings; + } + + isSelfClosing(tag: string): boolean { + if (/\/\s*>$/.test(tag)) return true; + + const voidElements = [ + "area", + "base", + "br", + "col", + "embed", + "hr", + "img", + "input", + "link", + "meta", + "source", + "track", + "wbr", + ]; + + const tagName = tag.match(/<([a-zA-Z][\w\-]*)/)?.[1]?.toLowerCase(); + return tagName ? voidElements.includes(tagName) : false; + } + + isInCodeBlock(editor: Editor, line: number): boolean { + let inCodeBlock = false; + for (let i = 0; i <= line; i++) { + const currentLine = editor.getLine(i); + if (currentLine && currentLine.trim().startsWith("```")) { + inCodeBlock = !inCodeBlock; + } + } + return inCodeBlock; + } + + isInInlineCode(line: string, index: number): boolean { + const before = line.slice(0, index); + const backticks = (before.match(/`/g) || []).length; + return backticks % 2 === 1; + } + + isTagExcluded(tag: string, excludedTags: string[]): boolean { + return excludedTags.includes(tag.toLowerCase()); + } + + shouldIgnorePosition( + editor: Editor, + line: string, + lineNumber: number, + position: number + ): boolean { + if ( + this.settings.ignoreInCodeBlocks && + this.isInCodeBlock(editor, lineNumber) + ) { + return true; + } + + if ( + this.settings.ignoreInlineCode && + this.isInInlineCode(line, position) + ) { + return true; + } + + return false; + } + + extractTagFromLine( + line: string, + cursorPosition: number + ): { tag: string; fullTag: string } | null { + const beforeCursor = line.slice(0, cursorPosition); + const tagMatch = beforeCursor.match(/<([a-zA-Z][\w\-]*)\s*([^>]*)>$/); + + if ( + !tagMatch || + beforeCursor.endsWith("/>") || + beforeCursor.endsWith("") { + return false; + } + + const tagInfo = this.tagDetector.extractTagFromLine(line, cursor.ch); + if (!tagInfo) { + return false; + } + + const { tag, fullTag } = tagInfo; + + if (this.tagDetector.isSelfClosing(fullTag)) { + return false; + } + + if (this.tagDetector.isTagExcluded(tag, excludedTags)) { + return false; + } + + if ( + this.tagDetector.shouldIgnorePosition( + editor, + line, + cursor.line, + cursor.ch + ) + ) { + return false; + } + + const closingTag = ``; + const insertPos = { line: cursor.line, ch: cursor.ch }; + + this.lastProcessedPosition = { line: cursor.line, ch: cursor.ch }; + + editor.replaceRange(closingTag, insertPos); + + if (this.settings.cursorPosition === "between") { + editor.setCursor({ line: cursor.line, ch: cursor.ch }); + } else { + editor.setCursor({ + line: cursor.line, + ch: cursor.ch + closingTag.length, + }); + } + + setTimeout(() => { + this.lastProcessedPosition = null; + }, 100); + + return true; + } + + hasMatchingClosingTag( + editor: Editor, + tagName: string, + fromLine: number, + fromCh: number + ): boolean { + const content = editor.getValue(); + const lines = content.split("\n"); + + let openCount = 1; + + for (let i = fromLine; i < lines.length; i++) { + const line = lines[i]; + const searchFrom = i === fromLine ? fromCh : 0; + const searchLine = line.slice(searchFrom); + + const openMatches = [ + ...searchLine.matchAll( + new RegExp(`<${tagName}(?:\\s[^>]*)?>`, "gi") + ), + ]; + openCount += openMatches.length; + + const closeMatches = [ + ...searchLine.matchAll(new RegExp(``, "gi")), + ]; + openCount -= closeMatches.length; + + if (openCount <= 0) { + return true; + } + } + + return false; + } + + insertClosingTag(editor: Editor, excludedTags: string[]): void { + const content = editor.getValue(); + const lines = content.split("\n"); + + const openTags: { tag: string; line: number }[] = []; + const closeTags: string[] = []; + + let insideCodeBlock = false; + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + + if (line.trim().startsWith("```")) { + insideCodeBlock = !insideCodeBlock; + continue; + } + + if (this.settings.ignoreInCodeBlocks && insideCodeBlock) continue; + + const openMatches = [ + ...line.matchAll(/<([a-zA-Z][\w\-]*)\s*([^>]*?)>/g), + ]; + for (const match of openMatches) { + const raw = match[0]; + const tag = match[1].toLowerCase(); + const matchIndex = match.index ?? 0; + + if (excludedTags.includes(tag)) continue; + if (this.tagDetector.isSelfClosing(raw)) continue; + if ( + this.settings.ignoreInlineCode && + this.tagDetector.isInInlineCode(line, matchIndex) + ) + continue; + + openTags.push({ tag, line: i }); + } + + const closeMatches = [...line.matchAll(/<\/([a-zA-Z][\w\-]*)>/g)]; + for (const match of closeMatches) { + const matchIndex = match.index ?? 0; + if ( + this.settings.ignoreInlineCode && + this.tagDetector.isInInlineCode(line, matchIndex) + ) + continue; + closeTags.push(match[1].toLowerCase()); + } + } + + for (const closeTag of closeTags) { + const openIndex = openTags.findLastIndex( + (openTag) => openTag.tag === closeTag + ); + if (openIndex !== -1) { + openTags.splice(openIndex, 1); + } + } + + if (openTags.length === 0) { + return; + } + + const tagToClose = openTags[openTags.length - 1].tag; + const closingTag = ``; + const cursor = editor.getCursor(); + + editor.replaceRange(closingTag, cursor); + + if (this.settings.cursorPosition === "after") { + editor.setCursor({ + line: cursor.line, + ch: cursor.ch + closingTag.length, + }); + } else { + editor.setCursor(cursor); + } + } +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..02b0596 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,13 @@ +export interface AutoCloseTagsSettings { + excludedTags: string; + cursorPosition: "between" | "after"; + ignoreInCodeBlocks: boolean; + ignoreInlineCode: boolean; +} + +export const DEFAULT_SETTINGS: AutoCloseTagsSettings = { + excludedTags: "", + cursorPosition: "between", + ignoreInCodeBlocks: false, + ignoreInlineCode: true, +};