├── semantic-search ├── context-fetcher-plugin │ ├── .npmrc │ ├── .eslintignore │ ├── versions.json │ ├── .editorconfig │ ├── manifest.json │ ├── .gitignore │ ├── tsconfig.json │ ├── LICENSE │ ├── version-bump.mjs │ ├── .eslintrc │ ├── package.json │ ├── esbuild.config.mjs │ ├── ContextFetcherService.ts │ ├── styles.css │ ├── ContextFetcherView.ts │ ├── chroma_query.py │ ├── README.md │ ├── main.ts │ ├── ChromaDBService.ts │ └── package-lock.json └── chroma │ ├── requirements.txt │ ├── otel-collector-config.yaml │ ├── main.py │ ├── clear-collection.py │ ├── docker-compose.yml │ └── reindex.py ├── LICENSE ├── README.md ├── quizmaster ├── quiz-app │ ├── README.md │ ├── index.html │ ├── styles.css │ └── quiz-engine.js └── .claude │ └── commands │ └── generate-quiz.md └── reverse-engineer-slidedeck └── .claude └── commands └── reverse-engineer-slidedeck.md /semantic-search/context-fetcher-plugin/.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix="" -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | 3 | main.js 4 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "1.0.0": "0.15.0" 3 | } 4 | -------------------------------------------------------------------------------- /semantic-search/chroma/requirements.txt: -------------------------------------------------------------------------------- 1 | #pip install -r requirements.txt 2 | chromadb 3 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = 4 10 | tab_width = 4 11 | -------------------------------------------------------------------------------- /semantic-search/chroma/otel-collector-config.yaml: -------------------------------------------------------------------------------- 1 | receivers: 2 | otlp: 3 | protocols: 4 | grpc: 5 | endpoint: 0.0.0.0:4317 6 | http: 7 | endpoint: 0.0.0.0:4318 8 | 9 | exporters: 10 | debug: 11 | zipkin: 12 | endpoint: "http://zipkin:9411/api/v2/spans" 13 | 14 | service: 15 | pipelines: 16 | traces: 17 | receivers: [otlp] 18 | exporters: [zipkin, debug] 19 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "context-fetcher-plugin", 3 | "name": "LLM-based Context Fetcher Plugin", 4 | "version": "1.0.0", 5 | "minAppVersion": "0.15.0", 6 | "description": "Searches the vault for potentially relevant notes.", 7 | "author": "Obsidian", 8 | "authorUrl": "https://obsidian.md", 9 | "fundingUrl": "https://obsidian.md/pricing", 10 | "isDesktopOnly": false 11 | } -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/.gitignore: -------------------------------------------------------------------------------- 1 | # vscode 2 | .vscode 3 | 4 | # Intellij 5 | *.iml 6 | .idea 7 | 8 | # npm 9 | node_modules 10 | 11 | # Don't include the compiled main.js file in the repo. 12 | # They should be uploaded to GitHub releases instead. 13 | main.js 14 | 15 | # Exclude sourcemaps 16 | *.map 17 | 18 | # obsidian 19 | data.json 20 | 21 | # Exclude macOS Finder (System Explorer) View States 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "inlineSourceMap": true, 5 | "inlineSources": true, 6 | "module": "ESNext", 7 | "target": "ES6", 8 | "allowJs": true, 9 | "noImplicitAny": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "isolatedModules": true, 13 | "strictNullChecks": true, 14 | "lib": [ 15 | "DOM", 16 | "ES5", 17 | "ES6", 18 | "ES7" 19 | ] 20 | }, 21 | "include": [ 22 | "**/*.ts" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2020-2025 by Dynalist Inc. 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/version-bump.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync, writeFileSync } from "fs"; 2 | 3 | const targetVersion = process.env.npm_package_version; 4 | 5 | // read minAppVersion from manifest.json and bump version to target version 6 | let manifest = JSON.parse(readFileSync("manifest.json", "utf8")); 7 | const { minAppVersion } = manifest; 8 | manifest.version = targetVersion; 9 | writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t")); 10 | 11 | // update versions.json with target version and minAppVersion from manifest.json 12 | let versions = JSON.parse(readFileSync("versions.json", "utf8")); 13 | versions[targetVersion] = minAppVersion; 14 | writeFileSync("versions.json", JSON.stringify(versions, null, "\t")); 15 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "env": { "node": true }, 5 | "plugins": [ 6 | "@typescript-eslint" 7 | ], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/eslint-recommended", 11 | "plugin:@typescript-eslint/recommended" 12 | ], 13 | "parserOptions": { 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "no-unused-vars": "off", 18 | "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], 19 | "@typescript-eslint/ban-ts-comment": "off", 20 | "no-prototype-builtins": "off", 21 | "@typescript-eslint/no-empty-function": "off" 22 | } 23 | } -------------------------------------------------------------------------------- /semantic-search/chroma/main.py: -------------------------------------------------------------------------------- 1 | # λ docker compose up --build -d 2 | import chromadb 3 | 4 | def main(): 5 | """chromadb hello world""" 6 | print("Main started") 7 | chroma_client = chromadb.HttpClient(host='localhost', port=8000) 8 | 9 | collection = chroma_client.get_or_create_collection(name="notes") 10 | 11 | collection.add( 12 | ids=["id1", "id2"], 13 | documents=[ 14 | "This is a document about pineapple", 15 | "This is a document about oranges" 16 | ] 17 | ) 18 | 19 | results = collection.query( 20 | query_texts=["This is a query document about hawaii"], # Chroma will embed this for you 21 | n_results=2 # how many results to return 22 | ) 23 | print(results) 24 | 25 | 26 | print("Main ended") 27 | 28 | if __name__ == "__main__": 29 | main() -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-sample-plugin", 3 | "version": "1.0.0", 4 | "description": "This is a sample plugin for Obsidian (https://obsidian.md)", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "node esbuild.config.mjs", 8 | "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", 9 | "version": "node version-bump.mjs && git add manifest.json versions.json" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "MIT", 14 | "dependencies": {}, 15 | "devDependencies": { 16 | "@types/node": "^16.11.6", 17 | "@typescript-eslint/eslint-plugin": "5.29.0", 18 | "@typescript-eslint/parser": "5.29.0", 19 | "builtin-modules": "3.3.0", 20 | "esbuild": "0.17.3", 21 | "obsidian": "latest", 22 | "tslib": "2.4.0", 23 | "typescript": "4.7.4" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /semantic-search/chroma/clear-collection.py: -------------------------------------------------------------------------------- 1 | import chromadb 2 | import sys 3 | 4 | def main(): 5 | """Clear a chromadb collection by name (default: 'notes') 6 | 7 | Usage: 8 | python .\scripts\chroma\clear-collection.py # clears 'notes' 9 | python .\scripts\chroma\clear-collection.py mycoll # clears 'mycoll' 10 | """ 11 | collection_name = sys.argv[1] if len(sys.argv) > 1 else "notes" 12 | print(f"Clearing collection: {collection_name}") 13 | chroma_client = chromadb.HttpClient(host='localhost', port=8000) 14 | collection = chroma_client.get_or_create_collection(name=collection_name) 15 | # Remove all documents in the collection 16 | # ChromaDB does not have a direct 'clear' method, so we fetch all ids and delete them 17 | all_ids = collection.get()['ids'] 18 | if all_ids: 19 | collection.delete(ids=all_ids) 20 | print(f"Deleted {len(all_ids)} documents from collection '{collection_name}'") 21 | else: 22 | print(f"Collection '{collection_name}' is already empty.") 23 | print("Done.") 24 | 25 | if __name__ == "__main__": 26 | main() 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Jo Van Eyck 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /semantic-search/chroma/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # docker compose up --build -d 2 | # Zipkin UI at http://localhost:9411 3 | services: 4 | zipkin: 5 | image: openzipkin/zipkin 6 | ports: 7 | - "9411:9411" 8 | depends_on: [otel-collector] 9 | networks: 10 | - internal 11 | otel-collector: 12 | image: otel/opentelemetry-collector-contrib:0.111.0 13 | command: ["--config=/etc/otel-collector-config.yaml"] 14 | volumes: 15 | - ${PWD}/otel-collector-config.yaml:/etc/otel-collector-config.yaml 16 | networks: 17 | - internal 18 | server: 19 | image: chromadb/chroma 20 | volumes: 21 | - chroma_data:/data 22 | ports: 23 | - "8000:8000" 24 | networks: 25 | - internal 26 | environment: 27 | - CHROMA_OPEN_TELEMETRY__ENDPOINT=http://otel-collector:4317/ 28 | - CHROMA_OPEN_TELEMETRY__SERVICE_NAME=chroma 29 | - CHROMA_SERVER_CORS_ALLOW_ORIGINS=* 30 | - ALLOW_RESET=TRUE 31 | depends_on: 32 | - otel-collector 33 | - zipkin 34 | healthcheck: 35 | test: ["CMD", "curl", "-f", "http://localhost:8000/api/v2/heartbeat"] 36 | interval: 30s 37 | timeout: 10s 38 | retries: 3 39 | 40 | networks: 41 | internal: 42 | 43 | volumes: 44 | chroma_data: -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/esbuild.config.mjs: -------------------------------------------------------------------------------- 1 | import esbuild from "esbuild"; 2 | import process from "process"; 3 | import builtins from "builtin-modules"; 4 | 5 | const banner = 6 | `/* 7 | THIS IS A GENERATED/BUNDLED FILE BY ESBUILD 8 | if you want to view the source, please visit the github repository of this plugin 9 | */ 10 | `; 11 | 12 | const prod = (process.argv[2] === "production"); 13 | 14 | const context = await esbuild.context({ 15 | banner: { 16 | js: banner, 17 | }, 18 | entryPoints: ["main.ts"], 19 | bundle: true, 20 | external: [ 21 | "obsidian", 22 | "electron", 23 | "@codemirror/autocomplete", 24 | "@codemirror/collab", 25 | "@codemirror/commands", 26 | "@codemirror/language", 27 | "@codemirror/lint", 28 | "@codemirror/search", 29 | "@codemirror/state", 30 | "@codemirror/view", 31 | "@lezer/common", 32 | "@lezer/highlight", 33 | "@lezer/lr", 34 | "cohere-ai", 35 | "ollama", 36 | "child_process", 37 | ...builtins], 38 | format: "cjs", 39 | target: "es2020", 40 | logLevel: "info", 41 | sourcemap: prod ? false : "inline", 42 | treeShaking: true, 43 | outfile: "main.js", 44 | minify: prod, 45 | }); 46 | 47 | if (prod) { 48 | await context.rebuild(); 49 | process.exit(0); 50 | } else { 51 | await context.watch(); 52 | } 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CLAUDE.md 2 | 3 | ## Repository Architecture 4 | 5 | This is a multi-project repository focused on Obsidian AI agent integrations and semantic search capabilities. It contains three main project areas: 6 | 7 | ### Core Projects 8 | 9 | 1. **Semantic Search System** (`semantic-search/`) 10 | - **ChromaDB Backend** (`chroma/`): Vector database for semantic search using ChromaDB 11 | - **Context Fetcher Plugin** (`context-fetcher-plugin/`): Obsidian plugin for retrieving contextually relevant notes 12 | 13 | 2. **Quiz System** (`quizmaster/`) 14 | - **Quiz Web App** (`quiz-app/`): Standalone web application for interactive knowledge testing 15 | - Uses embedded quiz data directly in JavaScript (no server required) 16 | - System prompt that interactively generates quizzes based on user input and vault notes 17 | 18 | 3. **Presentation Tools** (`reverse-engineer-slidedeck/`) 19 | - Tools for reverse engineering slide deck content 20 | 21 | ## Custom Claude Code Slash Commands 22 | 23 | The repository includes multiple specialized Claude commands in respective `.claude/commands/` folders: 24 | 25 | - `generate-quiz.md`: Comprehensive quiz generation system using ChromaDB for content discovery 26 | - `reverse-engineer-slidedeck.md`: Slide deck analysis and reconstruction 27 | - `gather-relevant-context.md`: Semantic search note retrieval for Obsidian -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/ContextFetcherService.ts: -------------------------------------------------------------------------------- 1 | import { Notice, TFile, WorkspaceLeaf, MarkdownView, App } from 'obsidian'; 2 | import { ChromaDBService, ChromaDBSettings } from './ChromaDBService'; 3 | import { promises } from 'fs' 4 | export interface ContextItem { 5 | type: "reference" | "counterpoint" | "definition" | "contradiction" | "example" | "template"; 6 | note: string; 7 | anchor: string; 8 | excerpt: string; 9 | reason: string; 10 | } 11 | 12 | export interface FetchContextOptions { 13 | app: App; 14 | file: TFile; 15 | setLoading: (loading: boolean) => void; 16 | updateContext: (items: ContextItem[]) => void; 17 | } 18 | 19 | export class ContextFetcherService { 20 | chromaService: ChromaDBService; 21 | 22 | constructor(chromaSettings: ChromaDBSettings) { 23 | this.chromaService = new ChromaDBService(chromaSettings); 24 | } 25 | 26 | async fetchContext(opts: FetchContextOptions) { 27 | const { app, file, setLoading, updateContext } = opts; 28 | 29 | try { 30 | setLoading(true); 31 | const contextItems = await this.chromaService.fetchContextForNote(app, file); 32 | updateContext(contextItems); 33 | 34 | } catch (error) { 35 | console.error('ChromaDB context fetch failed:', error); 36 | new Notice(`Context fetch failed: ${error.message}`); 37 | } finally { 38 | setLoading(false); 39 | } 40 | } 41 | 42 | async readFile(path: string) { 43 | return await promises.readFile(path, 'utf8'); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /quizmaster/quiz-app/README.md: -------------------------------------------------------------------------------- 1 | # Knowledge Vault Quiz App 2 | 3 | A web-based quiz application that replicates the interactive quizmaster experience. The app features a clean, modern interface with immediate feedback and performance assessment. 4 | 5 | ## Features 6 | 7 | - **Interactive Quiz Experience**: Acts as a quizmaster with question-by-question feedback 8 | - **No Server Required**: Quiz data is embedded directly in the JavaScript - just open the HTML file! 9 | - **Responsive Design**: Works on desktop and mobile devices 10 | - **Progress Tracking**: Visual progress bar and score tracking 11 | - **Performance Assessment**: Detailed feedback based on quiz results 12 | - **Modern UI**: Clean, professional interface with smooth animations 13 | 14 | ## File Structure 15 | 16 | ``` 17 | quiz-app/ 18 | ├── index.html # Main HTML structure 19 | ├── styles.css # CSS styling 20 | ├── quiz-engine.js # JavaScript quiz engine 21 | ├── quizzes/ 22 | │ └── knowledge-vault-quiz.json # Quiz data 23 | └── README.md # This file 24 | ``` 25 | 26 | ## How to Use 27 | 28 | 1. **Start the Quiz**: Simply double-click `index.html` to open in your browser (no server required!) 29 | 2. **Select a Quiz**: Choose from available quizzes (more can be added) 30 | 3. **Answer Questions**: Click on your chosen answer and submit 31 | 4. **Get Feedback**: Receive immediate feedback with explanations 32 | 5. **View Results**: See your final score and performance assessment 33 | 34 | ## Adding New Quizzes 35 | 36 | To add a new quiz, modify the `loadQuizzes()` method in `quiz-engine.js` and add a new quiz object with this structure: 37 | 38 | ```json 39 | { 40 | "title": "Your Quiz Title", 41 | "description": "Description of your quiz", 42 | "questions": [ 43 | { 44 | "question": "Your question here?", 45 | "options": [ 46 | "Option A", 47 | "Option B", 48 | "Option C", 49 | "Option D" 50 | ], 51 | "correctAnswer": 1, 52 | "explanation": "Explanation of the correct answer" 53 | } 54 | ] 55 | } 56 | ``` 57 | 58 | - `correctAnswer`: Index of the correct option (0-based) 59 | - `explanation`: Text shown after answering to explain the correct answer 60 | 61 | ## Technical Details 62 | 63 | - **Pure JavaScript**: No external dependencies 64 | - **Responsive CSS**: Mobile-friendly design 65 | - **Modular Architecture**: Easy to extend with new features 66 | - **Embedded Data**: Quiz data is directly embedded in JavaScript for offline use 67 | 68 | ## Browser Support 69 | 70 | Works in all modern browsers that support: 71 | - ES6 classes 72 | - CSS Grid and Flexbox 73 | - No server or special setup required! 74 | 75 | ## License 76 | 77 | This quiz app is part of the knowledge vault project and follows the same licensing terms. -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/styles.css: -------------------------------------------------------------------------------- 1 | .context-header-fixed { 2 | position: sticky; 3 | top: 0; 4 | background: var(--background-primary); 5 | border-bottom: 1px solid var(--background-modifier-border); 6 | padding: 10px; 7 | z-index: 10; 8 | display: flex; 9 | justify-content: space-between; 10 | align-items: center; 11 | } 12 | 13 | .context-header-fixed h4 { 14 | margin: 0; 15 | font-size: 1.1em; 16 | } 17 | 18 | .context-refresh-button { 19 | background: var(--interactive-accent); 20 | color: var(--text-on-accent); 21 | border: none; 22 | border-radius: 4px; 23 | padding: 6px 10px; 24 | cursor: pointer; 25 | font-size: 1.2em; 26 | display: flex; 27 | align-items: center; 28 | justify-content: center; 29 | min-width: 32px; 30 | height: 32px; 31 | } 32 | 33 | .context-refresh-button:hover { 34 | background: var(--interactive-accent-hover); 35 | } 36 | 37 | .context-scrollable-content { 38 | height: calc(100% - 60px); 39 | overflow-y: auto; 40 | overflow-x: hidden; 41 | } 42 | 43 | .context-content { 44 | padding: 10px; 45 | } 46 | 47 | .context-item { 48 | margin-bottom: 15px; 49 | padding: 10px; 50 | border: 1px solid var(--background-modifier-border); 51 | border-radius: 5px; 52 | background: var(--background-primary-alt); 53 | } 54 | 55 | .context-type { 56 | margin-bottom: 5px; 57 | } 58 | 59 | .context-type span { 60 | padding: 2px 6px; 61 | border-radius: 3px; 62 | font-size: 0.8em; 63 | font-weight: bold; 64 | text-transform: uppercase; 65 | } 66 | 67 | .type-reference { 68 | background-color: var(--color-blue); 69 | color: white; 70 | } 71 | 72 | .type-counterpoint { 73 | background-color: var(--color-red); 74 | color: white; 75 | } 76 | 77 | .type-definition { 78 | background-color: var(--color-green); 79 | color: white; 80 | } 81 | 82 | .type-contradiction { 83 | background-color: var(--color-orange); 84 | color: white; 85 | } 86 | 87 | .type-example { 88 | background-color: var(--color-purple); 89 | color: white; 90 | } 91 | 92 | .type-template { 93 | background-color: var(--color-yellow); 94 | color: black; 95 | } 96 | 97 | .context-note { 98 | margin-bottom: 8px; 99 | } 100 | 101 | .context-anchor { 102 | color: var(--text-muted); 103 | font-size: 0.9em; 104 | } 105 | 106 | .context-excerpt { 107 | margin-bottom: 8px; 108 | } 109 | 110 | .context-excerpt p { 111 | margin: 0; 112 | font-style: italic; 113 | color: var(--text-muted); 114 | } 115 | 116 | .context-reason { 117 | margin-bottom: 8px; 118 | } 119 | 120 | .context-reason em { 121 | color: var(--text-normal); 122 | font-size: 0.9em; 123 | } 124 | 125 | .context-action { 126 | text-align: right; 127 | } 128 | 129 | .action-suggestion { 130 | background-color: var(--interactive-accent); 131 | color: white; 132 | padding: 2px 6px; 133 | border-radius: 3px; 134 | font-size: 0.8em; 135 | } 136 | 137 | .loading-message, .empty-message { 138 | text-align: center; 139 | color: var(--text-muted); 140 | padding: 20px; 141 | font-style: italic; 142 | } 143 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/ContextFetcherView.ts: -------------------------------------------------------------------------------- 1 | import { ItemView, WorkspaceLeaf, Notice, TFile, App } from 'obsidian'; 2 | import type { ContextItem } from './ContextFetcherService'; 3 | 4 | export const VIEW_TYPE_CONTEXT_FETCHER = "context-fetcher-view"; 5 | 6 | export class ContextFetcherView extends ItemView { 7 | private contextItems: ContextItem[] = []; 8 | private isLoading = false; 9 | private plugin: any; 10 | 11 | constructor(leaf: WorkspaceLeaf, plugin: any) { 12 | super(leaf); 13 | this.plugin = plugin; 14 | } 15 | 16 | getViewType() { return VIEW_TYPE_CONTEXT_FETCHER; } 17 | getDisplayText() { return "Semantic Context Fetcher"; } 18 | 19 | async onOpen() { 20 | const container = this.containerEl.children[1]; 21 | container.empty(); 22 | 23 | // Create fixed header 24 | const headerDiv = container.createDiv({ cls: 'context-header-fixed' }); 25 | headerDiv.createEl("h4", { text: "Semantic Context Fetcher" }); 26 | const refreshButton = headerDiv.createEl("button", { 27 | text: "↻", 28 | cls: "context-refresh-button", 29 | attr: { "aria-label": "Fetch new context" } 30 | }); 31 | refreshButton.addEventListener('click', () => { 32 | this.plugin.fetchContextForCurrentNote(); 33 | }); 34 | 35 | // Create scrollable content area 36 | const scrollableDiv = container.createDiv({ cls: 'context-scrollable-content' }); 37 | 38 | this.renderContent(); 39 | } 40 | 41 | async onClose() { } 42 | 43 | setLoading(loading: boolean) { 44 | this.isLoading = loading; 45 | this.renderContent(); 46 | } 47 | 48 | updateContext(items: ContextItem[]) { 49 | this.contextItems = items; 50 | this.renderContent(); 51 | } 52 | 53 | private renderContent() { 54 | const container = this.containerEl.children[1]; 55 | const scrollableContainer = container.querySelector('.context-scrollable-content'); 56 | if (!scrollableContainer) return; 57 | 58 | const existingContent = scrollableContainer.querySelector('.context-content'); 59 | if (existingContent) existingContent.remove(); 60 | 61 | const contentDiv = scrollableContainer.createDiv({ cls: 'context-content' }); 62 | 63 | if (this.isLoading) { 64 | contentDiv.createEl('div', { text: 'Loading context...', cls: 'loading-message' }); 65 | return; 66 | } 67 | if (this.contextItems.length === 0) { 68 | contentDiv.createEl('div', { text: 'No context items. Fetch context for a note to see relevant information here.', cls: 'empty-message' }); 69 | return; 70 | } 71 | this.contextItems.forEach((item) => { 72 | const itemDiv = contentDiv.createDiv({ cls: 'context-item' }); 73 | const noteDiv = itemDiv.createDiv({ cls: 'context-note' }); 74 | const noteLink = noteDiv.createEl('a', { text: item.note, cls: 'context-note-link', href: '#' }); 75 | noteLink.addEventListener('click', async (e) => { 76 | e.preventDefault(); 77 | try { 78 | await this.app.workspace.openLinkText( 79 | item.note, 80 | this.app.workspace.getActiveFile()?.path || "", 81 | true 82 | ); 83 | } catch (err) { 84 | new Notice(`Could not open link: ${item.note}`); 85 | } 86 | }); 87 | if (item.anchor) { 88 | noteDiv.createEl('span', { text: ` ${item.anchor}`, cls: 'context-anchor' }); 89 | } 90 | const excerptDiv = itemDiv.createDiv({ cls: 'context-excerpt' }); 91 | excerptDiv.createEl('p', { text: item.excerpt }); 92 | const reasonDiv = itemDiv.createDiv({ cls: 'context-reason' }); 93 | reasonDiv.createEl('small', { text: item.reason, cls: 'distance-info' }); 94 | }); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /quizmaster/quiz-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Knowledge Vault Quiz 7 | 8 | 9 | 10 |
11 |
12 |

Knowledge Vault Quiz

13 |
14 | Score: 0/10 15 | Question 1 of 10 16 |
17 |
18 | 19 |
20 | 21 |
22 |

Welcome to your interactive knowledge vault quiz!

23 |

I'll be testing your understanding of concepts from software craftsmanship, cognitive science, systems thinking, and more.

24 |
25 | 26 | 29 |
30 | 31 |
32 | 33 | 34 | 43 | 44 | 45 | 56 | 57 | 58 | 76 |
77 | 78 |
79 |
80 |
81 |
82 |
83 |
84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/chroma_query.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | ChromaDB Query Script for Obsidian Context Fetcher Plugin 4 | 5 | This script accepts JSON input via stdin and returns JSON output via stdout. 6 | It connects to ChromaDB and performs queries based on the input parameters. 7 | 8 | Input JSON format: 9 | { 10 | "action": "query", 11 | "host": "localhost", 12 | "port": 8000, 13 | "collection_name": "notes", 14 | "query_text": "search text", 15 | "n_results": 5 16 | } 17 | 18 | Output JSON format: 19 | { 20 | "success": true, 21 | "results": [ 22 | { 23 | "id": "doc_id", 24 | "document": "document content", 25 | "metadata": {...}, 26 | "distance": 0.5 27 | } 28 | ] 29 | } 30 | 31 | Or on error: 32 | { 33 | "success": false, 34 | "error": "error message" 35 | } 36 | """ 37 | 38 | import sys 39 | import json 40 | import chromadb 41 | from typing import Dict, Any, List 42 | import io 43 | 44 | # Ensure both stdin and stdout use UTF-8 encoding to handle Unicode characters properly 45 | if sys.platform == 'win32': 46 | sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') 47 | sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8') 48 | 49 | 50 | def connect_to_chroma(host: str, port: int) -> chromadb.HttpClient: 51 | """Connect to ChromaDB server.""" 52 | try: 53 | client = chromadb.HttpClient(host=host, port=port) 54 | client.heartbeat() # Test connection 55 | return client 56 | except Exception as e: 57 | raise Exception(f"Failed to connect to ChromaDB at {host}:{port}: {e}") 58 | 59 | 60 | def query_collection(client: chromadb.HttpClient, collection_name: str, query_text: str, n_results: int) -> List[Dict[str, Any]]: 61 | """Query the ChromaDB collection.""" 62 | try: 63 | collection = client.get_collection(name=collection_name) 64 | 65 | results = collection.query( 66 | query_texts=[query_text], 67 | n_results=n_results, 68 | include=["documents", "metadatas", "distances"] 69 | ) 70 | 71 | # Transform results into a more convenient format 72 | formatted_results = [] 73 | if results['ids'] and len(results['ids']) > 0: 74 | for i in range(len(results['ids'][0])): 75 | formatted_results.append({ 76 | "id": results['ids'][0][i], 77 | "document": results['documents'][0][i] if results['documents'] else "", 78 | "metadata": results['metadatas'][0][i] if results['metadatas'] else {}, 79 | "distance": results['distances'][0][i] if results['distances'] else 0.0 80 | }) 81 | 82 | return formatted_results 83 | 84 | except Exception as e: 85 | raise Exception(f"Query failed: {e}") 86 | 87 | 88 | def main(): 89 | """Main function that handles stdin/stdout communication.""" 90 | try: 91 | # Read input from stdin 92 | input_data = sys.stdin.read().strip() 93 | if not input_data: 94 | raise Exception("No input provided") 95 | 96 | # Parse JSON input 97 | try: 98 | request = json.loads(input_data) 99 | except json.JSONDecodeError as e: 100 | raise Exception(f"Invalid JSON input: {e}") 101 | 102 | # Validate required fields 103 | required_fields = ["action", "host", "port", "collection_name", "query_text", "n_results"] 104 | for field in required_fields: 105 | if field not in request: 106 | raise Exception(f"Missing required field: {field}") 107 | 108 | if request["action"] != "query": 109 | raise Exception(f"Unsupported action: {request['action']}") 110 | 111 | # Connect to ChromaDB 112 | client = connect_to_chroma(request["host"], request["port"]) 113 | 114 | # Perform query 115 | results = query_collection( 116 | client, 117 | request["collection_name"], 118 | request["query_text"], 119 | request["n_results"] 120 | ) 121 | 122 | # Return success response 123 | response = { 124 | "success": True, 125 | "results": results 126 | } 127 | 128 | except Exception as e: 129 | # Return error response 130 | response = { 131 | "success": False, 132 | "error": str(e) 133 | } 134 | 135 | # Output JSON response to stdout 136 | print(json.dumps(response, ensure_ascii=False)) 137 | 138 | 139 | if __name__ == "__main__": 140 | main() -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Obsidian Sample Plugin 2 | 3 | This is a sample plugin for Obsidian (https://obsidian.md). 4 | 5 | This project uses TypeScript to provide type checking and documentation. 6 | The repo depends on the latest plugin API (obsidian.d.ts) in TypeScript Definition format, which contains TSDoc comments describing what it does. 7 | 8 | This sample plugin demonstrates some of the basic functionality the plugin API can do. 9 | - Adds a ribbon icon, which shows a Notice when clicked. 10 | - Adds a command "Open Sample Modal" which opens a Modal. 11 | - Adds a plugin setting tab to the settings page. 12 | - Registers a global click event and output 'click' to the console. 13 | - Registers a global interval which logs 'setInterval' to the console. 14 | 15 | ## First time developing plugins? 16 | 17 | Quick starting guide for new plugin devs: 18 | 19 | - Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with. 20 | - Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it). 21 | - Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder. 22 | - Install NodeJS, then run `npm i` in the command line under your repo folder. 23 | - Run `npm run dev` to compile your plugin from `main.ts` to `main.js`. 24 | - Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`. 25 | - Reload Obsidian to load the new version of your plugin. 26 | - Enable plugin in settings window. 27 | - For updates to the Obsidian API run `npm update` in the command line under your repo folder. 28 | 29 | ## Releasing new releases 30 | 31 | - Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release. 32 | - Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible. 33 | - Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases 34 | - Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release. 35 | - Publish the release. 36 | 37 | > You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`. 38 | > The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json` 39 | 40 | ## Adding your plugin to the community plugin list 41 | 42 | - Check the [plugin guidelines](https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines). 43 | - Publish an initial version. 44 | - Make sure you have a `README.md` file in the root of your repo. 45 | - Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin. 46 | 47 | ## How to use 48 | 49 | - Clone this repo. 50 | - Make sure your NodeJS is at least v16 (`node --version`). 51 | - `npm i` or `yarn` to install dependencies. 52 | - `npm run dev` to start compilation in watch mode. 53 | 54 | ## Manually installing the plugin 55 | 56 | - Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`. 57 | 58 | ## Improve code quality with eslint (optional) 59 | - [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code. 60 | - To use eslint with this project, make sure to install eslint from terminal: 61 | - `npm install -g eslint` 62 | - To use eslint to analyze this project use this command: 63 | - `eslint main.ts` 64 | - eslint will then create a report with suggestions for code improvement by file and line number. 65 | - If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder: 66 | - `eslint .\src\` 67 | 68 | ## Funding URL 69 | 70 | You can include funding URLs where people who use your plugin can financially support it. 71 | 72 | The simple way is to set the `fundingUrl` field to your link in your `manifest.json` file: 73 | 74 | ```json 75 | { 76 | "fundingUrl": "https://buymeacoffee.com" 77 | } 78 | ``` 79 | 80 | If you have multiple URLs, you can also do: 81 | 82 | ```json 83 | { 84 | "fundingUrl": { 85 | "Buy Me a Coffee": "https://buymeacoffee.com", 86 | "GitHub Sponsor": "https://github.com/sponsors", 87 | "Patreon": "https://www.patreon.com/" 88 | } 89 | } 90 | ``` 91 | 92 | ## API Documentation 93 | 94 | See https://github.com/obsidianmd/obsidian-api 95 | -------------------------------------------------------------------------------- /reverse-engineer-slidedeck/.claude/commands/reverse-engineer-slidedeck.md: -------------------------------------------------------------------------------- 1 | # Reverse Engineer Slide Deck 2 | 3 | Convert a folder of PNG slide images into a comprehensive text document following Jo Van Eyck's writing style. 4 | 5 | ## Command Parameters 6 | 7 | **Slide Folder**: {{slide_folder}} (required - absolute path to folder containing PNG slide images) 8 | 9 | **Output Document**: {{output_document}} (required - path to output document in vault, e.g., "projects/my-presentation.md") 10 | 11 | ## Instructions 12 | 13 | ### 1. Slide Discovery and Validation 14 | - List all PNG files in the specified folder 15 | - Sort slides numerically (Slide1.PNG, Slide2.PNG, etc.) to ensure proper order 16 | - Validate that slides exist and are readable 17 | - Report total number of slides found 18 | 19 | ### 2. Systematic Slide Processing 20 | **CRITICAL**: Process EVERY slide individually and systematically in **batches of 10 slides**: 21 | - Read each slide image one by one in numerical order 22 | - Extract all text content, concepts, code examples, and visual information 23 | - Identify slide type (title, section header, content, code example, diagram, etc.) 24 | - Note any visual elements that provide context (charts, diagrams, images) 25 | - **MANDATORY**: If a slide contains no parsable text or meaningful content, add the marker: `` where X is the slide number 26 | - **BATCH PROCESSING**: Process slides in batches of 10, writing accumulated content to output file after each batch to prevent context loss and enable resumption if interrupted 27 | 28 | ### 3. Content Analysis and Structure 29 | For each slide, analyze: 30 | - **Main topic or concept** being presented 31 | - **Key points** or bullet items 32 | - **Code examples** with proper syntax highlighting 33 | - **Quotes** or references to experts/sources 34 | - **Visual information** (diagrams, charts, images) and their meaning 35 | - **Progression** from previous slides and connection to next slides 36 | 37 | ### 4. Text Generation Following Specific Writing Style 38 | Read and utilize the style found in writing-style.md. 39 | 40 | ### 5. Document Structure 41 | Create a comprehensive document with: 42 | - **Title and metadata** (based on first slide or inferred from content) 43 | - **Table of contents** or overview section 44 | - **Major sections** corresponding to slide groups/topics 45 | - **Subsections** for detailed concepts 46 | - **Code examples** properly formatted 47 | - **Conclusion** synthesizing key takeaways 48 | - **References** to sources mentioned in slides 49 | 50 | ### 6. Error Handling and Quality Assurance 51 | - **Mandatory markers** for unparsable slides: `` 52 | - **Verification** that all slides are accounted for in final text 53 | - **Cross-references** between related concepts across slides 54 | - **Consistency checks** for terminology and style 55 | - **Completeness validation** ensuring no slide content is missed 56 | 57 | ### 7. Output Generation 58 | - Write content to the specified output path **after each batch of 10 slides** 59 | - Ensure proper markdown formatting 60 | - Include metadata about source slides and processing date 61 | - Verify the document is readable and well-structured 62 | - **INCREMENTAL WRITING**: Append each batch's content to the output file to prevent data loss and enable resumption 63 | 64 | ## Example Usage 65 | 66 | ``` 67 | /reverse-engineer-slidedeck slide_folder:c:/tmp/slides output_document:projects/reverse-engineered-text.md 68 | ``` 69 | 70 | ## Important Notes 71 | 72 | - **Completeness is critical**: Every slide must be processed or marked as unparsable 73 | - **Preserve slide order**: Maintain the logical flow from slide progression 74 | - **Extract ALL content**: Don't summarize - capture the full richness of each slide 75 | - **Use Jo's style**: Conversational, practical, with concrete examples and linked concepts 76 | - **Handle errors gracefully**: Mark unparsable slides clearly for manual review 77 | - **Verify totals**: Ensure slide count matches between source and processed content 78 | 79 | ## Processing Workflow 80 | 81 | 1. **Discover slides**: List and count all PNG files 82 | 2. **Process in batches**: Read slides 1-10, 11-20, 21-30, etc. in batches of 10 83 | 3. **Extract content**: Pull text, code, concepts, and visual information for each batch 84 | 4. **Transform style**: Convert to Jo's writing style with proper structure 85 | 5. **Link concepts**: Add [[concept]] links for interconnected ideas 86 | 6. **Mark errors**: Add markers for unparsable slides 87 | 7. **Write batch output**: Append each batch's content to output file immediately 88 | 8. **Resume capability**: If interrupted, can resume from next batch 89 | 9. **Validate completeness**: Verify all slides are accounted for in final document 90 | 91 | ## Success Criteria 92 | 93 | - All slides processed (either converted to text or marked as unparsable) 94 | - Content flows logically following slide progression 95 | - Defined writing style consistently applied 96 | - Proper markdown formatting with headings, code blocks, and links 97 | - Complete document written to specified output path 98 | - Any processing errors clearly marked for manual review 99 | 100 | The goal is to create a comprehensive, well-structured document that captures the full content and learning journey of the original slide deck while making it accessible as flowing prose in the provided distinctive writing style. -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/main.ts: -------------------------------------------------------------------------------- 1 | import { App, FileSystemAdapter, MarkdownView, Notice, Plugin, PluginSettingTab, Setting, WorkspaceLeaf } from 'obsidian'; 2 | import { ContextFetcherService, ContextItem } from './ContextFetcherService'; 3 | import { ContextFetcherView, VIEW_TYPE_CONTEXT_FETCHER } from './ContextFetcherView'; 4 | import { ChromaDBSettings } from './ChromaDBService'; 5 | 6 | interface ContextFetcherPluginSettings { 7 | chromaHost: string; 8 | chromaPort: number; 9 | chromaCollectionName: string; 10 | pythonPath: string; 11 | } 12 | 13 | const DEFAULT_SETTINGS: ContextFetcherPluginSettings = { 14 | chromaHost: 'localhost', 15 | chromaPort: 8000, 16 | chromaCollectionName: 'notes', 17 | pythonPath: 'C:\\Users\\Jo.VanEyck\\AppData\\Local\\Programs\\Python\\Python312\\python.exe', 18 | }; 19 | 20 | export default class ContextFetcherPlugin extends Plugin { 21 | settings: ContextFetcherPluginSettings; 22 | service: ContextFetcherService; 23 | contextView: ContextFetcherView | null = null; 24 | 25 | async onload() { 26 | await this.loadSettings(); 27 | const vaultPath = (this.app.vault.adapter as FileSystemAdapter).getBasePath(); 28 | const pluginDir = require('path').join(vaultPath, '.obsidian', 'plugins', 'context-fetcher-plugin'); 29 | const chromaSettings: ChromaDBSettings = { 30 | host: this.settings.chromaHost, 31 | port: this.settings.chromaPort, 32 | collectionName: this.settings.chromaCollectionName, 33 | pythonPath: this.settings.pythonPath, 34 | pluginDir: pluginDir 35 | }; 36 | this.service = new ContextFetcherService(chromaSettings); 37 | 38 | this.registerView( 39 | VIEW_TYPE_CONTEXT_FETCHER, 40 | (leaf) => { 41 | const view = new ContextFetcherView(leaf, this); 42 | this.contextView = view; 43 | return view; 44 | } 45 | ); 46 | 47 | this.addRibbonIcon('brain-circuit', 'Semantic Context Fetcher', () => { 48 | this.activateView(); 49 | }); 50 | 51 | this.addCommand({ 52 | id: 'fetch-context', 53 | name: 'Fetch Context for Current Note', 54 | callback: () => { 55 | this.fetchContextForCurrentNote(); 56 | } 57 | }); 58 | 59 | this.addSettingTab(new SettingTab(this.app, this)); 60 | } 61 | 62 | async activateView() { 63 | const { workspace } = this.app; 64 | let leaf: WorkspaceLeaf | null = null; 65 | const leaves = workspace.getLeavesOfType(VIEW_TYPE_CONTEXT_FETCHER); 66 | if (leaves.length > 0) { 67 | leaf = leaves[0]; 68 | } else { 69 | leaf = workspace.getRightLeaf(false); 70 | if (!leaf) { 71 | new Notice('Could not open context fetcher view: no available leaf'); 72 | return; 73 | } 74 | await leaf.setViewState({ type: VIEW_TYPE_CONTEXT_FETCHER, active: true }); 75 | } 76 | workspace.revealLeaf(leaf); 77 | } 78 | 79 | async fetchContextForCurrentNote() { 80 | let activeView = this.app.workspace.getActiveViewOfType(MarkdownView); 81 | if (!activeView) { 82 | const allLeaves = this.app.workspace.getLeavesOfType('markdown'); 83 | if (allLeaves.length > 0) { 84 | activeView = allLeaves[0].view as MarkdownView; 85 | } 86 | } 87 | if (!activeView) { 88 | new Notice('No markdown view available'); 89 | return; 90 | } 91 | const file = activeView.file; 92 | if (!file) { 93 | new Notice('No file in active view'); 94 | return; 95 | } 96 | const contextView = this.app.workspace.getLeavesOfType(VIEW_TYPE_CONTEXT_FETCHER)[0]?.view as ContextFetcherView; 97 | const setLoading = (loading: boolean) => contextView && contextView.setLoading(loading); 98 | const updateContext = (items: ContextItem[]) => contextView && contextView.updateContext(items); 99 | 100 | if (contextView) contextView.setLoading(true); 101 | const vaultPath = (this.app.vault.adapter as FileSystemAdapter).getBasePath(); 102 | const pluginDir = require('path').join(vaultPath, '.obsidian', 'plugins', 'context-fetcher-plugin'); 103 | const chromaSettings: ChromaDBSettings = { 104 | host: this.settings.chromaHost, 105 | port: this.settings.chromaPort, 106 | collectionName: this.settings.chromaCollectionName, 107 | pythonPath: this.settings.pythonPath, 108 | pluginDir: pluginDir 109 | }; 110 | await this.service.fetchContext({ 111 | app: this.app, 112 | file, 113 | setLoading, 114 | updateContext 115 | }); 116 | } 117 | 118 | onunload() { 119 | this.app.workspace.detachLeavesOfType(VIEW_TYPE_CONTEXT_FETCHER); 120 | } 121 | 122 | async loadSettings(): Promise { 123 | this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); 124 | return this.settings; 125 | } 126 | 127 | async saveSettings() { 128 | await this.saveData(this.settings); 129 | } 130 | } 131 | 132 | class SettingTab extends PluginSettingTab { 133 | plugin: ContextFetcherPlugin; 134 | constructor(app: App, plugin: ContextFetcherPlugin) { 135 | super(app, plugin); 136 | this.plugin = plugin; 137 | } 138 | display(): void { 139 | const { containerEl } = this; 140 | containerEl.empty(); 141 | 142 | containerEl.createEl('h2', { text: 'Context Fetcher Settings' }); 143 | 144 | new Setting(containerEl) 145 | .setName('ChromaDB Host') 146 | .setDesc('ChromaDB server host address') 147 | .addText(text => text 148 | .setPlaceholder('localhost') 149 | .setValue(this.plugin.settings.chromaHost) 150 | .onChange(async (value) => { 151 | this.plugin.settings.chromaHost = value; 152 | await this.plugin.saveSettings(); 153 | })); 154 | 155 | new Setting(containerEl) 156 | .setName('ChromaDB Port') 157 | .setDesc('ChromaDB server port') 158 | .addText(text => text 159 | .setPlaceholder('8000') 160 | .setValue(this.plugin.settings.chromaPort.toString()) 161 | .onChange(async (value) => { 162 | const port = parseInt(value); 163 | if (!isNaN(port)) { 164 | this.plugin.settings.chromaPort = port; 165 | await this.plugin.saveSettings(); 166 | } 167 | })); 168 | 169 | new Setting(containerEl) 170 | .setName('Collection Name') 171 | .setDesc('ChromaDB collection name for your notes') 172 | .addText(text => text 173 | .setPlaceholder('notes') 174 | .setValue(this.plugin.settings.chromaCollectionName) 175 | .onChange(async (value) => { 176 | this.plugin.settings.chromaCollectionName = value; 177 | await this.plugin.saveSettings(); 178 | })); 179 | 180 | new Setting(containerEl) 181 | .setName('Python Path') 182 | .setDesc('Path to Python executable') 183 | .addText(text => text 184 | .setPlaceholder('C:\\Users\\Jo.VanEyck\\AppData\\Local\\Programs\\Python\\Python312\\python.exe') 185 | .setValue(this.plugin.settings.pythonPath) 186 | .onChange(async (value) => { 187 | this.plugin.settings.pythonPath = value; 188 | await this.plugin.saveSettings(); 189 | })); 190 | 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /quizmaster/.claude/commands/generate-quiz.md: -------------------------------------------------------------------------------- 1 | # Generate Knowledge Vault Quiz 2 | 3 | You are going to create and run an interactive quiz based on the contents of this knowledge vault using ChromaDB. 4 | 5 | ## Quiz Parameters 6 | 7 | **Number of Questions**: {{num_questions}} (default: 10 if not specified) 8 | 9 | **Topic Focus**: {{topic}} (if specified, focus all questions on this specific topic; if not specified, make the quiz as broad and diverse as possible across all vault content) 10 | 11 | ## Instructions 12 | 13 | 1. **Topic Discovery Using ChromaDB**: 14 | - Use ChromaDB MCP tools to access the "notes" collection 15 | - If a specific topic is provided: 16 | - Use `mcp__chroma__chroma_query_documents` to search for documents semantically related to the topic 17 | - Limit to 10-15 most relevant documents for focused quiz content 18 | - If no topic is specified: 19 | - First, get the total document count using `mcp__chroma__chroma_get_collection_count` 20 | - Generate random offset values dynamically using Python or command-line tools 21 | - Use `mcp__chroma__chroma_get_documents` with these random offsets to get diverse content 22 | - Aim for 15-20 diverse documents across different domains 23 | 24 | 2. **Document Retrieval and Content Analysis**: 25 | - After identifying relevant documents from ChromaDB, use the Read tool to access the actual markdown files 26 | - Extract file paths from the ChromaDB metadata and read only those specific files 27 | - Analyze content for key concepts, frameworks, and interconnected ideas 28 | - Focus on understanding, not just facts 29 | 30 | 3. **Question Generation**: 31 | - If a specific topic is provided, generate ALL questions about that topic only 32 | - If no topic is specified, create the most diverse quiz possible - pull from different domains (software craftsmanship, cognitive science, systems thinking, AI, leadership, coaching, etc.) 33 | - Use only content from this knowledge vault - don't inject external knowledge 34 | - Create multiple choice questions with 4 options each 35 | - Ensure questions test understanding, not just memorization. You can do this by providing out-of-order listings, paraphrasing etc. 36 | - **CRITICAL**: When creating multiple choice options, ensure that each option is meaningfully different and tests real understanding. Avoid creating options that are merely reordered lists of the same elements. 37 | 38 | 4. **Quiz Execution**: 39 | - Act as an interactive quizmaster 40 | - Present questions one at a time 41 | - Wait for user response after each question 42 | - Provide immediate feedback (correct/incorrect) 43 | - If incorrect, briefly explain the mistake and the correct answer 44 | - Track score throughout 45 | 46 | 5. **Quiz Completion**: 47 | - Show final score at the end 48 | - Provide constructive, positive feedback 49 | - Give an experience level assessment based on performance 50 | - **CRITICAL**: Provide context-specific next steps based on the quiz topic and user's performance: 51 | - For software craftsmanship topics: suggest specific practices, books, or techniques to try 52 | - For cognitive science topics: recommend specific exercises or areas to explore 53 | - For systems thinking topics: suggest frameworks or real-world applications 54 | - For coaching topics: recommend specific coaching techniques or situations to practice 55 | - Always make suggestions actionable and specific to the quiz content 56 | 57 | ## Example Usage 58 | 59 | ``` 60 | /generate-quiz num_questions:5 topic:Conway's Law 61 | ``` 62 | (Creates 5 questions focused only on Conway's Law using semantic search) 63 | 64 | ``` 65 | /generate-quiz num_questions:15 66 | ``` 67 | (Creates 15 diverse questions across all vault topics using random sampling) 68 | 69 | ``` 70 | /generate-quiz 71 | ``` 72 | (Creates 10 diverse questions across all vault topics using random sampling) 73 | 74 | ## Important Notes 75 | 76 | - Questions should reflect the interconnected nature of concepts in the vault 77 | - Use the same positive, constructive tone as established in previous interactions 78 | - Ensure questions are challenging but fair 79 | - Draw from notes, literature notes, and project content 80 | - Reference specific files when explaining answers if relevant 81 | - **Efficiency**: Use ChromaDB to efficiently discover relevant content without reading all files 82 | 83 | ## Random Offset Generation Strategy 84 | 85 | For diverse content sampling, use this approach to generate smart random offsets: 86 | 87 | 1. **Calculate Safe Maximum**: `max_offset = total_documents - limit` (where limit is your per-query limit, e.g., 5) 88 | 2. **Generate Multiple Offsets**: Create 6-8 different random offsets to sample across the collection 89 | 3. **Ensure Distribution**: Aim for offsets that span the full range (early, middle, and late documents) 90 | 4. **Example Calculation**: 91 | - If collection has 267 documents and using limit=3 92 | - max_offset = 267 - 3 = 264 93 | - Generate offsets like: 12, 67, 145, 198, 234, 89 94 | 95 | **Command Examples**: 96 | ```bash 97 | # Python method (most reliable) 98 | python -c "import random; offsets=[random.randint(0, 264) for _ in range(6)]; print(offsets)" 99 | 100 | # PowerShell method (Windows) 101 | $offsets = 1..6 | ForEach-Object { Get-Random -Maximum 264 }; Write-Output $offsets 102 | ``` 103 | 104 | ## Quiz Mode Selection 105 | 106 | After generating the quiz content, ALWAYS ask the user to choose between: 107 | 108 | **A) Interactive Quiz Mode**: Run the quiz directly in the conversation (traditional Claude quizmaster experience) 109 | **B) Add to Web App**: Add the quiz to the quiz web app in `scripts/quiz-app/quiz-engine.js` 110 | 111 | Wait for the user's selection before proceeding with either option. 112 | 113 | ## Implementation Steps 114 | 115 | 1. Check ChromaDB collection info and document count using `mcp__chroma__chroma_get_collection_info` and `mcp__chroma__chroma_get_collection_count` 116 | 2. If topic specified: 117 | - Use `mcp__chroma__chroma_query_documents` with the topic as query text 118 | - Limit results to 10-15 most semantically similar documents 119 | 3. If no topic specified: 120 | - Generate random offset values using one of these methods: 121 | - Python: `python -c "import random; print(' '.join(str(random.randint(0, {max_offset})) for _ in range(6)))"` 122 | - Where {max_offset} = total_documents - 5 (to ensure we don't exceed bounds with limit) 123 | - Use `mcp__chroma__chroma_get_documents` with these random offsets to sample diverse content 124 | - Use small limits (3-5 docs each) to ensure we stay within collection bounds 125 | 4. Extract file paths from ChromaDB metadata and use Read tool to access actual content 126 | 5. Generate quiz questions with context-specific performance feedback for different score ranges 127 | 6. **MANDATORY**: Present the quiz mode selection to the user and wait for their choice 128 | 7. Based on user selection: 129 | - Option A: Run the interactive quiz as quizmaster with context-specific conclusions 130 | - Option B: Add the quiz to the web app including performance feedback data structure 131 | 132 | Begin generating quiz content now, but remember to ask about quiz mode before execution. -------------------------------------------------------------------------------- /quizmaster/quiz-app/styles.css: -------------------------------------------------------------------------------- 1 | /* Reset and base styles */ 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | } 7 | 8 | body { 9 | font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 10 | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 11 | min-height: 100vh; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | padding: 20px; 16 | } 17 | 18 | .quiz-container { 19 | background: white; 20 | border-radius: 15px; 21 | box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); 22 | max-width: 800px; 23 | width: 100%; 24 | min-height: 500px; 25 | position: relative; 26 | overflow: hidden; 27 | } 28 | 29 | /* Header */ 30 | .quiz-header { 31 | background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%); 32 | color: white; 33 | padding: 30px; 34 | text-align: center; 35 | } 36 | 37 | .quiz-header h1 { 38 | font-size: 2.5em; 39 | margin-bottom: 15px; 40 | font-weight: 300; 41 | } 42 | 43 | .score-container { 44 | display: flex; 45 | justify-content: space-between; 46 | align-items: center; 47 | font-size: 1.1em; 48 | opacity: 0.9; 49 | } 50 | 51 | /* Content */ 52 | .quiz-content { 53 | padding: 40px; 54 | min-height: 400px; 55 | } 56 | 57 | .screen { 58 | display: block; 59 | } 60 | 61 | .screen.hidden { 62 | display: none; 63 | } 64 | 65 | /* Welcome Screen */ 66 | #welcome-screen { 67 | text-align: center; 68 | } 69 | 70 | #welcome-screen h2 { 71 | color: #4f46e5; 72 | margin-bottom: 20px; 73 | font-size: 1.8em; 74 | } 75 | 76 | #welcome-screen p { 77 | color: #666; 78 | font-size: 1.1em; 79 | margin-bottom: 30px; 80 | line-height: 1.6; 81 | } 82 | 83 | .quiz-selection { 84 | margin-bottom: 30px; 85 | } 86 | 87 | .quiz-selection label { 88 | display: block; 89 | margin-bottom: 10px; 90 | font-weight: 600; 91 | color: #4f46e5; 92 | } 93 | 94 | .quiz-selection select { 95 | padding: 10px 15px; 96 | border: 2px solid #e5e7eb; 97 | border-radius: 8px; 98 | font-size: 1em; 99 | background: white; 100 | min-width: 200px; 101 | } 102 | 103 | /* Question Screen */ 104 | .question-container { 105 | max-width: 600px; 106 | margin: 0 auto; 107 | } 108 | 109 | #question-text { 110 | color: #333; 111 | font-size: 1.3em; 112 | margin-bottom: 30px; 113 | line-height: 1.6; 114 | } 115 | 116 | .options-container { 117 | margin-bottom: 30px; 118 | } 119 | 120 | .option { 121 | display: block; 122 | width: 100%; 123 | padding: 15px 20px; 124 | margin-bottom: 10px; 125 | background: #f8fafc; 126 | border: 2px solid #e5e7eb; 127 | border-radius: 8px; 128 | font-size: 1em; 129 | cursor: pointer; 130 | transition: all 0.3s ease; 131 | text-align: left; 132 | } 133 | 134 | .option:hover { 135 | background: #e0f2fe; 136 | border-color: #0284c7; 137 | } 138 | 139 | .option.selected { 140 | background: #dbeafe; 141 | border-color: #3b82f6; 142 | color: #1e40af; 143 | } 144 | 145 | /* Feedback Screen */ 146 | .feedback-container { 147 | text-align: center; 148 | max-width: 600px; 149 | margin: 0 auto; 150 | } 151 | 152 | .feedback-icon { 153 | font-size: 4em; 154 | margin-bottom: 20px; 155 | } 156 | 157 | .feedback-icon.correct::before { 158 | content: "✓"; 159 | color: #10b981; 160 | } 161 | 162 | .feedback-icon.incorrect::before { 163 | content: "✗"; 164 | color: #ef4444; 165 | } 166 | 167 | #feedback-title { 168 | font-size: 1.5em; 169 | margin-bottom: 20px; 170 | } 171 | 172 | #feedback-title.correct { 173 | color: #10b981; 174 | } 175 | 176 | #feedback-title.incorrect { 177 | color: #ef4444; 178 | } 179 | 180 | #feedback-explanation { 181 | color: #666; 182 | font-size: 1.1em; 183 | line-height: 1.6; 184 | margin-bottom: 30px; 185 | } 186 | 187 | .feedback-actions { 188 | display: flex; 189 | gap: 15px; 190 | justify-content: center; 191 | } 192 | 193 | /* Results Screen */ 194 | .results-container { 195 | text-align: center; 196 | max-width: 600px; 197 | margin: 0 auto; 198 | } 199 | 200 | .results-container h2 { 201 | color: #4f46e5; 202 | font-size: 2em; 203 | margin-bottom: 30px; 204 | } 205 | 206 | .final-score { 207 | background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%); 208 | padding: 30px; 209 | border-radius: 15px; 210 | margin-bottom: 30px; 211 | } 212 | 213 | .final-score h3 { 214 | font-size: 1.8em; 215 | color: #0369a1; 216 | margin-bottom: 10px; 217 | } 218 | 219 | .score-percentage { 220 | font-size: 3em; 221 | font-weight: bold; 222 | color: #0284c7; 223 | } 224 | 225 | .performance-feedback { 226 | background: #f9fafb; 227 | padding: 20px; 228 | border-radius: 10px; 229 | margin-bottom: 30px; 230 | } 231 | 232 | .performance-feedback h4 { 233 | color: #374151; 234 | margin-bottom: 10px; 235 | } 236 | 237 | .performance-feedback p { 238 | color: #6b7280; 239 | line-height: 1.6; 240 | } 241 | 242 | .results-actions { 243 | display: flex; 244 | gap: 15px; 245 | justify-content: center; 246 | } 247 | 248 | /* Buttons */ 249 | .btn { 250 | padding: 12px 30px; 251 | border: none; 252 | border-radius: 8px; 253 | font-size: 1em; 254 | font-weight: 600; 255 | cursor: pointer; 256 | transition: all 0.3s ease; 257 | text-decoration: none; 258 | display: inline-block; 259 | } 260 | 261 | .btn-primary { 262 | background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%); 263 | color: white; 264 | } 265 | 266 | .btn-primary:hover { 267 | transform: translateY(-2px); 268 | box-shadow: 0 10px 20px rgba(79, 70, 229, 0.3); 269 | } 270 | 271 | .btn-primary:disabled { 272 | background: #9ca3af; 273 | cursor: not-allowed; 274 | transform: none; 275 | box-shadow: none; 276 | } 277 | 278 | .btn-secondary { 279 | background: #6b7280; 280 | color: white; 281 | } 282 | 283 | .btn-secondary:hover { 284 | background: #4b5563; 285 | transform: translateY(-2px); 286 | } 287 | 288 | /* Progress Bar */ 289 | .progress-bar-container { 290 | position: absolute; 291 | bottom: 0; 292 | left: 0; 293 | right: 0; 294 | height: 6px; 295 | background: #e5e7eb; 296 | } 297 | 298 | .progress-bar { 299 | height: 100%; 300 | width: 100%; 301 | background: #e5e7eb; 302 | position: relative; 303 | } 304 | 305 | .progress-fill { 306 | height: 100%; 307 | background: linear-gradient(90deg, #10b981 0%, #059669 100%); 308 | width: 0%; 309 | transition: width 0.5s ease; 310 | } 311 | 312 | /* Responsive Design */ 313 | @media (max-width: 768px) { 314 | .quiz-container { 315 | margin: 10px; 316 | border-radius: 10px; 317 | } 318 | 319 | .quiz-header { 320 | padding: 20px; 321 | } 322 | 323 | .quiz-header h1 { 324 | font-size: 2em; 325 | } 326 | 327 | .score-container { 328 | flex-direction: column; 329 | gap: 10px; 330 | } 331 | 332 | .quiz-content { 333 | padding: 20px; 334 | } 335 | 336 | .feedback-actions, 337 | .results-actions { 338 | flex-direction: column; 339 | align-items: center; 340 | } 341 | 342 | .btn { 343 | width: 100%; 344 | max-width: 300px; 345 | } 346 | } 347 | 348 | /* Utility Classes */ 349 | .hidden { 350 | display: none !important; 351 | } 352 | 353 | .text-center { 354 | text-align: center; 355 | } 356 | 357 | .mb-20 { 358 | margin-bottom: 20px; 359 | } 360 | 361 | .mt-20 { 362 | margin-top: 20px; 363 | } -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/ChromaDBService.ts: -------------------------------------------------------------------------------- 1 | import { Notice, TFile, App } from 'obsidian'; 2 | import { ContextItem } from './ContextFetcherService'; 3 | import { spawn, ChildProcess } from 'child_process'; 4 | 5 | export interface ChromaDBSettings { 6 | host: string; 7 | port: number; 8 | collectionName: string; 9 | pythonPath: string; 10 | pluginDir?: string; 11 | } 12 | 13 | export class ChromaDBService { 14 | private settings: ChromaDBSettings; 15 | 16 | constructor(settings: ChromaDBSettings) { 17 | this.settings = settings; 18 | } 19 | 20 | async initialize(): Promise { 21 | // No initialization needed for subprocess approach 22 | } 23 | 24 | private async runPythonQuery(queryText: string, maxResults: number): Promise { 25 | return new Promise((resolve, reject) => { 26 | // Ensure query text is a clean string 27 | const cleanQueryText = typeof queryText === 'string' ? queryText.trim() : String(queryText).trim(); 28 | if (!cleanQueryText) { 29 | reject(new Error('Query text cannot be empty')); 30 | return; 31 | } 32 | 33 | const request = { 34 | action: "query", 35 | host: this.settings.host, 36 | port: this.settings.port, 37 | collection_name: this.settings.collectionName, 38 | query_text: cleanQueryText, 39 | n_results: maxResults 40 | }; 41 | 42 | const scriptPath = this.settings.pluginDir 43 | ? require('path').join(this.settings.pluginDir, 'chroma_query.py') 44 | : require('path').join(__dirname, 'chroma_query.py'); 45 | 46 | console.log('ChromaDBService: Request payload:'); 47 | console.dir(request) 48 | 49 | const python = spawn(this.settings.pythonPath, [scriptPath], { 50 | stdio: ['pipe', 'pipe', 'pipe'], 51 | windowsHide: true 52 | }); 53 | 54 | let stdout = ''; 55 | let stderr = ''; 56 | 57 | python.stdout.on('data', (data) => { 58 | const chunk = data.toString('utf8'); 59 | stdout += chunk; 60 | }); 61 | 62 | python.stderr.on('data', (data) => { 63 | const chunk = data.toString('utf8'); 64 | console.log('ChromaDBService: Python stderr chunk:', chunk); 65 | stderr += chunk; 66 | }); 67 | 68 | python.on('close', (code) => { 69 | console.log('ChromaDBService: Final stdout:'); 70 | console.dir(JSON.parse(stdout)); 71 | if (stderr) { 72 | console.log('ChromaDBService: Final stderr:', stderr); 73 | } 74 | 75 | if (code !== 0) { 76 | reject(new Error(`Python process exited with code ${code}: ${stderr}`)); 77 | return; 78 | } 79 | 80 | try { 81 | const response = JSON.parse(stdout); 82 | if (!response.success) { 83 | reject(new Error(response.error)); 84 | return; 85 | } 86 | resolve(response.results); 87 | } catch (error) { 88 | reject(new Error(`Failed to parse Python response: ${error}`)); 89 | } 90 | }); 91 | 92 | python.on('error', (error) => { 93 | const fs = require('fs'); 94 | const path = require('path'); 95 | 96 | let errorMessage = `Failed to spawn Python process: ${error}`; 97 | const pythonScriptPath = this.settings.pluginDir 98 | ? path.join(this.settings.pluginDir, 'chroma_query.py') 99 | : path.join(__dirname, 'chroma_query.py'); 100 | 101 | // Add diagnostic information 102 | errorMessage += `\nPython path: ${this.settings.pythonPath}`; 103 | errorMessage += `\nScript path: ${pythonScriptPath}`; 104 | errorMessage += `\nCurrent directory: ${__dirname}`; 105 | errorMessage += `\nPython exists: ${fs.existsSync(this.settings.pythonPath)}`; 106 | errorMessage += `\nScript exists: ${fs.existsSync(pythonScriptPath)}`; 107 | 108 | if (error.message.includes('ENOENT')) { 109 | errorMessage += `\nENOENT means "file not found" - check paths above.`; 110 | } 111 | reject(new Error(errorMessage)); 112 | }); 113 | 114 | // Send the request to stdin with explicit UTF-8 encoding 115 | const requestJson = JSON.stringify(request, null, 0); 116 | python.stdin.setDefaultEncoding('utf8'); 117 | python.stdin.write(requestJson, 'utf8'); 118 | python.stdin.end(); 119 | }); 120 | } 121 | 122 | async searchSimilarContent(queryText: string, maxResults: number = 8): Promise { 123 | try { 124 | const results = await this.runPythonQuery(queryText, maxResults); 125 | 126 | // Convert the Python response format to match the original ChromaDB format 127 | const formattedResults = { 128 | documents: [results.map((r: any) => r.document)], 129 | metadatas: [results.map((r: any) => r.metadata)], 130 | distances: [results.map((r: any) => r.distance)], 131 | ids: [results.map((r: any) => r.id)] 132 | }; 133 | 134 | return formattedResults; 135 | } catch (error) { 136 | console.error('ChromaDB query failed:', error); 137 | throw error; 138 | } 139 | } 140 | 141 | processChromaResults(results: any, currentNotePath: string): ContextItem[] { 142 | if (!results.documents || !results.documents[0] || results.documents[0].length === 0) { 143 | return []; 144 | } 145 | 146 | const contextItems: ContextItem[] = []; 147 | const documents = results.documents[0]; 148 | const metadatas = results.metadatas?.[0] || []; 149 | const distances = results.distances?.[0] || []; 150 | 151 | for (let i = 0; i < documents.length; i++) { 152 | const document = documents[i]; 153 | const metadata = metadatas[i] || {}; 154 | const distance = distances[i] || 1; 155 | 156 | const notePath = metadata.relative_path; 157 | 158 | // Normalize paths for comparison (handle different separators and formats) 159 | const normalizeNotePath = (path: string) => path?.replace(/\\/g, '/').toLowerCase(); 160 | const normalizedCurrentPath = normalizeNotePath(currentNotePath); 161 | const normalizedNotePath = normalizeNotePath(notePath); 162 | 163 | if (normalizedNotePath === normalizedCurrentPath) { 164 | continue; 165 | } 166 | 167 | const noteTitle = metadata.filename?.replace('.md', '') || 'Unknown'; 168 | const excerpt = document.substring(0, 240); 169 | 170 | const anchor = metadata.heading ? `#${metadata.heading}` : ''; 171 | const reason = `Distance: ${distance.toFixed(2)}`; 172 | 173 | contextItems.push({ 174 | type: 'reference', 175 | note: noteTitle, 176 | anchor, 177 | excerpt, 178 | reason 179 | }); 180 | } 181 | 182 | return contextItems; 183 | } 184 | 185 | async fetchContextForNote(app: App, file: TFile): Promise { 186 | try { 187 | const content = await app.vault.read(file); 188 | // Ensure proper string encoding and normalize line endings 189 | const cleanContent = content.toString().replace(/\r\n/g, '\n').replace(/\r/g, '\n'); 190 | 191 | // Prepend note title to query text 192 | const noteTitle = file.basename; // This strips .md automatically 193 | const queryText = `${noteTitle}\n\n${cleanContent}`; 194 | 195 | const results = await this.searchSimilarContent(queryText, 12); 196 | const contextItems = this.processChromaResults(results, file.path); 197 | 198 | return contextItems; 199 | } catch (error) { 200 | console.error('Error fetching context:', error); 201 | new Notice(`Error fetching context: ${error.message}`); 202 | return []; 203 | } 204 | } 205 | } -------------------------------------------------------------------------------- /semantic-search/chroma/reindex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Reindex script for Chroma collection. 4 | Processes all markdown files in notes/ and projects/ directories and uploads them to Chroma in batches. 5 | 6 | HOW TO RUN: 7 | ----------- 8 | 9 | Prerequisites: 10 | - ChromaDB server running on localhost:8000 (docker run -d -v ./chroma-data:/data -p 8000:8000 chromadb/chroma) 11 | - Python 3.6+ installed 12 | - chromadb package installed (pip install chromadb) 13 | 14 | Usage: 15 | 1. Start ChromaDB server: 16 | docker run -d -v ./chroma-data:/data -p 8000:8000 chromadb/chroma 17 | 18 | 2. Navigate to the vault root directory: 19 | cd C:\\Users\\Jo.VanEyck\\stack\\personal\\knowledge\\vault\\jovaneyck 20 | 21 | 3. Run the script: 22 | python scripts\\chroma\\reindex.py 23 | 24 | Or from the scripts/chroma directory: 25 | cd scripts\\chroma 26 | python reindex.py 27 | 28 | What it does: 29 | - Finds all .md files in notes/ and projects/ directories 30 | - Filters out empty files, TODO-only files, and files with encoding issues 31 | - Processes files in batches of 50 documents 32 | - Upserts documents into the "notes" Chroma collection (creates if not exists) 33 | - Uses ChromaDB's native upsert functionality for efficient updates 34 | - Provides detailed progress and success statistics 35 | 36 | Output: 37 | - Progress messages during processing 38 | - Detailed final report with statistics 39 | """ 40 | 41 | import os 42 | import json 43 | from pathlib import Path 44 | from typing import List, Dict, Tuple 45 | import chromadb 46 | import sys 47 | 48 | # Configuration 49 | BATCH_SIZE = 50 # Increased batch size for direct API calls 50 | COLLECTION_NAME = "notes" 51 | VAULT_ROOT = Path(__file__).parent.parent.parent 52 | CHROMA_HOST = "localhost" 53 | CHROMA_PORT = 8000 54 | 55 | def connect_to_chroma(): 56 | """Connect to ChromaDB server.""" 57 | try: 58 | client = chromadb.HttpClient(host=CHROMA_HOST, port=CHROMA_PORT) 59 | # Test connection 60 | client.heartbeat() 61 | print(f"Connected to ChromaDB at {CHROMA_HOST}:{CHROMA_PORT}") 62 | return client 63 | except Exception as e: 64 | print(f"Failed to connect to ChromaDB: {e}") 65 | print(f"Make sure ChromaDB server is running:") 66 | print(f" docker run -d -v ./chroma-data:/data -p {CHROMA_PORT}:{CHROMA_PORT} chromadb/chroma") 67 | return None 68 | 69 | def find_markdown_files() -> List[Path]: 70 | """Find all markdown files in notes/ and projects/ directories.""" 71 | directories = ["notes", "projects"] 72 | 73 | files = [] 74 | for directory in directories: 75 | dir_path = VAULT_ROOT / directory 76 | if dir_path.exists(): 77 | files.extend(dir_path.glob("**/*.md")) 78 | 79 | print(f"Found {len(files)} markdown files") 80 | return files 81 | 82 | def read_file_content(file_path: Path) -> Tuple[str, str]: 83 | """ 84 | Read file content and return (content, status). 85 | Status can be: 'success', 'empty', 'todo_only', 'encoding_error' 86 | """ 87 | try: 88 | with open(file_path, 'r', encoding='utf-8') as f: 89 | content = f.read().strip() 90 | 91 | if not content: 92 | return "", "empty" 93 | elif content == "#TODO": 94 | return content, "todo_only" 95 | else: 96 | return content, "success" 97 | 98 | except UnicodeDecodeError: 99 | try: 100 | # Try with different encoding 101 | with open(file_path, 'r', encoding='latin-1') as f: 102 | content = f.read().strip() 103 | return content, "success" 104 | except Exception as e: 105 | print(f"Encoding error reading {file_path}: {e}") 106 | return "", "encoding_error" 107 | except Exception as e: 108 | print(f"Error reading {file_path}: {e}") 109 | return "", "encoding_error" 110 | 111 | def generate_document_id(file_path: Path) -> str: 112 | """Generate a document ID from the file path.""" 113 | # Use the relative path from vault root as ID, replacing separators 114 | relative_path = file_path.relative_to(VAULT_ROOT) 115 | doc_id = str(relative_path).replace('\\', '/').replace('.md', '') 116 | return doc_id 117 | 118 | def process_files_into_batches(files: List[Path]) -> Tuple[List[Dict], Dict]: 119 | """ 120 | Process files and create batch data. 121 | Returns (batches, stats) 122 | """ 123 | batches = [] 124 | current_batch = {"documents": [], "ids": [], "metadatas": []} 125 | stats = { 126 | "total_files": len(files), 127 | "processed": 0, 128 | "empty": 0, 129 | "todo_only": 0, 130 | "encoding_error": 0, 131 | "success": 0, 132 | "batches_created": 0 133 | } 134 | 135 | for file_path in files: 136 | content, status = read_file_content(file_path) 137 | stats[status] += 1 138 | 139 | if status == "success": 140 | doc_id = generate_document_id(file_path) 141 | metadata = { 142 | "file_path": str(file_path), 143 | "relative_path": str(file_path.relative_to(VAULT_ROOT)), 144 | "folder": file_path.parent.name, 145 | "filename": file_path.name 146 | } 147 | 148 | current_batch["documents"].append(content) 149 | current_batch["ids"].append(doc_id) 150 | current_batch["metadatas"].append(metadata) 151 | stats["processed"] += 1 152 | 153 | # Check if batch is full 154 | if len(current_batch["documents"]) >= BATCH_SIZE: 155 | batches.append(current_batch.copy()) 156 | current_batch = {"documents": [], "ids": [], "metadatas": []} 157 | stats["batches_created"] += 1 158 | 159 | # Add remaining documents as final batch 160 | if current_batch["documents"]: 161 | batches.append(current_batch) 162 | stats["batches_created"] += 1 163 | 164 | return batches, stats 165 | 166 | def get_or_create_collection(client): 167 | """Get or create the Chroma collection.""" 168 | try: 169 | collection = client.get_or_create_collection(name=COLLECTION_NAME) 170 | print(f"Collection '{COLLECTION_NAME}' ready") 171 | return collection 172 | except Exception as e: 173 | print(f"Error creating/accessing collection: {e}") 174 | return None 175 | 176 | def upsert_batch_to_chroma(collection, batch: Dict) -> bool: 177 | """Upsert a single batch directly to Chroma.""" 178 | try: 179 | collection.upsert( 180 | ids=batch["ids"], 181 | documents=batch["documents"], 182 | metadatas=batch["metadatas"] 183 | ) 184 | print(f"[OK] Successfully upserted batch with {len(batch['documents'])} documents") 185 | return True 186 | except Exception as e: 187 | print(f"[ERROR] Error upserting batch: {e}") 188 | return False 189 | 190 | def upload_all_batches(collection, batches: List[Dict]) -> Dict: 191 | """Upload all batches directly to Chroma.""" 192 | upload_stats = { 193 | "total_batches": len(batches), 194 | "successful_uploads": 0, 195 | "failed_uploads": 0, 196 | "total_documents": 0 197 | } 198 | 199 | for i, batch in enumerate(batches, 1): 200 | print(f"Processing batch {i}/{len(batches)} ({len(batch['documents'])} documents)...") 201 | if upsert_batch_to_chroma(collection, batch): 202 | upload_stats["successful_uploads"] += 1 203 | upload_stats["total_documents"] += len(batch['documents']) 204 | else: 205 | upload_stats["failed_uploads"] += 1 206 | 207 | return upload_stats 208 | 209 | def print_final_report(processing_stats: Dict, upload_stats: Dict): 210 | """Print final processing and upload report.""" 211 | print("\n" + "="*60) 212 | print("REINDEXING COMPLETE") 213 | print("="*60) 214 | 215 | print("\nFile Processing Statistics:") 216 | print(f" Total files found: {processing_stats['total_files']}") 217 | print(f" Successfully processed: {processing_stats['processed']}") 218 | print(f" Empty files: {processing_stats['empty']}") 219 | print(f" TODO-only files: {processing_stats['todo_only']}") 220 | print(f" Encoding errors: {processing_stats['encoding_error']}") 221 | print(f" Batches created: {processing_stats['batches_created']}") 222 | 223 | print("\nUpload Statistics:") 224 | print(f" Total batches: {upload_stats['total_batches']}") 225 | print(f" Successful uploads: {upload_stats['successful_uploads']}") 226 | print(f" Failed uploads: {upload_stats['failed_uploads']}") 227 | print(f" Total documents uploaded: {upload_stats['total_documents']}") 228 | 229 | success_rate = (processing_stats['processed'] / processing_stats['total_files']) * 100 230 | upload_rate = (upload_stats['successful_uploads'] / upload_stats['total_batches']) * 100 if upload_stats['total_batches'] > 0 else 0 231 | 232 | print(f"\nSuccess Rates:") 233 | print(f" File processing: {success_rate:.1f}%") 234 | print(f" Batch upload: {upload_rate:.1f}%") 235 | 236 | if upload_stats['failed_uploads'] > 0: 237 | print(f"\n[WARNING] {upload_stats['failed_uploads']} batches failed to upload.") 238 | else: 239 | print(f"\n[SUCCESS] All {upload_stats['total_documents']} documents successfully upserted in Chroma collection '{COLLECTION_NAME}'") 240 | 241 | def main(): 242 | """Main execution function.""" 243 | print("Starting Chroma reindexing process...") 244 | print(f"Vault root: {VAULT_ROOT}") 245 | 246 | # Connect to ChromaDB 247 | client = connect_to_chroma() 248 | if not client: 249 | return 250 | 251 | # Get or create collection 252 | collection = get_or_create_collection(client) 253 | if not collection: 254 | return 255 | 256 | # Find and process files 257 | markdown_files = find_markdown_files() 258 | if not markdown_files: 259 | print("No markdown files found!") 260 | return 261 | 262 | # Process files into batches 263 | print("Processing files into batches...") 264 | batches, processing_stats = process_files_into_batches(markdown_files) 265 | 266 | if not batches: 267 | print("No valid documents to process!") 268 | return 269 | 270 | print(f"Created {len(batches)} batches from {processing_stats['processed']} valid documents") 271 | 272 | # Upload all batches directly to Chroma 273 | print("Upserting batches to Chroma...") 274 | upload_stats = upload_all_batches(collection, batches) 275 | 276 | # Final report 277 | print_final_report(processing_stats, upload_stats) 278 | 279 | if __name__ == "__main__": 280 | main() -------------------------------------------------------------------------------- /quizmaster/quiz-app/quiz-engine.js: -------------------------------------------------------------------------------- 1 | class QuizEngine { 2 | constructor() { 3 | this.currentQuiz = null; 4 | this.currentQuestionIndex = 0; 5 | this.score = 0; 6 | this.selectedAnswer = null; 7 | this.quizzes = {}; 8 | 9 | this.initializeElements(); 10 | this.bindEvents(); 11 | this.loadQuizzes(); 12 | } 13 | 14 | initializeElements() { 15 | // Screens 16 | this.welcomeScreen = document.getElementById('welcome-screen'); 17 | this.questionScreen = document.getElementById('question-screen'); 18 | this.feedbackScreen = document.getElementById('feedback-screen'); 19 | this.resultsScreen = document.getElementById('results-screen'); 20 | 21 | // Elements 22 | this.quizSelect = document.getElementById('quiz-select'); 23 | this.startQuizBtn = document.getElementById('start-quiz'); 24 | this.submitAnswerBtn = document.getElementById('submit-answer'); 25 | this.nextQuestionBtn = document.getElementById('next-question'); 26 | this.finishQuizBtn = document.getElementById('finish-quiz'); 27 | this.restartQuizBtn = document.getElementById('restart-quiz'); 28 | this.selectNewQuizBtn = document.getElementById('select-new-quiz'); 29 | 30 | // Content elements 31 | this.questionText = document.getElementById('question-text'); 32 | this.optionsContainer = document.getElementById('options-container'); 33 | this.currentScoreEl = document.getElementById('current-score'); 34 | this.totalQuestionsEl = document.getElementById('total-questions'); 35 | this.questionNumberEl = document.getElementById('question-number'); 36 | this.totalQuestionsCounterEl = document.getElementById('total-questions-counter'); 37 | this.progressFill = document.getElementById('progress-fill'); 38 | 39 | // Feedback elements 40 | this.feedbackIcon = document.getElementById('feedback-icon'); 41 | this.feedbackTitle = document.getElementById('feedback-title'); 42 | this.feedbackExplanation = document.getElementById('feedback-explanation'); 43 | 44 | // Results elements 45 | this.finalScoreEl = document.getElementById('final-score'); 46 | this.finalTotalEl = document.getElementById('final-total'); 47 | this.scorePercentageEl = document.getElementById('score-percentage'); 48 | this.performanceFeedbackEl = document.getElementById('performance-feedback'); 49 | } 50 | 51 | bindEvents() { 52 | this.startQuizBtn.addEventListener('click', () => this.startQuiz()); 53 | this.submitAnswerBtn.addEventListener('click', () => this.submitAnswer()); 54 | this.nextQuestionBtn.addEventListener('click', () => this.nextQuestion()); 55 | this.finishQuizBtn.addEventListener('click', () => this.showResults()); 56 | this.restartQuizBtn.addEventListener('click', () => this.restartQuiz()); 57 | this.selectNewQuizBtn.addEventListener('click', () => this.showWelcome()); 58 | } 59 | 60 | loadQuizzes() { 61 | // Embedded quiz data - no need for fetch 62 | const knowledgeVaultQuiz = { 63 | "title": "Knowledge Vault Quiz", 64 | "description": "A comprehensive quiz covering software craftsmanship, cognitive science, systems thinking, and more from the knowledge vault", 65 | "questions": [ 66 | { 67 | "question": "According to Conway's Law, what is the relationship between organizational structure and system design?", 68 | "options": [ 69 | "Organizations should design systems independently of their communication structures", 70 | "Organizations are constrained to produce designs that copy their communication structures", 71 | "System architecture should determine organizational structure", 72 | "There is no relationship between organizational structure and system design" 73 | ], 74 | "correctAnswer": 1, 75 | "explanation": "Conway's Law states that 'organizations which design systems are constrained to produce designs which are copies of the communication structures of the organizations.' This is why strong software architects need to be socio-technical system architects with both technical and social skills." 76 | } 77 | ], 78 | "performanceFeedback": { 79 | "expert": { 80 | "level": "Knowledge Vault Master", 81 | "feedback": "Exceptional! You have a deep understanding of software craftsmanship, cognitive science, and systems thinking concepts.", 82 | "suggestions": "Consider applying these concepts in your daily work: implement TDD practices, use Conway's Law for team design, and leverage cognitive biases awareness in decision-making. You're ready to mentor others in these areas." 83 | }, 84 | "proficient": { 85 | "level": "Well-Versed Practitioner", 86 | "feedback": "Strong performance! You grasp the core concepts across multiple domains.", 87 | "suggestions": "Focus on deepening your understanding of the topics you missed. Practice applying the 4 Rules of Simple Design in your code, experiment with zettelkasten note-taking, and explore flow state techniques for improved productivity." 88 | }, 89 | "developing": { 90 | "level": "Growing Learner", 91 | "feedback": "Good foundation! You're building knowledge across important areas.", 92 | "suggestions": "Strengthen your understanding by: reading 'Thinking, Fast and Slow' for cognitive biases, practicing deliberate practice techniques, and exploring the linked notes in the vault for deeper context on topics you found challenging." 93 | }, 94 | "beginner": { 95 | "level": "Knowledge Explorer", 96 | "feedback": "Great start! You've been introduced to some powerful concepts.", 97 | "suggestions": "Begin with the fundamentals: start a simple zettelkasten system, practice basic TDD with one small project, and read the specific vault notes on topics you found most interesting. Take the quiz again after exploring these areas." 98 | } 99 | } 100 | }; 101 | 102 | 103 | this.quizzes['default'] = knowledgeVaultQuiz; 104 | 105 | // Populate quiz selector 106 | this.populateQuizSelector(); 107 | } 108 | 109 | populateQuizSelector() { 110 | this.quizSelect.innerHTML = ''; 111 | Object.keys(this.quizzes).forEach(quizId => { 112 | const option = document.createElement('option'); 113 | option.value = quizId; 114 | option.textContent = this.quizzes[quizId].title; 115 | this.quizSelect.appendChild(option); 116 | }); 117 | } 118 | 119 | startQuiz() { 120 | const selectedQuizId = this.quizSelect.value; 121 | this.currentQuiz = this.quizzes[selectedQuizId]; 122 | 123 | if (!this.currentQuiz) { 124 | this.showError('Quiz not found. Please select a valid quiz.'); 125 | return; 126 | } 127 | 128 | this.currentQuestionIndex = 0; 129 | this.score = 0; 130 | this.selectedAnswer = null; 131 | 132 | this.updateScoreDisplay(); 133 | this.updateProgressBar(); 134 | this.showQuestion(); 135 | } 136 | 137 | showQuestion() { 138 | this.showScreen('question'); 139 | 140 | const question = this.currentQuiz.questions[this.currentQuestionIndex]; 141 | this.questionText.textContent = question.question; 142 | 143 | // Update counters 144 | this.questionNumberEl.textContent = this.currentQuestionIndex + 1; 145 | this.totalQuestionsCounterEl.textContent = this.currentQuiz.questions.length; 146 | 147 | // Clear previous options 148 | this.optionsContainer.innerHTML = ''; 149 | 150 | // Create option buttons 151 | question.options.forEach((option, index) => { 152 | const button = document.createElement('button'); 153 | button.className = 'option'; 154 | button.textContent = `${String.fromCharCode(65 + index)}) ${option}`; 155 | button.addEventListener('click', () => this.selectOption(index, button)); 156 | this.optionsContainer.appendChild(button); 157 | }); 158 | 159 | this.submitAnswerBtn.disabled = true; 160 | this.selectedAnswer = null; 161 | } 162 | 163 | selectOption(index, buttonElement) { 164 | // Remove previous selection 165 | document.querySelectorAll('.option').forEach(btn => btn.classList.remove('selected')); 166 | 167 | // Select current option 168 | buttonElement.classList.add('selected'); 169 | this.selectedAnswer = index; 170 | this.submitAnswerBtn.disabled = false; 171 | } 172 | 173 | submitAnswer() { 174 | if (this.selectedAnswer === null) return; 175 | 176 | const question = this.currentQuiz.questions[this.currentQuestionIndex]; 177 | const isCorrect = this.selectedAnswer === question.correctAnswer; 178 | 179 | if (isCorrect) { 180 | this.score++; 181 | this.updateScoreDisplay(); 182 | } 183 | 184 | this.showFeedback(isCorrect, question); 185 | } 186 | 187 | showFeedback(isCorrect, question) { 188 | this.showScreen('feedback'); 189 | 190 | // Update feedback icon and title 191 | this.feedbackIcon.className = `feedback-icon ${isCorrect ? 'correct' : 'incorrect'}`; 192 | this.feedbackTitle.textContent = isCorrect ? 'Correct!' : 'Incorrect.'; 193 | this.feedbackTitle.className = isCorrect ? 'correct' : 'incorrect'; 194 | 195 | // Show explanation 196 | this.feedbackExplanation.textContent = question.explanation; 197 | 198 | // Show appropriate button 199 | const isLastQuestion = this.currentQuestionIndex === this.currentQuiz.questions.length - 1; 200 | this.nextQuestionBtn.classList.toggle('hidden', isLastQuestion); 201 | this.finishQuizBtn.classList.toggle('hidden', !isLastQuestion); 202 | } 203 | 204 | nextQuestion() { 205 | this.currentQuestionIndex++; 206 | this.updateProgressBar(); 207 | this.showQuestion(); 208 | } 209 | 210 | showResults() { 211 | this.showScreen('results'); 212 | 213 | const totalQuestions = this.currentQuiz.questions.length; 214 | const percentage = Math.round((this.score / totalQuestions) * 100); 215 | 216 | this.finalScoreEl.textContent = this.score; 217 | this.finalTotalEl.textContent = totalQuestions; 218 | this.scorePercentageEl.textContent = percentage; 219 | 220 | // Generate performance feedback 221 | this.generatePerformanceFeedback(percentage, totalQuestions); 222 | } 223 | 224 | generatePerformanceFeedback(percentage, totalQuestions) { 225 | // Use quiz-specific performance feedback if available, otherwise fall back to generic 226 | const performanceFeedback = this.currentQuiz.performanceFeedback || this.getGenericPerformanceFeedback(); 227 | 228 | let level, feedback, suggestions; 229 | 230 | if (percentage >= 90) { 231 | level = performanceFeedback.expert.level; 232 | feedback = performanceFeedback.expert.feedback; 233 | suggestions = performanceFeedback.expert.suggestions; 234 | } else if (percentage >= 70) { 235 | level = performanceFeedback.proficient.level; 236 | feedback = performanceFeedback.proficient.feedback; 237 | suggestions = performanceFeedback.proficient.suggestions; 238 | } else if (percentage >= 50) { 239 | level = performanceFeedback.developing.level; 240 | feedback = performanceFeedback.developing.feedback; 241 | suggestions = performanceFeedback.developing.suggestions; 242 | } else { 243 | level = performanceFeedback.beginner.level; 244 | feedback = performanceFeedback.beginner.feedback; 245 | suggestions = performanceFeedback.beginner.suggestions; 246 | } 247 | 248 | this.performanceFeedbackEl.innerHTML = ` 249 |

${level}

250 |

${feedback}

251 |

Next steps: ${suggestions}

252 | `; 253 | } 254 | 255 | getGenericPerformanceFeedback() { 256 | return { 257 | expert: { 258 | level: "Expert Level", 259 | feedback: "Outstanding! You have an excellent grasp of the concepts in this knowledge vault.", 260 | suggestions: "Consider teaching these concepts to others or diving deeper into related advanced topics." 261 | }, 262 | proficient: { 263 | level: "Proficient", 264 | feedback: "Great work! You have a solid understanding of most concepts.", 265 | suggestions: "Review the questions you missed and explore the related topics to strengthen your knowledge." 266 | }, 267 | developing: { 268 | level: "Developing", 269 | feedback: "Good effort! You're on the right track but there's room for improvement.", 270 | suggestions: "Focus on the areas where you struggled and spend more time with the source material." 271 | }, 272 | beginner: { 273 | level: "Beginner", 274 | feedback: "Don't worry, everyone starts somewhere! This quiz identified areas for growth.", 275 | suggestions: "Consider reviewing the foundational concepts and taking the quiz again after studying." 276 | } 277 | }; 278 | } 279 | 280 | restartQuiz() { 281 | this.startQuiz(); 282 | } 283 | 284 | showWelcome() { 285 | this.showScreen('welcome'); 286 | this.resetProgress(); 287 | } 288 | 289 | showScreen(screenName) { 290 | // Hide all screens 291 | document.querySelectorAll('.screen').forEach(screen => { 292 | screen.classList.add('hidden'); 293 | }); 294 | 295 | // Show selected screen 296 | document.getElementById(`${screenName}-screen`).classList.remove('hidden'); 297 | } 298 | 299 | updateScoreDisplay() { 300 | this.currentScoreEl.textContent = this.score; 301 | this.totalQuestionsEl.textContent = this.currentQuiz.questions.length; 302 | } 303 | 304 | updateProgressBar() { 305 | const totalQuestions = this.currentQuiz.questions.length; 306 | const progress = ((this.currentQuestionIndex + 1) / totalQuestions) * 100; 307 | this.progressFill.style.width = `${progress}%`; 308 | } 309 | 310 | resetProgress() { 311 | this.progressFill.style.width = '0%'; 312 | this.currentQuestionIndex = 0; 313 | this.score = 0; 314 | this.selectedAnswer = null; 315 | } 316 | 317 | showError(message) { 318 | alert(message); // Simple error handling - could be enhanced with a proper modal 319 | } 320 | } 321 | 322 | // Initialize the quiz engine when the page loads 323 | document.addEventListener('DOMContentLoaded', () => { 324 | new QuizEngine(); 325 | }); -------------------------------------------------------------------------------- /semantic-search/context-fetcher-plugin/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "obsidian-sample-plugin", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "obsidian-sample-plugin", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@types/node": "^16.11.6", 13 | "@typescript-eslint/eslint-plugin": "5.29.0", 14 | "@typescript-eslint/parser": "5.29.0", 15 | "builtin-modules": "3.3.0", 16 | "esbuild": "0.17.3", 17 | "obsidian": "latest", 18 | "tslib": "2.4.0", 19 | "typescript": "4.7.4" 20 | } 21 | }, 22 | "node_modules/@codemirror/state": { 23 | "version": "6.5.2", 24 | "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", 25 | "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", 26 | "dev": true, 27 | "license": "MIT", 28 | "peer": true, 29 | "dependencies": { 30 | "@marijn/find-cluster-break": "^1.0.0" 31 | } 32 | }, 33 | "node_modules/@codemirror/view": { 34 | "version": "6.38.1", 35 | "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.1.tgz", 36 | "integrity": "sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ==", 37 | "dev": true, 38 | "license": "MIT", 39 | "peer": true, 40 | "dependencies": { 41 | "@codemirror/state": "^6.5.0", 42 | "crelt": "^1.0.6", 43 | "style-mod": "^4.1.0", 44 | "w3c-keyname": "^2.2.4" 45 | } 46 | }, 47 | "node_modules/@esbuild/android-arm": { 48 | "version": "0.17.3", 49 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.3.tgz", 50 | "integrity": "sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg==", 51 | "cpu": [ 52 | "arm" 53 | ], 54 | "dev": true, 55 | "license": "MIT", 56 | "optional": true, 57 | "os": [ 58 | "android" 59 | ], 60 | "engines": { 61 | "node": ">=12" 62 | } 63 | }, 64 | "node_modules/@esbuild/android-arm64": { 65 | "version": "0.17.3", 66 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz", 67 | "integrity": "sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ==", 68 | "cpu": [ 69 | "arm64" 70 | ], 71 | "dev": true, 72 | "license": "MIT", 73 | "optional": true, 74 | "os": [ 75 | "android" 76 | ], 77 | "engines": { 78 | "node": ">=12" 79 | } 80 | }, 81 | "node_modules/@esbuild/android-x64": { 82 | "version": "0.17.3", 83 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.3.tgz", 84 | "integrity": "sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A==", 85 | "cpu": [ 86 | "x64" 87 | ], 88 | "dev": true, 89 | "license": "MIT", 90 | "optional": true, 91 | "os": [ 92 | "android" 93 | ], 94 | "engines": { 95 | "node": ">=12" 96 | } 97 | }, 98 | "node_modules/@esbuild/darwin-arm64": { 99 | "version": "0.17.3", 100 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz", 101 | "integrity": "sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw==", 102 | "cpu": [ 103 | "arm64" 104 | ], 105 | "dev": true, 106 | "license": "MIT", 107 | "optional": true, 108 | "os": [ 109 | "darwin" 110 | ], 111 | "engines": { 112 | "node": ">=12" 113 | } 114 | }, 115 | "node_modules/@esbuild/darwin-x64": { 116 | "version": "0.17.3", 117 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz", 118 | "integrity": "sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA==", 119 | "cpu": [ 120 | "x64" 121 | ], 122 | "dev": true, 123 | "license": "MIT", 124 | "optional": true, 125 | "os": [ 126 | "darwin" 127 | ], 128 | "engines": { 129 | "node": ">=12" 130 | } 131 | }, 132 | "node_modules/@esbuild/freebsd-arm64": { 133 | "version": "0.17.3", 134 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz", 135 | "integrity": "sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w==", 136 | "cpu": [ 137 | "arm64" 138 | ], 139 | "dev": true, 140 | "license": "MIT", 141 | "optional": true, 142 | "os": [ 143 | "freebsd" 144 | ], 145 | "engines": { 146 | "node": ">=12" 147 | } 148 | }, 149 | "node_modules/@esbuild/freebsd-x64": { 150 | "version": "0.17.3", 151 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz", 152 | "integrity": "sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg==", 153 | "cpu": [ 154 | "x64" 155 | ], 156 | "dev": true, 157 | "license": "MIT", 158 | "optional": true, 159 | "os": [ 160 | "freebsd" 161 | ], 162 | "engines": { 163 | "node": ">=12" 164 | } 165 | }, 166 | "node_modules/@esbuild/linux-arm": { 167 | "version": "0.17.3", 168 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz", 169 | "integrity": "sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ==", 170 | "cpu": [ 171 | "arm" 172 | ], 173 | "dev": true, 174 | "license": "MIT", 175 | "optional": true, 176 | "os": [ 177 | "linux" 178 | ], 179 | "engines": { 180 | "node": ">=12" 181 | } 182 | }, 183 | "node_modules/@esbuild/linux-arm64": { 184 | "version": "0.17.3", 185 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz", 186 | "integrity": "sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g==", 187 | "cpu": [ 188 | "arm64" 189 | ], 190 | "dev": true, 191 | "license": "MIT", 192 | "optional": true, 193 | "os": [ 194 | "linux" 195 | ], 196 | "engines": { 197 | "node": ">=12" 198 | } 199 | }, 200 | "node_modules/@esbuild/linux-ia32": { 201 | "version": "0.17.3", 202 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz", 203 | "integrity": "sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA==", 204 | "cpu": [ 205 | "ia32" 206 | ], 207 | "dev": true, 208 | "license": "MIT", 209 | "optional": true, 210 | "os": [ 211 | "linux" 212 | ], 213 | "engines": { 214 | "node": ">=12" 215 | } 216 | }, 217 | "node_modules/@esbuild/linux-loong64": { 218 | "version": "0.17.3", 219 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz", 220 | "integrity": "sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA==", 221 | "cpu": [ 222 | "loong64" 223 | ], 224 | "dev": true, 225 | "license": "MIT", 226 | "optional": true, 227 | "os": [ 228 | "linux" 229 | ], 230 | "engines": { 231 | "node": ">=12" 232 | } 233 | }, 234 | "node_modules/@esbuild/linux-mips64el": { 235 | "version": "0.17.3", 236 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz", 237 | "integrity": "sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ==", 238 | "cpu": [ 239 | "mips64el" 240 | ], 241 | "dev": true, 242 | "license": "MIT", 243 | "optional": true, 244 | "os": [ 245 | "linux" 246 | ], 247 | "engines": { 248 | "node": ">=12" 249 | } 250 | }, 251 | "node_modules/@esbuild/linux-ppc64": { 252 | "version": "0.17.3", 253 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz", 254 | "integrity": "sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ==", 255 | "cpu": [ 256 | "ppc64" 257 | ], 258 | "dev": true, 259 | "license": "MIT", 260 | "optional": true, 261 | "os": [ 262 | "linux" 263 | ], 264 | "engines": { 265 | "node": ">=12" 266 | } 267 | }, 268 | "node_modules/@esbuild/linux-riscv64": { 269 | "version": "0.17.3", 270 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz", 271 | "integrity": "sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow==", 272 | "cpu": [ 273 | "riscv64" 274 | ], 275 | "dev": true, 276 | "license": "MIT", 277 | "optional": true, 278 | "os": [ 279 | "linux" 280 | ], 281 | "engines": { 282 | "node": ">=12" 283 | } 284 | }, 285 | "node_modules/@esbuild/linux-s390x": { 286 | "version": "0.17.3", 287 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz", 288 | "integrity": "sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug==", 289 | "cpu": [ 290 | "s390x" 291 | ], 292 | "dev": true, 293 | "license": "MIT", 294 | "optional": true, 295 | "os": [ 296 | "linux" 297 | ], 298 | "engines": { 299 | "node": ">=12" 300 | } 301 | }, 302 | "node_modules/@esbuild/linux-x64": { 303 | "version": "0.17.3", 304 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz", 305 | "integrity": "sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg==", 306 | "cpu": [ 307 | "x64" 308 | ], 309 | "dev": true, 310 | "license": "MIT", 311 | "optional": true, 312 | "os": [ 313 | "linux" 314 | ], 315 | "engines": { 316 | "node": ">=12" 317 | } 318 | }, 319 | "node_modules/@esbuild/netbsd-x64": { 320 | "version": "0.17.3", 321 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz", 322 | "integrity": "sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg==", 323 | "cpu": [ 324 | "x64" 325 | ], 326 | "dev": true, 327 | "license": "MIT", 328 | "optional": true, 329 | "os": [ 330 | "netbsd" 331 | ], 332 | "engines": { 333 | "node": ">=12" 334 | } 335 | }, 336 | "node_modules/@esbuild/openbsd-x64": { 337 | "version": "0.17.3", 338 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz", 339 | "integrity": "sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA==", 340 | "cpu": [ 341 | "x64" 342 | ], 343 | "dev": true, 344 | "license": "MIT", 345 | "optional": true, 346 | "os": [ 347 | "openbsd" 348 | ], 349 | "engines": { 350 | "node": ">=12" 351 | } 352 | }, 353 | "node_modules/@esbuild/sunos-x64": { 354 | "version": "0.17.3", 355 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz", 356 | "integrity": "sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q==", 357 | "cpu": [ 358 | "x64" 359 | ], 360 | "dev": true, 361 | "license": "MIT", 362 | "optional": true, 363 | "os": [ 364 | "sunos" 365 | ], 366 | "engines": { 367 | "node": ">=12" 368 | } 369 | }, 370 | "node_modules/@esbuild/win32-arm64": { 371 | "version": "0.17.3", 372 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz", 373 | "integrity": "sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A==", 374 | "cpu": [ 375 | "arm64" 376 | ], 377 | "dev": true, 378 | "license": "MIT", 379 | "optional": true, 380 | "os": [ 381 | "win32" 382 | ], 383 | "engines": { 384 | "node": ">=12" 385 | } 386 | }, 387 | "node_modules/@esbuild/win32-ia32": { 388 | "version": "0.17.3", 389 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz", 390 | "integrity": "sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg==", 391 | "cpu": [ 392 | "ia32" 393 | ], 394 | "dev": true, 395 | "license": "MIT", 396 | "optional": true, 397 | "os": [ 398 | "win32" 399 | ], 400 | "engines": { 401 | "node": ">=12" 402 | } 403 | }, 404 | "node_modules/@esbuild/win32-x64": { 405 | "version": "0.17.3", 406 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz", 407 | "integrity": "sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g==", 408 | "cpu": [ 409 | "x64" 410 | ], 411 | "dev": true, 412 | "license": "MIT", 413 | "optional": true, 414 | "os": [ 415 | "win32" 416 | ], 417 | "engines": { 418 | "node": ">=12" 419 | } 420 | }, 421 | "node_modules/@eslint-community/eslint-utils": { 422 | "version": "4.7.0", 423 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", 424 | "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", 425 | "dev": true, 426 | "license": "MIT", 427 | "peer": true, 428 | "dependencies": { 429 | "eslint-visitor-keys": "^3.4.3" 430 | }, 431 | "engines": { 432 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 433 | }, 434 | "funding": { 435 | "url": "https://opencollective.com/eslint" 436 | }, 437 | "peerDependencies": { 438 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" 439 | } 440 | }, 441 | "node_modules/@eslint-community/regexpp": { 442 | "version": "4.12.1", 443 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", 444 | "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", 445 | "dev": true, 446 | "license": "MIT", 447 | "peer": true, 448 | "engines": { 449 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0" 450 | } 451 | }, 452 | "node_modules/@eslint/eslintrc": { 453 | "version": "2.1.4", 454 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", 455 | "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", 456 | "dev": true, 457 | "license": "MIT", 458 | "peer": true, 459 | "dependencies": { 460 | "ajv": "^6.12.4", 461 | "debug": "^4.3.2", 462 | "espree": "^9.6.0", 463 | "globals": "^13.19.0", 464 | "ignore": "^5.2.0", 465 | "import-fresh": "^3.2.1", 466 | "js-yaml": "^4.1.0", 467 | "minimatch": "^3.1.2", 468 | "strip-json-comments": "^3.1.1" 469 | }, 470 | "engines": { 471 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 472 | }, 473 | "funding": { 474 | "url": "https://opencollective.com/eslint" 475 | } 476 | }, 477 | "node_modules/@eslint/js": { 478 | "version": "8.57.1", 479 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", 480 | "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", 481 | "dev": true, 482 | "license": "MIT", 483 | "peer": true, 484 | "engines": { 485 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 486 | } 487 | }, 488 | "node_modules/@humanwhocodes/config-array": { 489 | "version": "0.13.0", 490 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", 491 | "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", 492 | "deprecated": "Use @eslint/config-array instead", 493 | "dev": true, 494 | "license": "Apache-2.0", 495 | "peer": true, 496 | "dependencies": { 497 | "@humanwhocodes/object-schema": "^2.0.3", 498 | "debug": "^4.3.1", 499 | "minimatch": "^3.0.5" 500 | }, 501 | "engines": { 502 | "node": ">=10.10.0" 503 | } 504 | }, 505 | "node_modules/@humanwhocodes/module-importer": { 506 | "version": "1.0.1", 507 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 508 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 509 | "dev": true, 510 | "license": "Apache-2.0", 511 | "peer": true, 512 | "engines": { 513 | "node": ">=12.22" 514 | }, 515 | "funding": { 516 | "type": "github", 517 | "url": "https://github.com/sponsors/nzakas" 518 | } 519 | }, 520 | "node_modules/@humanwhocodes/object-schema": { 521 | "version": "2.0.3", 522 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", 523 | "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", 524 | "deprecated": "Use @eslint/object-schema instead", 525 | "dev": true, 526 | "license": "BSD-3-Clause", 527 | "peer": true 528 | }, 529 | "node_modules/@marijn/find-cluster-break": { 530 | "version": "1.0.2", 531 | "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", 532 | "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", 533 | "dev": true, 534 | "license": "MIT", 535 | "peer": true 536 | }, 537 | "node_modules/@nodelib/fs.scandir": { 538 | "version": "2.1.5", 539 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 540 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 541 | "dev": true, 542 | "license": "MIT", 543 | "dependencies": { 544 | "@nodelib/fs.stat": "2.0.5", 545 | "run-parallel": "^1.1.9" 546 | }, 547 | "engines": { 548 | "node": ">= 8" 549 | } 550 | }, 551 | "node_modules/@nodelib/fs.stat": { 552 | "version": "2.0.5", 553 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 554 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 555 | "dev": true, 556 | "license": "MIT", 557 | "engines": { 558 | "node": ">= 8" 559 | } 560 | }, 561 | "node_modules/@nodelib/fs.walk": { 562 | "version": "1.2.8", 563 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 564 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 565 | "dev": true, 566 | "license": "MIT", 567 | "dependencies": { 568 | "@nodelib/fs.scandir": "2.1.5", 569 | "fastq": "^1.6.0" 570 | }, 571 | "engines": { 572 | "node": ">= 8" 573 | } 574 | }, 575 | "node_modules/@types/codemirror": { 576 | "version": "5.60.8", 577 | "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz", 578 | "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==", 579 | "dev": true, 580 | "license": "MIT", 581 | "dependencies": { 582 | "@types/tern": "*" 583 | } 584 | }, 585 | "node_modules/@types/estree": { 586 | "version": "1.0.8", 587 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", 588 | "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", 589 | "dev": true, 590 | "license": "MIT" 591 | }, 592 | "node_modules/@types/json-schema": { 593 | "version": "7.0.15", 594 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", 595 | "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", 596 | "dev": true, 597 | "license": "MIT" 598 | }, 599 | "node_modules/@types/node": { 600 | "version": "16.18.126", 601 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", 602 | "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", 603 | "dev": true, 604 | "license": "MIT" 605 | }, 606 | "node_modules/@types/tern": { 607 | "version": "0.23.9", 608 | "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", 609 | "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", 610 | "dev": true, 611 | "license": "MIT", 612 | "dependencies": { 613 | "@types/estree": "*" 614 | } 615 | }, 616 | "node_modules/@typescript-eslint/eslint-plugin": { 617 | "version": "5.29.0", 618 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", 619 | "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", 620 | "dev": true, 621 | "license": "MIT", 622 | "dependencies": { 623 | "@typescript-eslint/scope-manager": "5.29.0", 624 | "@typescript-eslint/type-utils": "5.29.0", 625 | "@typescript-eslint/utils": "5.29.0", 626 | "debug": "^4.3.4", 627 | "functional-red-black-tree": "^1.0.1", 628 | "ignore": "^5.2.0", 629 | "regexpp": "^3.2.0", 630 | "semver": "^7.3.7", 631 | "tsutils": "^3.21.0" 632 | }, 633 | "engines": { 634 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 635 | }, 636 | "funding": { 637 | "type": "opencollective", 638 | "url": "https://opencollective.com/typescript-eslint" 639 | }, 640 | "peerDependencies": { 641 | "@typescript-eslint/parser": "^5.0.0", 642 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 643 | }, 644 | "peerDependenciesMeta": { 645 | "typescript": { 646 | "optional": true 647 | } 648 | } 649 | }, 650 | "node_modules/@typescript-eslint/parser": { 651 | "version": "5.29.0", 652 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", 653 | "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", 654 | "dev": true, 655 | "license": "BSD-2-Clause", 656 | "dependencies": { 657 | "@typescript-eslint/scope-manager": "5.29.0", 658 | "@typescript-eslint/types": "5.29.0", 659 | "@typescript-eslint/typescript-estree": "5.29.0", 660 | "debug": "^4.3.4" 661 | }, 662 | "engines": { 663 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 664 | }, 665 | "funding": { 666 | "type": "opencollective", 667 | "url": "https://opencollective.com/typescript-eslint" 668 | }, 669 | "peerDependencies": { 670 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 671 | }, 672 | "peerDependenciesMeta": { 673 | "typescript": { 674 | "optional": true 675 | } 676 | } 677 | }, 678 | "node_modules/@typescript-eslint/scope-manager": { 679 | "version": "5.29.0", 680 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", 681 | "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", 682 | "dev": true, 683 | "license": "MIT", 684 | "dependencies": { 685 | "@typescript-eslint/types": "5.29.0", 686 | "@typescript-eslint/visitor-keys": "5.29.0" 687 | }, 688 | "engines": { 689 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 690 | }, 691 | "funding": { 692 | "type": "opencollective", 693 | "url": "https://opencollective.com/typescript-eslint" 694 | } 695 | }, 696 | "node_modules/@typescript-eslint/type-utils": { 697 | "version": "5.29.0", 698 | "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", 699 | "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", 700 | "dev": true, 701 | "license": "MIT", 702 | "dependencies": { 703 | "@typescript-eslint/utils": "5.29.0", 704 | "debug": "^4.3.4", 705 | "tsutils": "^3.21.0" 706 | }, 707 | "engines": { 708 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 709 | }, 710 | "funding": { 711 | "type": "opencollective", 712 | "url": "https://opencollective.com/typescript-eslint" 713 | }, 714 | "peerDependencies": { 715 | "eslint": "*" 716 | }, 717 | "peerDependenciesMeta": { 718 | "typescript": { 719 | "optional": true 720 | } 721 | } 722 | }, 723 | "node_modules/@typescript-eslint/types": { 724 | "version": "5.29.0", 725 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", 726 | "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", 727 | "dev": true, 728 | "license": "MIT", 729 | "engines": { 730 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 731 | }, 732 | "funding": { 733 | "type": "opencollective", 734 | "url": "https://opencollective.com/typescript-eslint" 735 | } 736 | }, 737 | "node_modules/@typescript-eslint/typescript-estree": { 738 | "version": "5.29.0", 739 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", 740 | "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", 741 | "dev": true, 742 | "license": "BSD-2-Clause", 743 | "dependencies": { 744 | "@typescript-eslint/types": "5.29.0", 745 | "@typescript-eslint/visitor-keys": "5.29.0", 746 | "debug": "^4.3.4", 747 | "globby": "^11.1.0", 748 | "is-glob": "^4.0.3", 749 | "semver": "^7.3.7", 750 | "tsutils": "^3.21.0" 751 | }, 752 | "engines": { 753 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 754 | }, 755 | "funding": { 756 | "type": "opencollective", 757 | "url": "https://opencollective.com/typescript-eslint" 758 | }, 759 | "peerDependenciesMeta": { 760 | "typescript": { 761 | "optional": true 762 | } 763 | } 764 | }, 765 | "node_modules/@typescript-eslint/utils": { 766 | "version": "5.29.0", 767 | "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", 768 | "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", 769 | "dev": true, 770 | "license": "MIT", 771 | "dependencies": { 772 | "@types/json-schema": "^7.0.9", 773 | "@typescript-eslint/scope-manager": "5.29.0", 774 | "@typescript-eslint/types": "5.29.0", 775 | "@typescript-eslint/typescript-estree": "5.29.0", 776 | "eslint-scope": "^5.1.1", 777 | "eslint-utils": "^3.0.0" 778 | }, 779 | "engines": { 780 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 781 | }, 782 | "funding": { 783 | "type": "opencollective", 784 | "url": "https://opencollective.com/typescript-eslint" 785 | }, 786 | "peerDependencies": { 787 | "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" 788 | } 789 | }, 790 | "node_modules/@typescript-eslint/visitor-keys": { 791 | "version": "5.29.0", 792 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", 793 | "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", 794 | "dev": true, 795 | "license": "MIT", 796 | "dependencies": { 797 | "@typescript-eslint/types": "5.29.0", 798 | "eslint-visitor-keys": "^3.3.0" 799 | }, 800 | "engines": { 801 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 802 | }, 803 | "funding": { 804 | "type": "opencollective", 805 | "url": "https://opencollective.com/typescript-eslint" 806 | } 807 | }, 808 | "node_modules/@ungap/structured-clone": { 809 | "version": "1.3.0", 810 | "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", 811 | "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", 812 | "dev": true, 813 | "license": "ISC", 814 | "peer": true 815 | }, 816 | "node_modules/acorn": { 817 | "version": "8.15.0", 818 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", 819 | "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", 820 | "dev": true, 821 | "license": "MIT", 822 | "peer": true, 823 | "bin": { 824 | "acorn": "bin/acorn" 825 | }, 826 | "engines": { 827 | "node": ">=0.4.0" 828 | } 829 | }, 830 | "node_modules/acorn-jsx": { 831 | "version": "5.3.2", 832 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 833 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 834 | "dev": true, 835 | "license": "MIT", 836 | "peer": true, 837 | "peerDependencies": { 838 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" 839 | } 840 | }, 841 | "node_modules/ajv": { 842 | "version": "6.12.6", 843 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 844 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 845 | "dev": true, 846 | "license": "MIT", 847 | "peer": true, 848 | "dependencies": { 849 | "fast-deep-equal": "^3.1.1", 850 | "fast-json-stable-stringify": "^2.0.0", 851 | "json-schema-traverse": "^0.4.1", 852 | "uri-js": "^4.2.2" 853 | }, 854 | "funding": { 855 | "type": "github", 856 | "url": "https://github.com/sponsors/epoberezkin" 857 | } 858 | }, 859 | "node_modules/ansi-regex": { 860 | "version": "5.0.1", 861 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 862 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 863 | "dev": true, 864 | "license": "MIT", 865 | "peer": true, 866 | "engines": { 867 | "node": ">=8" 868 | } 869 | }, 870 | "node_modules/ansi-styles": { 871 | "version": "4.3.0", 872 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 873 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 874 | "dev": true, 875 | "license": "MIT", 876 | "peer": true, 877 | "dependencies": { 878 | "color-convert": "^2.0.1" 879 | }, 880 | "engines": { 881 | "node": ">=8" 882 | }, 883 | "funding": { 884 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 885 | } 886 | }, 887 | "node_modules/argparse": { 888 | "version": "2.0.1", 889 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 890 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 891 | "dev": true, 892 | "license": "Python-2.0", 893 | "peer": true 894 | }, 895 | "node_modules/array-union": { 896 | "version": "2.1.0", 897 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 898 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 899 | "dev": true, 900 | "license": "MIT", 901 | "engines": { 902 | "node": ">=8" 903 | } 904 | }, 905 | "node_modules/balanced-match": { 906 | "version": "1.0.2", 907 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 908 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 909 | "dev": true, 910 | "license": "MIT", 911 | "peer": true 912 | }, 913 | "node_modules/brace-expansion": { 914 | "version": "1.1.12", 915 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", 916 | "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", 917 | "dev": true, 918 | "license": "MIT", 919 | "peer": true, 920 | "dependencies": { 921 | "balanced-match": "^1.0.0", 922 | "concat-map": "0.0.1" 923 | } 924 | }, 925 | "node_modules/braces": { 926 | "version": "3.0.3", 927 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 928 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 929 | "dev": true, 930 | "license": "MIT", 931 | "dependencies": { 932 | "fill-range": "^7.1.1" 933 | }, 934 | "engines": { 935 | "node": ">=8" 936 | } 937 | }, 938 | "node_modules/builtin-modules": { 939 | "version": "3.3.0", 940 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", 941 | "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", 942 | "dev": true, 943 | "license": "MIT", 944 | "engines": { 945 | "node": ">=6" 946 | }, 947 | "funding": { 948 | "url": "https://github.com/sponsors/sindresorhus" 949 | } 950 | }, 951 | "node_modules/callsites": { 952 | "version": "3.1.0", 953 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 954 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 955 | "dev": true, 956 | "license": "MIT", 957 | "peer": true, 958 | "engines": { 959 | "node": ">=6" 960 | } 961 | }, 962 | "node_modules/chalk": { 963 | "version": "4.1.2", 964 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 965 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 966 | "dev": true, 967 | "license": "MIT", 968 | "peer": true, 969 | "dependencies": { 970 | "ansi-styles": "^4.1.0", 971 | "supports-color": "^7.1.0" 972 | }, 973 | "engines": { 974 | "node": ">=10" 975 | }, 976 | "funding": { 977 | "url": "https://github.com/chalk/chalk?sponsor=1" 978 | } 979 | }, 980 | "node_modules/color-convert": { 981 | "version": "2.0.1", 982 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 983 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 984 | "dev": true, 985 | "license": "MIT", 986 | "peer": true, 987 | "dependencies": { 988 | "color-name": "~1.1.4" 989 | }, 990 | "engines": { 991 | "node": ">=7.0.0" 992 | } 993 | }, 994 | "node_modules/color-name": { 995 | "version": "1.1.4", 996 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 997 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 998 | "dev": true, 999 | "license": "MIT", 1000 | "peer": true 1001 | }, 1002 | "node_modules/concat-map": { 1003 | "version": "0.0.1", 1004 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1005 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 1006 | "dev": true, 1007 | "license": "MIT", 1008 | "peer": true 1009 | }, 1010 | "node_modules/crelt": { 1011 | "version": "1.0.6", 1012 | "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", 1013 | "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", 1014 | "dev": true, 1015 | "license": "MIT", 1016 | "peer": true 1017 | }, 1018 | "node_modules/cross-spawn": { 1019 | "version": "7.0.6", 1020 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 1021 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 1022 | "dev": true, 1023 | "license": "MIT", 1024 | "peer": true, 1025 | "dependencies": { 1026 | "path-key": "^3.1.0", 1027 | "shebang-command": "^2.0.0", 1028 | "which": "^2.0.1" 1029 | }, 1030 | "engines": { 1031 | "node": ">= 8" 1032 | } 1033 | }, 1034 | "node_modules/debug": { 1035 | "version": "4.4.1", 1036 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", 1037 | "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", 1038 | "dev": true, 1039 | "license": "MIT", 1040 | "dependencies": { 1041 | "ms": "^2.1.3" 1042 | }, 1043 | "engines": { 1044 | "node": ">=6.0" 1045 | }, 1046 | "peerDependenciesMeta": { 1047 | "supports-color": { 1048 | "optional": true 1049 | } 1050 | } 1051 | }, 1052 | "node_modules/deep-is": { 1053 | "version": "0.1.4", 1054 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 1055 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 1056 | "dev": true, 1057 | "license": "MIT", 1058 | "peer": true 1059 | }, 1060 | "node_modules/dir-glob": { 1061 | "version": "3.0.1", 1062 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 1063 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 1064 | "dev": true, 1065 | "license": "MIT", 1066 | "dependencies": { 1067 | "path-type": "^4.0.0" 1068 | }, 1069 | "engines": { 1070 | "node": ">=8" 1071 | } 1072 | }, 1073 | "node_modules/doctrine": { 1074 | "version": "3.0.0", 1075 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 1076 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 1077 | "dev": true, 1078 | "license": "Apache-2.0", 1079 | "peer": true, 1080 | "dependencies": { 1081 | "esutils": "^2.0.2" 1082 | }, 1083 | "engines": { 1084 | "node": ">=6.0.0" 1085 | } 1086 | }, 1087 | "node_modules/esbuild": { 1088 | "version": "0.17.3", 1089 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz", 1090 | "integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==", 1091 | "dev": true, 1092 | "hasInstallScript": true, 1093 | "license": "MIT", 1094 | "bin": { 1095 | "esbuild": "bin/esbuild" 1096 | }, 1097 | "engines": { 1098 | "node": ">=12" 1099 | }, 1100 | "optionalDependencies": { 1101 | "@esbuild/android-arm": "0.17.3", 1102 | "@esbuild/android-arm64": "0.17.3", 1103 | "@esbuild/android-x64": "0.17.3", 1104 | "@esbuild/darwin-arm64": "0.17.3", 1105 | "@esbuild/darwin-x64": "0.17.3", 1106 | "@esbuild/freebsd-arm64": "0.17.3", 1107 | "@esbuild/freebsd-x64": "0.17.3", 1108 | "@esbuild/linux-arm": "0.17.3", 1109 | "@esbuild/linux-arm64": "0.17.3", 1110 | "@esbuild/linux-ia32": "0.17.3", 1111 | "@esbuild/linux-loong64": "0.17.3", 1112 | "@esbuild/linux-mips64el": "0.17.3", 1113 | "@esbuild/linux-ppc64": "0.17.3", 1114 | "@esbuild/linux-riscv64": "0.17.3", 1115 | "@esbuild/linux-s390x": "0.17.3", 1116 | "@esbuild/linux-x64": "0.17.3", 1117 | "@esbuild/netbsd-x64": "0.17.3", 1118 | "@esbuild/openbsd-x64": "0.17.3", 1119 | "@esbuild/sunos-x64": "0.17.3", 1120 | "@esbuild/win32-arm64": "0.17.3", 1121 | "@esbuild/win32-ia32": "0.17.3", 1122 | "@esbuild/win32-x64": "0.17.3" 1123 | } 1124 | }, 1125 | "node_modules/escape-string-regexp": { 1126 | "version": "4.0.0", 1127 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1128 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1129 | "dev": true, 1130 | "license": "MIT", 1131 | "peer": true, 1132 | "engines": { 1133 | "node": ">=10" 1134 | }, 1135 | "funding": { 1136 | "url": "https://github.com/sponsors/sindresorhus" 1137 | } 1138 | }, 1139 | "node_modules/eslint": { 1140 | "version": "8.57.1", 1141 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", 1142 | "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", 1143 | "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", 1144 | "dev": true, 1145 | "license": "MIT", 1146 | "peer": true, 1147 | "dependencies": { 1148 | "@eslint-community/eslint-utils": "^4.2.0", 1149 | "@eslint-community/regexpp": "^4.6.1", 1150 | "@eslint/eslintrc": "^2.1.4", 1151 | "@eslint/js": "8.57.1", 1152 | "@humanwhocodes/config-array": "^0.13.0", 1153 | "@humanwhocodes/module-importer": "^1.0.1", 1154 | "@nodelib/fs.walk": "^1.2.8", 1155 | "@ungap/structured-clone": "^1.2.0", 1156 | "ajv": "^6.12.4", 1157 | "chalk": "^4.0.0", 1158 | "cross-spawn": "^7.0.2", 1159 | "debug": "^4.3.2", 1160 | "doctrine": "^3.0.0", 1161 | "escape-string-regexp": "^4.0.0", 1162 | "eslint-scope": "^7.2.2", 1163 | "eslint-visitor-keys": "^3.4.3", 1164 | "espree": "^9.6.1", 1165 | "esquery": "^1.4.2", 1166 | "esutils": "^2.0.2", 1167 | "fast-deep-equal": "^3.1.3", 1168 | "file-entry-cache": "^6.0.1", 1169 | "find-up": "^5.0.0", 1170 | "glob-parent": "^6.0.2", 1171 | "globals": "^13.19.0", 1172 | "graphemer": "^1.4.0", 1173 | "ignore": "^5.2.0", 1174 | "imurmurhash": "^0.1.4", 1175 | "is-glob": "^4.0.0", 1176 | "is-path-inside": "^3.0.3", 1177 | "js-yaml": "^4.1.0", 1178 | "json-stable-stringify-without-jsonify": "^1.0.1", 1179 | "levn": "^0.4.1", 1180 | "lodash.merge": "^4.6.2", 1181 | "minimatch": "^3.1.2", 1182 | "natural-compare": "^1.4.0", 1183 | "optionator": "^0.9.3", 1184 | "strip-ansi": "^6.0.1", 1185 | "text-table": "^0.2.0" 1186 | }, 1187 | "bin": { 1188 | "eslint": "bin/eslint.js" 1189 | }, 1190 | "engines": { 1191 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1192 | }, 1193 | "funding": { 1194 | "url": "https://opencollective.com/eslint" 1195 | } 1196 | }, 1197 | "node_modules/eslint-scope": { 1198 | "version": "5.1.1", 1199 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 1200 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1201 | "dev": true, 1202 | "license": "BSD-2-Clause", 1203 | "dependencies": { 1204 | "esrecurse": "^4.3.0", 1205 | "estraverse": "^4.1.1" 1206 | }, 1207 | "engines": { 1208 | "node": ">=8.0.0" 1209 | } 1210 | }, 1211 | "node_modules/eslint-utils": { 1212 | "version": "3.0.0", 1213 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 1214 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 1215 | "dev": true, 1216 | "license": "MIT", 1217 | "dependencies": { 1218 | "eslint-visitor-keys": "^2.0.0" 1219 | }, 1220 | "engines": { 1221 | "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" 1222 | }, 1223 | "funding": { 1224 | "url": "https://github.com/sponsors/mysticatea" 1225 | }, 1226 | "peerDependencies": { 1227 | "eslint": ">=5" 1228 | } 1229 | }, 1230 | "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { 1231 | "version": "2.1.0", 1232 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1233 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1234 | "dev": true, 1235 | "license": "Apache-2.0", 1236 | "engines": { 1237 | "node": ">=10" 1238 | } 1239 | }, 1240 | "node_modules/eslint-visitor-keys": { 1241 | "version": "3.4.3", 1242 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", 1243 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", 1244 | "dev": true, 1245 | "license": "Apache-2.0", 1246 | "engines": { 1247 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1248 | }, 1249 | "funding": { 1250 | "url": "https://opencollective.com/eslint" 1251 | } 1252 | }, 1253 | "node_modules/eslint/node_modules/eslint-scope": { 1254 | "version": "7.2.2", 1255 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", 1256 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", 1257 | "dev": true, 1258 | "license": "BSD-2-Clause", 1259 | "peer": true, 1260 | "dependencies": { 1261 | "esrecurse": "^4.3.0", 1262 | "estraverse": "^5.2.0" 1263 | }, 1264 | "engines": { 1265 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1266 | }, 1267 | "funding": { 1268 | "url": "https://opencollective.com/eslint" 1269 | } 1270 | }, 1271 | "node_modules/eslint/node_modules/estraverse": { 1272 | "version": "5.3.0", 1273 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1274 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1275 | "dev": true, 1276 | "license": "BSD-2-Clause", 1277 | "peer": true, 1278 | "engines": { 1279 | "node": ">=4.0" 1280 | } 1281 | }, 1282 | "node_modules/espree": { 1283 | "version": "9.6.1", 1284 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", 1285 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", 1286 | "dev": true, 1287 | "license": "BSD-2-Clause", 1288 | "peer": true, 1289 | "dependencies": { 1290 | "acorn": "^8.9.0", 1291 | "acorn-jsx": "^5.3.2", 1292 | "eslint-visitor-keys": "^3.4.1" 1293 | }, 1294 | "engines": { 1295 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 1296 | }, 1297 | "funding": { 1298 | "url": "https://opencollective.com/eslint" 1299 | } 1300 | }, 1301 | "node_modules/esquery": { 1302 | "version": "1.6.0", 1303 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", 1304 | "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", 1305 | "dev": true, 1306 | "license": "BSD-3-Clause", 1307 | "peer": true, 1308 | "dependencies": { 1309 | "estraverse": "^5.1.0" 1310 | }, 1311 | "engines": { 1312 | "node": ">=0.10" 1313 | } 1314 | }, 1315 | "node_modules/esquery/node_modules/estraverse": { 1316 | "version": "5.3.0", 1317 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1318 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1319 | "dev": true, 1320 | "license": "BSD-2-Clause", 1321 | "peer": true, 1322 | "engines": { 1323 | "node": ">=4.0" 1324 | } 1325 | }, 1326 | "node_modules/esrecurse": { 1327 | "version": "4.3.0", 1328 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1329 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1330 | "dev": true, 1331 | "license": "BSD-2-Clause", 1332 | "dependencies": { 1333 | "estraverse": "^5.2.0" 1334 | }, 1335 | "engines": { 1336 | "node": ">=4.0" 1337 | } 1338 | }, 1339 | "node_modules/esrecurse/node_modules/estraverse": { 1340 | "version": "5.3.0", 1341 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1342 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1343 | "dev": true, 1344 | "license": "BSD-2-Clause", 1345 | "engines": { 1346 | "node": ">=4.0" 1347 | } 1348 | }, 1349 | "node_modules/estraverse": { 1350 | "version": "4.3.0", 1351 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1352 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1353 | "dev": true, 1354 | "license": "BSD-2-Clause", 1355 | "engines": { 1356 | "node": ">=4.0" 1357 | } 1358 | }, 1359 | "node_modules/esutils": { 1360 | "version": "2.0.3", 1361 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1362 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1363 | "dev": true, 1364 | "license": "BSD-2-Clause", 1365 | "peer": true, 1366 | "engines": { 1367 | "node": ">=0.10.0" 1368 | } 1369 | }, 1370 | "node_modules/fast-deep-equal": { 1371 | "version": "3.1.3", 1372 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1373 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1374 | "dev": true, 1375 | "license": "MIT", 1376 | "peer": true 1377 | }, 1378 | "node_modules/fast-glob": { 1379 | "version": "3.3.3", 1380 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", 1381 | "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", 1382 | "dev": true, 1383 | "license": "MIT", 1384 | "dependencies": { 1385 | "@nodelib/fs.stat": "^2.0.2", 1386 | "@nodelib/fs.walk": "^1.2.3", 1387 | "glob-parent": "^5.1.2", 1388 | "merge2": "^1.3.0", 1389 | "micromatch": "^4.0.8" 1390 | }, 1391 | "engines": { 1392 | "node": ">=8.6.0" 1393 | } 1394 | }, 1395 | "node_modules/fast-glob/node_modules/glob-parent": { 1396 | "version": "5.1.2", 1397 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1398 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1399 | "dev": true, 1400 | "license": "ISC", 1401 | "dependencies": { 1402 | "is-glob": "^4.0.1" 1403 | }, 1404 | "engines": { 1405 | "node": ">= 6" 1406 | } 1407 | }, 1408 | "node_modules/fast-json-stable-stringify": { 1409 | "version": "2.1.0", 1410 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1411 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1412 | "dev": true, 1413 | "license": "MIT", 1414 | "peer": true 1415 | }, 1416 | "node_modules/fast-levenshtein": { 1417 | "version": "2.0.6", 1418 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1419 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 1420 | "dev": true, 1421 | "license": "MIT", 1422 | "peer": true 1423 | }, 1424 | "node_modules/fastq": { 1425 | "version": "1.19.1", 1426 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", 1427 | "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", 1428 | "dev": true, 1429 | "license": "ISC", 1430 | "dependencies": { 1431 | "reusify": "^1.0.4" 1432 | } 1433 | }, 1434 | "node_modules/file-entry-cache": { 1435 | "version": "6.0.1", 1436 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1437 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1438 | "dev": true, 1439 | "license": "MIT", 1440 | "peer": true, 1441 | "dependencies": { 1442 | "flat-cache": "^3.0.4" 1443 | }, 1444 | "engines": { 1445 | "node": "^10.12.0 || >=12.0.0" 1446 | } 1447 | }, 1448 | "node_modules/fill-range": { 1449 | "version": "7.1.1", 1450 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1451 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1452 | "dev": true, 1453 | "license": "MIT", 1454 | "dependencies": { 1455 | "to-regex-range": "^5.0.1" 1456 | }, 1457 | "engines": { 1458 | "node": ">=8" 1459 | } 1460 | }, 1461 | "node_modules/find-up": { 1462 | "version": "5.0.0", 1463 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1464 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1465 | "dev": true, 1466 | "license": "MIT", 1467 | "peer": true, 1468 | "dependencies": { 1469 | "locate-path": "^6.0.0", 1470 | "path-exists": "^4.0.0" 1471 | }, 1472 | "engines": { 1473 | "node": ">=10" 1474 | }, 1475 | "funding": { 1476 | "url": "https://github.com/sponsors/sindresorhus" 1477 | } 1478 | }, 1479 | "node_modules/flat-cache": { 1480 | "version": "3.2.0", 1481 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", 1482 | "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", 1483 | "dev": true, 1484 | "license": "MIT", 1485 | "peer": true, 1486 | "dependencies": { 1487 | "flatted": "^3.2.9", 1488 | "keyv": "^4.5.3", 1489 | "rimraf": "^3.0.2" 1490 | }, 1491 | "engines": { 1492 | "node": "^10.12.0 || >=12.0.0" 1493 | } 1494 | }, 1495 | "node_modules/flatted": { 1496 | "version": "3.3.3", 1497 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", 1498 | "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", 1499 | "dev": true, 1500 | "license": "ISC", 1501 | "peer": true 1502 | }, 1503 | "node_modules/fs.realpath": { 1504 | "version": "1.0.0", 1505 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1506 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 1507 | "dev": true, 1508 | "license": "ISC", 1509 | "peer": true 1510 | }, 1511 | "node_modules/functional-red-black-tree": { 1512 | "version": "1.0.1", 1513 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1514 | "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", 1515 | "dev": true, 1516 | "license": "MIT" 1517 | }, 1518 | "node_modules/glob": { 1519 | "version": "7.2.3", 1520 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 1521 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 1522 | "deprecated": "Glob versions prior to v9 are no longer supported", 1523 | "dev": true, 1524 | "license": "ISC", 1525 | "peer": true, 1526 | "dependencies": { 1527 | "fs.realpath": "^1.0.0", 1528 | "inflight": "^1.0.4", 1529 | "inherits": "2", 1530 | "minimatch": "^3.1.1", 1531 | "once": "^1.3.0", 1532 | "path-is-absolute": "^1.0.0" 1533 | }, 1534 | "engines": { 1535 | "node": "*" 1536 | }, 1537 | "funding": { 1538 | "url": "https://github.com/sponsors/isaacs" 1539 | } 1540 | }, 1541 | "node_modules/glob-parent": { 1542 | "version": "6.0.2", 1543 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1544 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1545 | "dev": true, 1546 | "license": "ISC", 1547 | "peer": true, 1548 | "dependencies": { 1549 | "is-glob": "^4.0.3" 1550 | }, 1551 | "engines": { 1552 | "node": ">=10.13.0" 1553 | } 1554 | }, 1555 | "node_modules/globals": { 1556 | "version": "13.24.0", 1557 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", 1558 | "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", 1559 | "dev": true, 1560 | "license": "MIT", 1561 | "peer": true, 1562 | "dependencies": { 1563 | "type-fest": "^0.20.2" 1564 | }, 1565 | "engines": { 1566 | "node": ">=8" 1567 | }, 1568 | "funding": { 1569 | "url": "https://github.com/sponsors/sindresorhus" 1570 | } 1571 | }, 1572 | "node_modules/globby": { 1573 | "version": "11.1.0", 1574 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", 1575 | "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", 1576 | "dev": true, 1577 | "license": "MIT", 1578 | "dependencies": { 1579 | "array-union": "^2.1.0", 1580 | "dir-glob": "^3.0.1", 1581 | "fast-glob": "^3.2.9", 1582 | "ignore": "^5.2.0", 1583 | "merge2": "^1.4.1", 1584 | "slash": "^3.0.0" 1585 | }, 1586 | "engines": { 1587 | "node": ">=10" 1588 | }, 1589 | "funding": { 1590 | "url": "https://github.com/sponsors/sindresorhus" 1591 | } 1592 | }, 1593 | "node_modules/graphemer": { 1594 | "version": "1.4.0", 1595 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", 1596 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", 1597 | "dev": true, 1598 | "license": "MIT", 1599 | "peer": true 1600 | }, 1601 | "node_modules/has-flag": { 1602 | "version": "4.0.0", 1603 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1604 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1605 | "dev": true, 1606 | "license": "MIT", 1607 | "peer": true, 1608 | "engines": { 1609 | "node": ">=8" 1610 | } 1611 | }, 1612 | "node_modules/ignore": { 1613 | "version": "5.3.2", 1614 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", 1615 | "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", 1616 | "dev": true, 1617 | "license": "MIT", 1618 | "engines": { 1619 | "node": ">= 4" 1620 | } 1621 | }, 1622 | "node_modules/import-fresh": { 1623 | "version": "3.3.1", 1624 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", 1625 | "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", 1626 | "dev": true, 1627 | "license": "MIT", 1628 | "peer": true, 1629 | "dependencies": { 1630 | "parent-module": "^1.0.0", 1631 | "resolve-from": "^4.0.0" 1632 | }, 1633 | "engines": { 1634 | "node": ">=6" 1635 | }, 1636 | "funding": { 1637 | "url": "https://github.com/sponsors/sindresorhus" 1638 | } 1639 | }, 1640 | "node_modules/imurmurhash": { 1641 | "version": "0.1.4", 1642 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1643 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 1644 | "dev": true, 1645 | "license": "MIT", 1646 | "peer": true, 1647 | "engines": { 1648 | "node": ">=0.8.19" 1649 | } 1650 | }, 1651 | "node_modules/inflight": { 1652 | "version": "1.0.6", 1653 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1654 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 1655 | "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.", 1656 | "dev": true, 1657 | "license": "ISC", 1658 | "peer": true, 1659 | "dependencies": { 1660 | "once": "^1.3.0", 1661 | "wrappy": "1" 1662 | } 1663 | }, 1664 | "node_modules/inherits": { 1665 | "version": "2.0.4", 1666 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1667 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1668 | "dev": true, 1669 | "license": "ISC", 1670 | "peer": true 1671 | }, 1672 | "node_modules/is-extglob": { 1673 | "version": "2.1.1", 1674 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1675 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1676 | "dev": true, 1677 | "license": "MIT", 1678 | "engines": { 1679 | "node": ">=0.10.0" 1680 | } 1681 | }, 1682 | "node_modules/is-glob": { 1683 | "version": "4.0.3", 1684 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1685 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1686 | "dev": true, 1687 | "license": "MIT", 1688 | "dependencies": { 1689 | "is-extglob": "^2.1.1" 1690 | }, 1691 | "engines": { 1692 | "node": ">=0.10.0" 1693 | } 1694 | }, 1695 | "node_modules/is-number": { 1696 | "version": "7.0.0", 1697 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1698 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1699 | "dev": true, 1700 | "license": "MIT", 1701 | "engines": { 1702 | "node": ">=0.12.0" 1703 | } 1704 | }, 1705 | "node_modules/is-path-inside": { 1706 | "version": "3.0.3", 1707 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 1708 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 1709 | "dev": true, 1710 | "license": "MIT", 1711 | "peer": true, 1712 | "engines": { 1713 | "node": ">=8" 1714 | } 1715 | }, 1716 | "node_modules/isexe": { 1717 | "version": "2.0.0", 1718 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1719 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1720 | "dev": true, 1721 | "license": "ISC", 1722 | "peer": true 1723 | }, 1724 | "node_modules/js-yaml": { 1725 | "version": "4.1.0", 1726 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1727 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1728 | "dev": true, 1729 | "license": "MIT", 1730 | "peer": true, 1731 | "dependencies": { 1732 | "argparse": "^2.0.1" 1733 | }, 1734 | "bin": { 1735 | "js-yaml": "bin/js-yaml.js" 1736 | } 1737 | }, 1738 | "node_modules/json-buffer": { 1739 | "version": "3.0.1", 1740 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", 1741 | "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", 1742 | "dev": true, 1743 | "license": "MIT", 1744 | "peer": true 1745 | }, 1746 | "node_modules/json-schema-traverse": { 1747 | "version": "0.4.1", 1748 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1749 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1750 | "dev": true, 1751 | "license": "MIT", 1752 | "peer": true 1753 | }, 1754 | "node_modules/json-stable-stringify-without-jsonify": { 1755 | "version": "1.0.1", 1756 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1757 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 1758 | "dev": true, 1759 | "license": "MIT", 1760 | "peer": true 1761 | }, 1762 | "node_modules/keyv": { 1763 | "version": "4.5.4", 1764 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", 1765 | "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", 1766 | "dev": true, 1767 | "license": "MIT", 1768 | "peer": true, 1769 | "dependencies": { 1770 | "json-buffer": "3.0.1" 1771 | } 1772 | }, 1773 | "node_modules/levn": { 1774 | "version": "0.4.1", 1775 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1776 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1777 | "dev": true, 1778 | "license": "MIT", 1779 | "peer": true, 1780 | "dependencies": { 1781 | "prelude-ls": "^1.2.1", 1782 | "type-check": "~0.4.0" 1783 | }, 1784 | "engines": { 1785 | "node": ">= 0.8.0" 1786 | } 1787 | }, 1788 | "node_modules/locate-path": { 1789 | "version": "6.0.0", 1790 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1791 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1792 | "dev": true, 1793 | "license": "MIT", 1794 | "peer": true, 1795 | "dependencies": { 1796 | "p-locate": "^5.0.0" 1797 | }, 1798 | "engines": { 1799 | "node": ">=10" 1800 | }, 1801 | "funding": { 1802 | "url": "https://github.com/sponsors/sindresorhus" 1803 | } 1804 | }, 1805 | "node_modules/lodash.merge": { 1806 | "version": "4.6.2", 1807 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1808 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1809 | "dev": true, 1810 | "license": "MIT", 1811 | "peer": true 1812 | }, 1813 | "node_modules/merge2": { 1814 | "version": "1.4.1", 1815 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1816 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1817 | "dev": true, 1818 | "license": "MIT", 1819 | "engines": { 1820 | "node": ">= 8" 1821 | } 1822 | }, 1823 | "node_modules/micromatch": { 1824 | "version": "4.0.8", 1825 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 1826 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 1827 | "dev": true, 1828 | "license": "MIT", 1829 | "dependencies": { 1830 | "braces": "^3.0.3", 1831 | "picomatch": "^2.3.1" 1832 | }, 1833 | "engines": { 1834 | "node": ">=8.6" 1835 | } 1836 | }, 1837 | "node_modules/minimatch": { 1838 | "version": "3.1.2", 1839 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1840 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1841 | "dev": true, 1842 | "license": "ISC", 1843 | "peer": true, 1844 | "dependencies": { 1845 | "brace-expansion": "^1.1.7" 1846 | }, 1847 | "engines": { 1848 | "node": "*" 1849 | } 1850 | }, 1851 | "node_modules/moment": { 1852 | "version": "2.29.4", 1853 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", 1854 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", 1855 | "dev": true, 1856 | "license": "MIT", 1857 | "engines": { 1858 | "node": "*" 1859 | } 1860 | }, 1861 | "node_modules/ms": { 1862 | "version": "2.1.3", 1863 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1864 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1865 | "dev": true, 1866 | "license": "MIT" 1867 | }, 1868 | "node_modules/natural-compare": { 1869 | "version": "1.4.0", 1870 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1871 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1872 | "dev": true, 1873 | "license": "MIT", 1874 | "peer": true 1875 | }, 1876 | "node_modules/obsidian": { 1877 | "version": "1.8.7", 1878 | "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz", 1879 | "integrity": "sha512-h4bWwNFAGRXlMlMAzdEiIM2ppTGlrh7uGOJS6w4gClrsjc+ei/3YAtU2VdFUlCiPuTHpY4aBpFJJW75S1Tl/JA==", 1880 | "dev": true, 1881 | "license": "MIT", 1882 | "dependencies": { 1883 | "@types/codemirror": "5.60.8", 1884 | "moment": "2.29.4" 1885 | }, 1886 | "peerDependencies": { 1887 | "@codemirror/state": "^6.0.0", 1888 | "@codemirror/view": "^6.0.0" 1889 | } 1890 | }, 1891 | "node_modules/once": { 1892 | "version": "1.4.0", 1893 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1894 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1895 | "dev": true, 1896 | "license": "ISC", 1897 | "peer": true, 1898 | "dependencies": { 1899 | "wrappy": "1" 1900 | } 1901 | }, 1902 | "node_modules/optionator": { 1903 | "version": "0.9.4", 1904 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", 1905 | "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", 1906 | "dev": true, 1907 | "license": "MIT", 1908 | "peer": true, 1909 | "dependencies": { 1910 | "deep-is": "^0.1.3", 1911 | "fast-levenshtein": "^2.0.6", 1912 | "levn": "^0.4.1", 1913 | "prelude-ls": "^1.2.1", 1914 | "type-check": "^0.4.0", 1915 | "word-wrap": "^1.2.5" 1916 | }, 1917 | "engines": { 1918 | "node": ">= 0.8.0" 1919 | } 1920 | }, 1921 | "node_modules/p-limit": { 1922 | "version": "3.1.0", 1923 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1924 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1925 | "dev": true, 1926 | "license": "MIT", 1927 | "peer": true, 1928 | "dependencies": { 1929 | "yocto-queue": "^0.1.0" 1930 | }, 1931 | "engines": { 1932 | "node": ">=10" 1933 | }, 1934 | "funding": { 1935 | "url": "https://github.com/sponsors/sindresorhus" 1936 | } 1937 | }, 1938 | "node_modules/p-locate": { 1939 | "version": "5.0.0", 1940 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1941 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1942 | "dev": true, 1943 | "license": "MIT", 1944 | "peer": true, 1945 | "dependencies": { 1946 | "p-limit": "^3.0.2" 1947 | }, 1948 | "engines": { 1949 | "node": ">=10" 1950 | }, 1951 | "funding": { 1952 | "url": "https://github.com/sponsors/sindresorhus" 1953 | } 1954 | }, 1955 | "node_modules/parent-module": { 1956 | "version": "1.0.1", 1957 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1958 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1959 | "dev": true, 1960 | "license": "MIT", 1961 | "peer": true, 1962 | "dependencies": { 1963 | "callsites": "^3.0.0" 1964 | }, 1965 | "engines": { 1966 | "node": ">=6" 1967 | } 1968 | }, 1969 | "node_modules/path-exists": { 1970 | "version": "4.0.0", 1971 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1972 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1973 | "dev": true, 1974 | "license": "MIT", 1975 | "peer": true, 1976 | "engines": { 1977 | "node": ">=8" 1978 | } 1979 | }, 1980 | "node_modules/path-is-absolute": { 1981 | "version": "1.0.1", 1982 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1983 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1984 | "dev": true, 1985 | "license": "MIT", 1986 | "peer": true, 1987 | "engines": { 1988 | "node": ">=0.10.0" 1989 | } 1990 | }, 1991 | "node_modules/path-key": { 1992 | "version": "3.1.1", 1993 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1994 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1995 | "dev": true, 1996 | "license": "MIT", 1997 | "peer": true, 1998 | "engines": { 1999 | "node": ">=8" 2000 | } 2001 | }, 2002 | "node_modules/path-type": { 2003 | "version": "4.0.0", 2004 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 2005 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 2006 | "dev": true, 2007 | "license": "MIT", 2008 | "engines": { 2009 | "node": ">=8" 2010 | } 2011 | }, 2012 | "node_modules/picomatch": { 2013 | "version": "2.3.1", 2014 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2015 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2016 | "dev": true, 2017 | "license": "MIT", 2018 | "engines": { 2019 | "node": ">=8.6" 2020 | }, 2021 | "funding": { 2022 | "url": "https://github.com/sponsors/jonschlinkert" 2023 | } 2024 | }, 2025 | "node_modules/prelude-ls": { 2026 | "version": "1.2.1", 2027 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2028 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2029 | "dev": true, 2030 | "license": "MIT", 2031 | "peer": true, 2032 | "engines": { 2033 | "node": ">= 0.8.0" 2034 | } 2035 | }, 2036 | "node_modules/punycode": { 2037 | "version": "2.3.1", 2038 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 2039 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 2040 | "dev": true, 2041 | "license": "MIT", 2042 | "peer": true, 2043 | "engines": { 2044 | "node": ">=6" 2045 | } 2046 | }, 2047 | "node_modules/queue-microtask": { 2048 | "version": "1.2.3", 2049 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2050 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 2051 | "dev": true, 2052 | "funding": [ 2053 | { 2054 | "type": "github", 2055 | "url": "https://github.com/sponsors/feross" 2056 | }, 2057 | { 2058 | "type": "patreon", 2059 | "url": "https://www.patreon.com/feross" 2060 | }, 2061 | { 2062 | "type": "consulting", 2063 | "url": "https://feross.org/support" 2064 | } 2065 | ], 2066 | "license": "MIT" 2067 | }, 2068 | "node_modules/regexpp": { 2069 | "version": "3.2.0", 2070 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 2071 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 2072 | "dev": true, 2073 | "license": "MIT", 2074 | "engines": { 2075 | "node": ">=8" 2076 | }, 2077 | "funding": { 2078 | "url": "https://github.com/sponsors/mysticatea" 2079 | } 2080 | }, 2081 | "node_modules/resolve-from": { 2082 | "version": "4.0.0", 2083 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2084 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2085 | "dev": true, 2086 | "license": "MIT", 2087 | "peer": true, 2088 | "engines": { 2089 | "node": ">=4" 2090 | } 2091 | }, 2092 | "node_modules/reusify": { 2093 | "version": "1.1.0", 2094 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", 2095 | "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", 2096 | "dev": true, 2097 | "license": "MIT", 2098 | "engines": { 2099 | "iojs": ">=1.0.0", 2100 | "node": ">=0.10.0" 2101 | } 2102 | }, 2103 | "node_modules/rimraf": { 2104 | "version": "3.0.2", 2105 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2106 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2107 | "deprecated": "Rimraf versions prior to v4 are no longer supported", 2108 | "dev": true, 2109 | "license": "ISC", 2110 | "peer": true, 2111 | "dependencies": { 2112 | "glob": "^7.1.3" 2113 | }, 2114 | "bin": { 2115 | "rimraf": "bin.js" 2116 | }, 2117 | "funding": { 2118 | "url": "https://github.com/sponsors/isaacs" 2119 | } 2120 | }, 2121 | "node_modules/run-parallel": { 2122 | "version": "1.2.0", 2123 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2124 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2125 | "dev": true, 2126 | "funding": [ 2127 | { 2128 | "type": "github", 2129 | "url": "https://github.com/sponsors/feross" 2130 | }, 2131 | { 2132 | "type": "patreon", 2133 | "url": "https://www.patreon.com/feross" 2134 | }, 2135 | { 2136 | "type": "consulting", 2137 | "url": "https://feross.org/support" 2138 | } 2139 | ], 2140 | "license": "MIT", 2141 | "dependencies": { 2142 | "queue-microtask": "^1.2.2" 2143 | } 2144 | }, 2145 | "node_modules/semver": { 2146 | "version": "7.7.2", 2147 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", 2148 | "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", 2149 | "dev": true, 2150 | "license": "ISC", 2151 | "bin": { 2152 | "semver": "bin/semver.js" 2153 | }, 2154 | "engines": { 2155 | "node": ">=10" 2156 | } 2157 | }, 2158 | "node_modules/shebang-command": { 2159 | "version": "2.0.0", 2160 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2161 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2162 | "dev": true, 2163 | "license": "MIT", 2164 | "peer": true, 2165 | "dependencies": { 2166 | "shebang-regex": "^3.0.0" 2167 | }, 2168 | "engines": { 2169 | "node": ">=8" 2170 | } 2171 | }, 2172 | "node_modules/shebang-regex": { 2173 | "version": "3.0.0", 2174 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2175 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2176 | "dev": true, 2177 | "license": "MIT", 2178 | "peer": true, 2179 | "engines": { 2180 | "node": ">=8" 2181 | } 2182 | }, 2183 | "node_modules/slash": { 2184 | "version": "3.0.0", 2185 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2186 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2187 | "dev": true, 2188 | "license": "MIT", 2189 | "engines": { 2190 | "node": ">=8" 2191 | } 2192 | }, 2193 | "node_modules/strip-ansi": { 2194 | "version": "6.0.1", 2195 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2196 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2197 | "dev": true, 2198 | "license": "MIT", 2199 | "peer": true, 2200 | "dependencies": { 2201 | "ansi-regex": "^5.0.1" 2202 | }, 2203 | "engines": { 2204 | "node": ">=8" 2205 | } 2206 | }, 2207 | "node_modules/strip-json-comments": { 2208 | "version": "3.1.1", 2209 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2210 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2211 | "dev": true, 2212 | "license": "MIT", 2213 | "peer": true, 2214 | "engines": { 2215 | "node": ">=8" 2216 | }, 2217 | "funding": { 2218 | "url": "https://github.com/sponsors/sindresorhus" 2219 | } 2220 | }, 2221 | "node_modules/style-mod": { 2222 | "version": "4.1.2", 2223 | "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", 2224 | "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==", 2225 | "dev": true, 2226 | "license": "MIT", 2227 | "peer": true 2228 | }, 2229 | "node_modules/supports-color": { 2230 | "version": "7.2.0", 2231 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2232 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2233 | "dev": true, 2234 | "license": "MIT", 2235 | "peer": true, 2236 | "dependencies": { 2237 | "has-flag": "^4.0.0" 2238 | }, 2239 | "engines": { 2240 | "node": ">=8" 2241 | } 2242 | }, 2243 | "node_modules/text-table": { 2244 | "version": "0.2.0", 2245 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2246 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 2247 | "dev": true, 2248 | "license": "MIT", 2249 | "peer": true 2250 | }, 2251 | "node_modules/to-regex-range": { 2252 | "version": "5.0.1", 2253 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2254 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2255 | "dev": true, 2256 | "license": "MIT", 2257 | "dependencies": { 2258 | "is-number": "^7.0.0" 2259 | }, 2260 | "engines": { 2261 | "node": ">=8.0" 2262 | } 2263 | }, 2264 | "node_modules/tslib": { 2265 | "version": "2.4.0", 2266 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", 2267 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", 2268 | "dev": true, 2269 | "license": "0BSD" 2270 | }, 2271 | "node_modules/tsutils": { 2272 | "version": "3.21.0", 2273 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", 2274 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 2275 | "dev": true, 2276 | "license": "MIT", 2277 | "dependencies": { 2278 | "tslib": "^1.8.1" 2279 | }, 2280 | "engines": { 2281 | "node": ">= 6" 2282 | }, 2283 | "peerDependencies": { 2284 | "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" 2285 | } 2286 | }, 2287 | "node_modules/tsutils/node_modules/tslib": { 2288 | "version": "1.14.1", 2289 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 2290 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 2291 | "dev": true, 2292 | "license": "0BSD" 2293 | }, 2294 | "node_modules/type-check": { 2295 | "version": "0.4.0", 2296 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2297 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2298 | "dev": true, 2299 | "license": "MIT", 2300 | "peer": true, 2301 | "dependencies": { 2302 | "prelude-ls": "^1.2.1" 2303 | }, 2304 | "engines": { 2305 | "node": ">= 0.8.0" 2306 | } 2307 | }, 2308 | "node_modules/type-fest": { 2309 | "version": "0.20.2", 2310 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2311 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2312 | "dev": true, 2313 | "license": "(MIT OR CC0-1.0)", 2314 | "peer": true, 2315 | "engines": { 2316 | "node": ">=10" 2317 | }, 2318 | "funding": { 2319 | "url": "https://github.com/sponsors/sindresorhus" 2320 | } 2321 | }, 2322 | "node_modules/typescript": { 2323 | "version": "4.7.4", 2324 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", 2325 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", 2326 | "dev": true, 2327 | "license": "Apache-2.0", 2328 | "bin": { 2329 | "tsc": "bin/tsc", 2330 | "tsserver": "bin/tsserver" 2331 | }, 2332 | "engines": { 2333 | "node": ">=4.2.0" 2334 | } 2335 | }, 2336 | "node_modules/uri-js": { 2337 | "version": "4.4.1", 2338 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2339 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2340 | "dev": true, 2341 | "license": "BSD-2-Clause", 2342 | "peer": true, 2343 | "dependencies": { 2344 | "punycode": "^2.1.0" 2345 | } 2346 | }, 2347 | "node_modules/w3c-keyname": { 2348 | "version": "2.2.8", 2349 | "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", 2350 | "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", 2351 | "dev": true, 2352 | "license": "MIT", 2353 | "peer": true 2354 | }, 2355 | "node_modules/which": { 2356 | "version": "2.0.2", 2357 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2358 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2359 | "dev": true, 2360 | "license": "ISC", 2361 | "peer": true, 2362 | "dependencies": { 2363 | "isexe": "^2.0.0" 2364 | }, 2365 | "bin": { 2366 | "node-which": "bin/node-which" 2367 | }, 2368 | "engines": { 2369 | "node": ">= 8" 2370 | } 2371 | }, 2372 | "node_modules/word-wrap": { 2373 | "version": "1.2.5", 2374 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 2375 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 2376 | "dev": true, 2377 | "license": "MIT", 2378 | "peer": true, 2379 | "engines": { 2380 | "node": ">=0.10.0" 2381 | } 2382 | }, 2383 | "node_modules/wrappy": { 2384 | "version": "1.0.2", 2385 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2386 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2387 | "dev": true, 2388 | "license": "ISC", 2389 | "peer": true 2390 | }, 2391 | "node_modules/yocto-queue": { 2392 | "version": "0.1.0", 2393 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2394 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2395 | "dev": true, 2396 | "license": "MIT", 2397 | "peer": true, 2398 | "engines": { 2399 | "node": ">=10" 2400 | }, 2401 | "funding": { 2402 | "url": "https://github.com/sponsors/sindresorhus" 2403 | } 2404 | } 2405 | } 2406 | } 2407 | --------------------------------------------------------------------------------