diff --git a/build.js b/build.js index d1481ab..ad7671f 100644 --- a/build.js +++ b/build.js @@ -1,5 +1,7 @@ const fs = require('fs').promises; const path = require('path'); +const esbuild = require('esbuild'); +const { execSync } = require('child_process'); /** * Parse YAML front matter from markdown content @@ -174,6 +176,54 @@ async function updateGraphWithBlogNodes(posts, graphPath) { console.log(`✓ Added ${blogNodes.length} blog node(s) to graph`); } +/** + * Bundle all JavaScript files into a single bundle.js using esbuild + */ +async function bundleJavaScript() { + const entryPoint = path.join(__dirname, 'website', 'scripts', 'main.js'); + const outfile = path.join(__dirname, 'build', 'scripts', 'bundle.js'); + const scriptsDir = path.join(__dirname, 'build', 'scripts'); + + try { + await esbuild.build({ + entryPoints: [entryPoint], + bundle: true, + outfile: outfile, + format: 'esm', + platform: 'browser', + target: 'es2022', + minify: true, + sourcemap: false, + }); + + console.log('✓ Bundled JavaScript with esbuild'); + + // Remove all individual JS files except bundle.js + async function removeJsFiles(dir) { + const items = await fs.readdir(dir); + + for (const item of items) { + const fullPath = path.join(dir, item); + const stats = await fs.stat(fullPath); + + if (stats.isDirectory()) { + await removeJsFiles(fullPath); + // Remove empty directory + await fs.rmdir(fullPath); + } else if (item.endsWith('.js') && item !== 'bundle.js') { + await fs.unlink(fullPath); + } + } + } + + await removeJsFiles(scriptsDir); + console.log('✓ Removed individual JS files'); + } catch (error) { + console.error('✗ JavaScript bundling failed:', error); + throw error; + } +} + // Copy files recursively from website to build async function copyWebsiteFiles() { const websiteDir = path.join(__dirname, 'website'); @@ -215,10 +265,71 @@ async function copyWebsiteFiles() { } } +/** + * Minify CSS files in the build directory + */ +async function minifyCSS() { + const stylesDir = path.join(__dirname, 'build', 'styles'); + + try { + const files = await fs.readdir(stylesDir); + const cssFiles = files.filter(f => f.endsWith('.css')); + + for (const file of cssFiles) { + const filePath = path.join(stylesDir, file); + const outputPath = filePath; + + execSync(`npx cleancss -o "${outputPath}" "${filePath}"`, { + cwd: __dirname, + stdio: 'pipe' + }); + } + + console.log(`✓ Minified ${cssFiles.length} CSS file(s)`); + } catch (error) { + console.error('✗ CSS minification failed:', error); + throw error; + } +} + +/** + * Update HTML files to use bundled JavaScript + */ +async function updateHtmlForBundle() { + const htmlPath = path.join(__dirname, 'build', 'index.html'); + + try { + let html = await fs.readFile(htmlPath, 'utf-8'); + + // Replace module script tag with bundle script tag (keep type="module" for esm format) + html = html.replace( + /' + ); + + await fs.writeFile(htmlPath, html); + console.log('✓ Updated HTML to use bundle.js'); + } catch (error) { + console.error('✗ Failed to update HTML:', error); + throw error; + } +} + // Run the build async function build() { await processBlogPosts(); await copyWebsiteFiles(); + await bundleJavaScript(); + await minifyCSS(); + await updateHtmlForBundle(); + + // Report final sizes + console.log('\n=== Build Summary ==='); + const bundleStats = await fs.stat(path.join(__dirname, 'build', 'scripts', 'bundle.js')); + const cssStats = await fs.stat(path.join(__dirname, 'build', 'styles', 'main.css')); + console.log(`bundle.js: ${(bundleStats.size / 1024).toFixed(2)} KB`); + console.log(`main.css: ${(cssStats.size / 1024).toFixed(2)} KB`); + console.log('=====================\n'); } build(); diff --git a/package-lock.json b/package-lock.json index 55471fa..d9b2f27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,977 @@ "dependencies": { "@litruv/mxjs-lite": "^1.0.1", "jimp": "^1.6.0" + }, + "devDependencies": { + "@milkdown/crepe": "^7.20.0", + "clean-css-cli": "^5.6.3", + "esbuild": "^0.28.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.2", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.2.tgz", + "integrity": "sha512-G5FPkgIiLjOgZMjqVjvuKQ1rGPtHogLldJr33eFJdVLtmwY+giGrlv/ewljLz6b9BSQLkjxuwBc6g6omDM+YxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-angular": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@codemirror/lang-angular/-/lang-angular-0.1.4.tgz", + "integrity": "sha512-oap+gsltb/fzdlTQWD6BFF4bSLKcDnlxDsLdePiJpCVNKWXSTAbiiQeYI3UmES+BLAdkmIC1WjyztC1pi/bX4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.1.2", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.3" + } + }, + "node_modules/@codemirror/lang-cpp": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.3.tgz", + "integrity": "sha512-URM26M3vunFFn9/sm6rzqrBzDgfWuDixp85uTY49wKudToc2jTHUrKIGGKs+QWND+YLofNNZpxcNGRynFJfvgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/cpp": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-go": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz", + "integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/go": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.11", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz", + "integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-java": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-java/-/lang-java-6.0.2.tgz", + "integrity": "sha512-m5Nt1mQ/cznJY7tMfQTJchmrjdjQ71IDs+55d1GAa8DGaB8JXWsVCkVT284C3RTASaY43YknrK2X3hPO/J3MOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/java": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-jinja": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-jinja/-/lang-jinja-6.0.1.tgz", + "integrity": "sha512-P5kyHLObzjtbGj16h+hyvZTxJhSjBEeSx4wMjbnAf3b0uwTy2+F0zGjMZL4PQOm/mh2eGZ5xUDVZXgwP783Nsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.4.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-less": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-less/-/lang-less-6.0.2.tgz", + "integrity": "sha512-EYdQTG22V+KUUk8Qq582g7FMnCZeEHsyuOJisHRft/mQ+ZSZ2w51NupvDUHiqtsOy7It5cHLPGfHQLpMh9bqpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/lang-css": "^6.2.0", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-liquid": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-liquid/-/lang-liquid-6.3.2.tgz", + "integrity": "sha512-6PDVU3ZnfeYyz1at1E/ttorErZvZFXXt1OPhtfe1EZJ2V2iDFa0CwPqPgG5F7NXN0yONGoBogKmFAafKTqlwIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.1" + } + }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz", + "integrity": "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-php": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.2.tgz", + "integrity": "sha512-ZKy2v1n8Fc8oEXj0Th0PUMXzQJ0AIR6TaZU+PbDHExFwdu+guzOA4jmCHS1Nz4vbFezwD7LyBdDnddSJeScMCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/php": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-python": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz", + "integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.3.2", + "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/python": "^1.1.4" + } + }, + "node_modules/@codemirror/lang-rust": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz", + "integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/rust": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sass": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sass/-/lang-sass-6.0.2.tgz", + "integrity": "sha512-l/bdzIABvnTo1nzdY6U+kPAC51czYQcOErfzQ9zSm9D8GmNPD0WTW8st/CJwBTPLO8jlrbyvlSEcN20dc4iL0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/lang-css": "^6.2.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/sass": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-sql": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz", + "integrity": "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-vue": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz", + "integrity": "sha512-QSKdtYTDRhEHCfo5zOShzxCmqKJvgGrZwDQSdbvCRJ5pRLWBS7pD/8e/tH44aVQT6FKm0t6RVNoSUWHOI5vNug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.1.2", + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.1" + } + }, + "node_modules/@codemirror/lang-wast": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-wast/-/lang-wast-6.0.2.tgz", + "integrity": "sha512-Imi2KTpVGm7TKuUkqyJ5NRmeFWF7aMpNiwHnLQe0x9kmrxElndyH0K6H/gXtWwY6UshMRAhpENsgfpSwsgmC6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-yaml": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.3.tgz", + "integrity": "sha512-AZ8DJBuXGVHybpBQhmZtgew5//4hv3tdkXnr3vDmOUMJRuB6vn/uuwtmTOTlqEaQFg3hQSVeA90NmvIQyUV6FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.2.0", + "@lezer/lr": "^1.0.0", + "@lezer/yaml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/language-data": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/language-data/-/language-data-6.5.2.tgz", + "integrity": "sha512-CPkWBKrNS8stYbEU5kwBwTf3JB1kghlbh4FSAwzGW2TEscdeHHH4FGysREW86Mqnj3Qn09s0/6Ea/TutmoTobg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/lang-angular": "^0.1.0", + "@codemirror/lang-cpp": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-go": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-java": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/lang-jinja": "^6.0.0", + "@codemirror/lang-json": "^6.0.0", + "@codemirror/lang-less": "^6.0.0", + "@codemirror/lang-liquid": "^6.0.0", + "@codemirror/lang-markdown": "^6.0.0", + "@codemirror/lang-php": "^6.0.0", + "@codemirror/lang-python": "^6.0.0", + "@codemirror/lang-rust": "^6.0.0", + "@codemirror/lang-sass": "^6.0.0", + "@codemirror/lang-sql": "^6.0.0", + "@codemirror/lang-vue": "^0.1.1", + "@codemirror/lang-wast": "^6.0.0", + "@codemirror/lang-xml": "^6.0.0", + "@codemirror/lang-yaml": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/legacy-modes": "^6.4.0" + } + }, + "node_modules/@codemirror/legacy-modes": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.2.tgz", + "integrity": "sha512-/jJbwSTazlQEDOQw2FJ8LEEKVS72pU0lx6oM54kGpL8t/NJ2Jda3CZ4pcltiKTdqYSRk3ug1B3pil1gsjA6+8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.6.tgz", + "integrity": "sha512-6Kp7r6XfCi/D/5sdXieMfg9pJU1bUEx96WITuLU6ESaKizCz0QHFMjY/TaFSbigDdEAIgi93itLBIUETP4oK+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.0.tgz", + "integrity": "sha512-ZvGm99wc/s2cITtMT15LFdn8aH/aS+V+DqyGq/N5ZlV5vWtH+nILvC2nw0zX7ByNoHHDZ2IxxdW38O0tc5nVHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", + "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.42.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.42.1.tgz", + "integrity": "sha512-ToN3oFc0nsxNUYVF5P0ztLgbC4UPPjPtA9aKYhkOKQaZASpOUo6ISXyQLP66ctVwlDc+j6Jv0uK5IFALkiXztg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", + "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", + "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", + "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", + "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", + "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", + "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", + "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", + "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", + "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", + "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", + "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", + "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", + "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", + "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", + "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", + "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", + "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", + "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", + "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", + "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", + "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", + "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", + "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", + "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", + "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", + "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "dev": true, + "license": "MIT" + }, "node_modules/@jimp/core": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz", @@ -425,24 +1394,767 @@ "node": ">=18" } }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.5.tgz", + "integrity": "sha512-DIhSXmYtJKLehrjzDFN+2cPt547ySQ41nA8yqcDf/GxMc+YM736xqltFkvADL2M0VebU5I+3+4ks2Vv+Kyq3Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/css": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.3.tgz", + "integrity": "sha512-RzBo8r+/6QJeow7aPHIpGVIH59xTcJXp399820gZoMo9noQDRVpJLheIBUicYwKcsbOYoBRoLZlf2720dG/4Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/go": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.1.tgz", + "integrity": "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/java": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@lezer/java/-/java-1.1.3.tgz", + "integrity": "sha512-yHquUfujwg6Yu4Fd1GNHCvidIvJwi/1Xu2DaKl/pfWIA2c1oXkVvawH3NyXhCaFx4OdlYBVX5wvz2f7Aoa/4Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.6.3.tgz", + "integrity": "sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/php": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.5.tgz", + "integrity": "sha512-W7asp9DhM6q0W6DYNwIkLSKOvxlXRrif+UXBMxzsJUuqmhE7oVU+gS3THO4S/Puh7Xzgm858UNaFi6dxTP8dJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" + } + }, + "node_modules/@lezer/python": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.18.tgz", + "integrity": "sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/rust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz", + "integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/sass": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lezer/sass/-/sass-1.1.0.tgz", + "integrity": "sha512-3mMGdCTUZ/84ArHOuXWQr37pnf7f+Nw9ycPUeKX+wu19b7pSMcZGLbaXwvD2APMBDOGxPmpK/O6S1v1EvLoqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/yaml": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.4.tgz", + "integrity": "sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.4.0" + } + }, "node_modules/@litruv/mxjs-lite": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@litruv/mxjs-lite/-/mxjs-lite-1.1.2.tgz", "integrity": "sha512-kEL/MZdezhibPNQFiQWUWRBPRxfjWTUNnDNpqxmDyLFFG8iLXMQy2mJAMYPBgxw6D+NXARiMcABp5pEWezfC9w==", "license": "MIT" }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@milkdown/components": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/components/-/components-7.20.0.tgz", + "integrity": "sha512-Qn91/oZugGjf17ARE51nbEsH4YklZQaomRSsfxOAtIcwGEJe5osq+zhhKGtgAYFfUb6rU3W86Pe4XDlXN6vFjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.5.1", + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/exception": "7.20.0", + "@milkdown/plugin-tooltip": "7.20.0", + "@milkdown/preset-commonmark": "7.20.0", + "@milkdown/preset-gfm": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/transformer": "7.20.0", + "@milkdown/utils": "7.20.0", + "@types/lodash-es": "^4.17.12", + "clsx": "^2.0.0", + "dompurify": "^3.2.5", + "lodash-es": "^4.17.21", + "nanoid": "^5.0.9", + "unist-util-visit": "^5.0.0", + "vue": "^3.5.20" + }, + "peerDependencies": { + "@codemirror/language": "^6", + "@codemirror/state": "^6", + "@codemirror/view": "^6" + } + }, + "node_modules/@milkdown/core": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/core/-/core-7.20.0.tgz", + "integrity": "sha512-X9LaUcIR4Y2oiY2J5tslavlPVOwIB3X8/9z1bOeBjlIPtr+urbkY7YEX86EeLV9LyRQ3+t+jXaLMCIjW1wsV6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/ctx": "7.20.0", + "@milkdown/exception": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/transformer": "7.20.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.3" + } + }, + "node_modules/@milkdown/crepe": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/crepe/-/crepe-7.20.0.tgz", + "integrity": "sha512-KT+oFF6Q7mI41z01c9v/wUUCyQ2f908TgOsa6mwi25yuxnxQxISZFCjRvlh0sc9p9D3CrMeuJWGCN6DialQdig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/commands": "^6.2.4", + "@codemirror/language": "^6.10.1", + "@codemirror/language-data": "^6.3.1", + "@codemirror/state": "^6.4.1", + "@codemirror/theme-one-dark": "^6.1.2", + "@codemirror/view": "^6.16.0", + "@milkdown/kit": "7.20.0", + "@types/lodash-es": "^4.17.12", + "clsx": "^2.0.0", + "codemirror": "^6.0.1", + "katex": "^0.16.0", + "lodash-es": "^4.17.21", + "prosemirror-virtual-cursor": "^0.4.2", + "remark-math": "^6.0.0", + "unist-util-visit": "^5.0.0", + "vue": "^3.5.20" + } + }, + "node_modules/@milkdown/ctx": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/ctx/-/ctx-7.20.0.tgz", + "integrity": "sha512-LUK4xdsUngY2xCCvPTyHPifjAknJ5rE6VBjgsP+LySIUKeFUrhqzo/zz2vaOODKzm3DBMIhpZAoW3MAqxoMGIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/exception": "7.20.0" + } + }, + "node_modules/@milkdown/exception": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/exception/-/exception-7.20.0.tgz", + "integrity": "sha512-u8EL7rbqgrWrPpkDhrxUYXauw2DO52JUQmuokrUZvqezmflo7pgIDCr+Rk6AQslzB4Xw+n9eYik5rXX3RXC7Qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@milkdown/kit": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/kit/-/kit-7.20.0.tgz", + "integrity": "sha512-X74KMa0tcDAAMOE9aFtBRN+RCdD/HMXor5YN18e7d0pe4a65MGFklUGlcg1U6zEfeMMYeC3msNvMKLMwk3O5RA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/components": "7.20.0", + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/plugin-block": "7.20.0", + "@milkdown/plugin-clipboard": "7.20.0", + "@milkdown/plugin-cursor": "7.20.0", + "@milkdown/plugin-history": "7.20.0", + "@milkdown/plugin-indent": "7.20.0", + "@milkdown/plugin-listener": "7.20.0", + "@milkdown/plugin-slash": "7.20.0", + "@milkdown/plugin-tooltip": "7.20.0", + "@milkdown/plugin-trailing": "7.20.0", + "@milkdown/plugin-upload": "7.20.0", + "@milkdown/preset-commonmark": "7.20.0", + "@milkdown/preset-gfm": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/transformer": "7.20.0", + "@milkdown/utils": "7.20.0" + } + }, + "node_modules/@milkdown/plugin-block": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-block/-/plugin-block-7.20.0.tgz", + "integrity": "sha512-jIXfzJ8Zje+6+9ZwQuVmNeYE8KfzqL9YJ/YdMvWQIEiKhy2x9pZMAkkufgmUlq1aouxOV+gk5fX+ovxzEzfSrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.5.1", + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0", + "@types/lodash-es": "^4.17.12", + "lodash-es": "^4.17.21" + } + }, + "node_modules/@milkdown/plugin-clipboard": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-clipboard/-/plugin-clipboard-7.20.0.tgz", + "integrity": "sha512-PyokNvwgWcO6/I/0LxDRnATpnxvs5upFRlp6eO8PhjwBFZftCIU6D15Wg4JAxwW7Y0NyTWfViWjc9TwiBd6KOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0" + } + }, + "node_modules/@milkdown/plugin-cursor": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-cursor/-/plugin-cursor-7.20.0.tgz", + "integrity": "sha512-goCPwUARBzGV6Hvnr3P57Bj5TnyFjYIfDFLvgWTIlsm/dR2Wr4Syy4HDOtaKO9YL/VtZ8gtiZVgeo0vhc4CzMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0", + "prosemirror-drop-indicator": "^0.1.0" + } + }, + "node_modules/@milkdown/plugin-history": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-history/-/plugin-history-7.20.0.tgz", + "integrity": "sha512-lqOYQBrxKj4px/i0Cav3zRkCArwnkv8o7fGMh3NtnUXMLSE7/xojK5GFPS4EaS/UKK7/+i1oV2+HRA6+6Ezy7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0" + } + }, + "node_modules/@milkdown/plugin-indent": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-indent/-/plugin-indent-7.20.0.tgz", + "integrity": "sha512-KfdIztQMuHv4Rx1JmSQe2vooN4+Zm7MhjQkNolGyiI7BPZbu855hVIC/s96x3Dk04tkbb+M/i9MJhxCazxfd6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0" + } + }, + "node_modules/@milkdown/plugin-listener": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-listener/-/plugin-listener-7.20.0.tgz", + "integrity": "sha512-Sj+B63JfM3NVVS3uGXTPkoz8xx8MQYrR28pI9AaqX5q60tvCvOJw9E1ODvSsBEjeqnN4kablDthIugLlBhOlwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@types/lodash-es": "^4.17.12", + "lodash-es": "^4.17.21" + } + }, + "node_modules/@milkdown/plugin-slash": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-slash/-/plugin-slash-7.20.0.tgz", + "integrity": "sha512-Qm3/ZxkGYd5XN+J/X91lGGu7SBzuQBOTOLjuJdg4qDBZmdEHlGojB+5BhCSAMB3WGyCpQQGbSqKOelUrXtj68w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.5.1", + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0", + "@types/lodash-es": "^4.17.12", + "lodash-es": "^4.17.21" + } + }, + "node_modules/@milkdown/plugin-tooltip": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-tooltip/-/plugin-tooltip-7.20.0.tgz", + "integrity": "sha512-BVaXorpmA6ZAS3+xv0rgrtjV1h2K39G5Z9Wun4RxT1YXJTTbzIuFQ3hwBAGLjLMwTsosp7YhRLaMJJAC0jEY5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.5.1", + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0", + "@types/lodash-es": "^4.17.12", + "lodash-es": "^4.17.21" + } + }, + "node_modules/@milkdown/plugin-trailing": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-trailing/-/plugin-trailing-7.20.0.tgz", + "integrity": "sha512-AxDeMSAZfj0Er7RYLvLRf6FKdQtLVmotxML6Se6zgqIa++bFeIXCU22/FC+9r/6d1eUtraTva9ez5K2qPy8qig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/ctx": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0" + } + }, + "node_modules/@milkdown/plugin-upload": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/plugin-upload/-/plugin-upload-7.20.0.tgz", + "integrity": "sha512-g3UQrD2zfpm86r3BcBDfOdEAyQHhay1nf5wUQgNf4zn6IgRttfEF8tosQsL1B/WBnZB05hH5scLWo4DR2bFhUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/exception": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/utils": "7.20.0" + } + }, + "node_modules/@milkdown/preset-commonmark": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/preset-commonmark/-/preset-commonmark-7.20.0.tgz", + "integrity": "sha512-+mPcONXfdjaXdx8JMxDIOT3PWHfy5vewK8iY8j8bUiYD8Iw7YfyWTUh9JHOf4vmOpiKGCJd7+iz7e93u95bQRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/exception": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/transformer": "7.20.0", + "@milkdown/utils": "7.20.0", + "remark-inline-links": "^7.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@milkdown/preset-gfm": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/preset-gfm/-/preset-gfm-7.20.0.tgz", + "integrity": "sha512-ulErTWDqrGYYqto4kQO9dPTMRp+q44pdRTPW4MTeiSO7eJ6JIBUKSqtCm1zf7MX6nZPaPhuscmg5CU2moXOwxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/exception": "7.20.0", + "@milkdown/preset-commonmark": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/transformer": "7.20.0", + "@milkdown/utils": "7.20.0", + "prosemirror-safari-ime-span": "^1.0.1", + "remark-gfm": "^4.0.1" + } + }, + "node_modules/@milkdown/prose": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/prose/-/prose-7.20.0.tgz", + "integrity": "sha512-Qe6jmKcXsjOfpk8duDFdkLCEo5044L8HSyKVn7ewAe7XJJPUM6bPQaP130UAznq75/+TiKxFCzurcrBO3LzNRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/exception": "7.20.0", + "prosemirror-changeset": "^2.3.1", + "prosemirror-commands": "^1.7.1", + "prosemirror-dropcursor": "^1.8.2", + "prosemirror-gapcursor": "^1.4.0", + "prosemirror-history": "^1.5.0", + "prosemirror-inputrules": "^1.5.1", + "prosemirror-keymap": "^1.2.3", + "prosemirror-model": "^1.25.4", + "prosemirror-schema-list": "^1.5.1", + "prosemirror-state": "^1.4.4", + "prosemirror-tables": "^1.8.1", + "prosemirror-transform": "^1.10.5", + "prosemirror-view": "^1.41.3" + } + }, + "node_modules/@milkdown/transformer": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/transformer/-/transformer-7.20.0.tgz", + "integrity": "sha512-h7KGFr1o5AYwc+hEfnA3Dldo4jRrYOB/7KExaqelcjUz++KYI/9LXMOsV7CpgjtLI3Xtf2IIRTZND1+p2nsOaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/exception": "7.20.0", + "@milkdown/prose": "7.20.0", + "remark": "^15.0.1", + "unified": "^11.0.3" + } + }, + "node_modules/@milkdown/utils": { + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@milkdown/utils/-/utils-7.20.0.tgz", + "integrity": "sha512-ciEhtLKhIW/Kaz/NRE5DUXVoMCdenn7S4mClrO7sZ/nXtmObnk3okJzSDnamQoDOcLOIbpOu1V3E1Btkvc5x9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@milkdown/core": "7.20.0", + "@milkdown/ctx": "7.20.0", + "@milkdown/exception": "7.20.0", + "@milkdown/prose": "7.20.0", + "@milkdown/transformer": "7.20.0", + "nanoid": "^5.0.9" + } + }, + "node_modules/@ocavue/utils": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@ocavue/utils/-/utils-1.6.0.tgz", + "integrity": "sha512-8W3q1hxx9qFdrYgPtbElllG/tqYkO/dMhlRUiqasO0SuDFTj78azSQjhIrBTFWxlBPPsSZN6zXYHmb3RwN2Jtg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ocavue" + } + }, "node_modules/@tokenizer/token": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", "license": "MIT" }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/katex": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.8.tgz", + "integrity": "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "16.9.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz", + "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@vue/shared": "3.5.34", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", + "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.34", + "@vue/shared": "3.5.34" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", + "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.3", + "@vue/compiler-core": "3.5.34", + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.14", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", + "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.34", + "@vue/shared": "3.5.34" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz", + "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.34" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz", + "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.34", + "@vue/shared": "3.5.34" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", + "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.34", + "@vue/runtime-core": "3.5.34", + "@vue/shared": "3.5.34", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz", + "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.34", + "@vue/shared": "3.5.34" + }, + "peerDependencies": { + "vue": "3.5.34" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz", + "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", + "dev": true, + "license": "MIT" + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -461,6 +2173,20 @@ "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", "license": "MIT" }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/await-to-js": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", @@ -470,6 +2196,24 @@ "node": ">=6.0.0" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -490,12 +2234,49 @@ ], "license": "MIT" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bmp-ts": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", "license": "MIT" }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -520,6 +2301,283 @@ "ieee754": "^1.2.1" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css-cli": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/clean-css-cli/-/clean-css-cli-5.6.3.tgz", + "integrity": "sha512-MUAta8pEqA/d2DKQwtZU5nm0Og8TCyAglOx3GlWwjhGdKBwY4kVF6E5M6LU/jmmuswv+HbYqG/dKKkq5p1dD0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.2", + "clean-css": "^5.3.3", + "commander": "7.x", + "glob": "^7.1.6" + }, + "bin": { + "cleancss": "bin/cleancss" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/codemirror": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dompurify": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", + "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", + "dev": true, + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", + "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.0", + "@esbuild/android-arm": "0.28.0", + "@esbuild/android-arm64": "0.28.0", + "@esbuild/android-x64": "0.28.0", + "@esbuild/darwin-arm64": "0.28.0", + "@esbuild/darwin-x64": "0.28.0", + "@esbuild/freebsd-arm64": "0.28.0", + "@esbuild/freebsd-x64": "0.28.0", + "@esbuild/linux-arm": "0.28.0", + "@esbuild/linux-arm64": "0.28.0", + "@esbuild/linux-ia32": "0.28.0", + "@esbuild/linux-loong64": "0.28.0", + "@esbuild/linux-mips64el": "0.28.0", + "@esbuild/linux-ppc64": "0.28.0", + "@esbuild/linux-riscv64": "0.28.0", + "@esbuild/linux-s390x": "0.28.0", + "@esbuild/linux-x64": "0.28.0", + "@esbuild/netbsd-arm64": "0.28.0", + "@esbuild/netbsd-x64": "0.28.0", + "@esbuild/openbsd-arm64": "0.28.0", + "@esbuild/openbsd-x64": "0.28.0", + "@esbuild/openharmony-arm64": "0.28.0", + "@esbuild/sunos-x64": "0.28.0", + "@esbuild/win32-arm64": "0.28.0", + "@esbuild/win32-ia32": "0.28.0", + "@esbuild/win32-x64": "0.28.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", @@ -543,6 +2601,13 @@ "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, "node_modules/file-type": { "version": "16.5.4", "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", @@ -560,6 +2625,41 @@ "url": "https://github.com/sindresorhus/file-type?sponsor=1" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/gifwrap": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", @@ -570,6 +2670,41 @@ "omggif": "^1.0.10" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -599,6 +2734,84 @@ "@types/node": "16.9.1" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jimp": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz", @@ -643,6 +2856,919 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "license": "BSD-3-Clause" }, + "node_modules/katex": { + "version": "0.16.45", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.45.tgz", + "integrity": "sha512-pQpZbdBu7wCTmQUh7ufPmLr0pFoObnGUoL/yhtwJDgmmQpbkg/0HSVti25Fu4rmd1oCR6NGWe9vqTWuWv3GcNA==", + "dev": true, + "funding": [ + "https://opencollective.com/katex", + "https://github.com/sponsors/katex" + ], + "license": "MIT", + "dependencies": { + "commander": "^8.3.0" + }, + "bin": { + "katex": "cli.js" + } + }, + "node_modules/katex/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-math": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-math/-/mdast-util-math-3.0.0.tgz", + "integrity": "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "longest-streak": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.1.0", + "unist-util-remove-position": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-math": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-math/-/micromark-extension-math-3.1.0.tgz", + "integrity": "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/katex": "^0.16.0", + "devlop": "^1.0.0", + "katex": "^0.16.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/mime": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", @@ -655,12 +3781,78 @@ "node": ">=10.0.0" } }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz", + "integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/omggif": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==", "license": "MIT" }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "dev": true, + "license": "MIT" + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -689,6 +3881,16 @@ "xml2js": "^0.5.0" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/peek-readable": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", @@ -702,6 +3904,26 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pixelmatch": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", @@ -732,6 +3954,54 @@ "node": ">=14.19.0" } }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -741,6 +4011,214 @@ "node": ">= 0.6.0" } }, + "node_modules/prosemirror-changeset": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.1.tgz", + "integrity": "sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-drop-indicator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/prosemirror-drop-indicator/-/prosemirror-drop-indicator-0.1.3.tgz", + "integrity": "sha512-fJV6G2tHIVXZLUuc60fS9ly1/GuGOlAZUm67S1El+kGFUYh27Hyv6hcGx3rrJ+Q/JZL5jnyAibIZYYWpPqE45g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ocavue/utils": "^1.0.0", + "prosemirror-model": "^1.25.4", + "prosemirror-state": "^1.4.4", + "prosemirror-view": "^1.41.3" + }, + "funding": { + "url": "https://github.com/sponsors/ocavue" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz", + "integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", + "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz", + "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.4", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz", + "integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-safari-ime-span": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/prosemirror-safari-ime-span/-/prosemirror-safari-ime-span-1.0.2.tgz", + "integrity": "sha512-QJqD8s1zE/CuK56kDsUhndh5hiHh/gFnAuPOA9ytva2s85/ZEt2tNWeALTJN48DtWghSKOmiBsvVn2OlnJ5H2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.4.3", + "prosemirror-view": "^1.33.8" + }, + "funding": { + "url": "https://github.com/sponsors/ocavue" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", + "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz", + "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.2.3", + "prosemirror-model": "^1.25.4", + "prosemirror-state": "^1.4.4", + "prosemirror-transform": "^1.10.5", + "prosemirror-view": "^1.41.4" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.0.tgz", + "integrity": "sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.41.8", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.8.tgz", + "integrity": "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.20.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, + "node_modules/prosemirror-virtual-cursor": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/prosemirror-virtual-cursor/-/prosemirror-virtual-cursor-0.4.2.tgz", + "integrity": "sha512-pUMKnIuOhhnMcgIJUjhIQTVJruBEGxfMBVQSrK0g2qhGPDm1i12KdsVaFw15dYk+29tZcxjMeR7P5VDKwmbwJg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ocavue" + }, + "peerDependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + }, + "peerDependenciesMeta": { + "prosemirror-model": { + "optional": true + }, + "prosemirror-state": { + "optional": true + }, + "prosemirror-view": { + "optional": true + } + } + }, "node_modules/readable-stream": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", @@ -773,6 +4251,128 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/remark": { + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", + "integrity": "sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-inline-links": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/remark-inline-links/-/remark-inline-links-7.0.0.tgz", + "integrity": "sha512-4uj1pPM+F495ySZhTIB6ay2oSkTsKgmYaKk/q5HIdhX2fuyLEegpjWa0VdJRJ01sgOqAFo7MBKdDUejIYBMVMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-definitions": "^6.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-math": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/remark-math/-/remark-math-6.0.0.tgz", + "integrity": "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-math": "^3.0.0", + "micromark-extension-math": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -811,6 +4411,26 @@ "node": ">=20.12.2" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -837,12 +4457,32 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "dev": true, + "license": "MIT" + }, "node_modules/tinycolor2": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", "license": "MIT" }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/token-types": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", @@ -860,6 +4500,111 @@ "url": "https://github.com/sponsors/Borewit" } }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/utif2": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", @@ -869,6 +4614,72 @@ "pako": "^1.0.11" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vue": { + "version": "3.5.34", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz", + "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.34", + "@vue/compiler-sfc": "3.5.34", + "@vue/runtime-dom": "3.5.34", + "@vue/server-renderer": "3.5.34", + "@vue/shared": "3.5.34" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, "node_modules/xml-parse-from-string": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", @@ -905,6 +4716,17 @@ "funding": { "url": "https://github.com/sponsors/colinhacks" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index 231bd9e..32c36a3 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.html", "scripts": { "start": "python3 -m http.server 8000", - "start-alt": "python -m SimpleHTTPServer 8000" + "start-alt": "python -m SimpleHTTPServer 8000", + "blog-editor": "node tools/blog-editor.js" }, "keywords": [ "terminal", @@ -27,5 +28,10 @@ "type": "git", "url": "https://github.com/litruv/lit.ruv.wtf" }, - "homepage": "https://lit.ruv.wtf" + "homepage": "https://lit.ruv.wtf", + "devDependencies": { + "@milkdown/crepe": "^7.20.0", + "clean-css-cli": "^5.6.3", + "esbuild": "^0.28.0" + } } diff --git a/tools/blogeditor/.vscodeignore b/tools/blogeditor/.vscodeignore new file mode 100644 index 0000000..7b335b1 --- /dev/null +++ b/tools/blogeditor/.vscodeignore @@ -0,0 +1,4 @@ +# Exclude source/build artifacts — keep only what's needed in the VSIX +build-dist.js +*.vsix +.gitignore diff --git a/tools/blogeditor/blog-editor-0.1.11.vsix b/tools/blogeditor/blog-editor-0.1.11.vsix new file mode 100644 index 0000000..3d59106 Binary files /dev/null and b/tools/blogeditor/blog-editor-0.1.11.vsix differ diff --git a/tools/blogeditor/build-dist.js b/tools/blogeditor/build-dist.js new file mode 100644 index 0000000..8201cf5 --- /dev/null +++ b/tools/blogeditor/build-dist.js @@ -0,0 +1,83 @@ +'use strict'; + +/** + * Pre-builds the Milkdown Crepe JS + CSS bundles into .vscode/dist/ + * Run this before packaging the VSIX: node .vscode/build-dist.js + */ + +const path = require('path'); +const fs = require('fs'); + +// Resolve symlinks so node_modules lookup works even in junction'd paths +const ROOT = fs.realpathSync(__dirname); +const DIST_DIR = path.join(ROOT, 'dist'); + +/** + * Walks up from startDir to find node_modules containing a given package. + * Returns null if not found (never throws). + * @param {string} pkg + * @param {string} startDir + * @returns {string | null} + */ +function resolveFromNearestNodeModules(pkg, startDir) { + let dir = startDir; + while (true) { + const candidate = path.join(dir, 'node_modules', pkg); + if (fs.existsSync(candidate)) return candidate; + const parent = path.dirname(dir); + if (parent === dir) return null; + dir = parent; + } +} + +// Walk up from __dirname until we find node_modules with esbuild. +// Also tries process.cwd() in case the script is in a stub folder without node_modules. +const esbuildEntry = resolveFromNearestNodeModules('esbuild', ROOT) + ?? resolveFromNearestNodeModules('esbuild', process.cwd()); +if (!esbuildEntry) throw new Error('Cannot find esbuild. Run this from the project root that contains node_modules.'); +const esbuild = require(path.join(esbuildEntry, 'lib', 'main.js')); +const crepeLib = resolveFromNearestNodeModules('@milkdown/crepe', ROOT) + ?? resolveFromNearestNodeModules('@milkdown/crepe', process.cwd()); +const CREPE_DIR = path.join(crepeLib, 'lib', 'theme'); +// Also need the root for esbuild resolveDir (must contain node_modules/@milkdown) +const ROOT_DIR = path.dirname(path.dirname(esbuildEntry)); + +const FONT_LOADERS = { + '.woff2': 'dataurl', + '.woff': 'dataurl', + '.ttf': 'dataurl', + '.eot': 'dataurl', + '.svg': 'dataurl', +}; + +async function main() { + fs.mkdirSync(DIST_DIR, { recursive: true }); + + console.log('⏳ Bundling Milkdown JS…'); + const jsResult = await esbuild.build({ + stdin: { contents: `export { Crepe, CrepeFeature } from '@milkdown/crepe';`, resolveDir: ROOT_DIR, loader: 'js' }, + bundle: true, format: 'esm', platform: 'browser', target: 'es2022', minify: true, write: false, + }); + fs.writeFileSync(path.join(DIST_DIR, 'milkdown.js'), jsResult.outputFiles[0].contents); + console.log(`✓ milkdown.js ${(jsResult.outputFiles[0].contents.byteLength / 1024).toFixed(0)} KB`); + + console.log('⏳ Bundling common CSS…'); + const cssCommon = await esbuild.build({ + entryPoints: [path.join(CREPE_DIR, 'common', 'style.css')], + bundle: true, write: false, loader: FONT_LOADERS, + }); + fs.writeFileSync(path.join(DIST_DIR, 'milkdown-common.css'), cssCommon.outputFiles[0].contents); + console.log(`✓ milkdown-common.css ${(cssCommon.outputFiles[0].contents.byteLength / 1024).toFixed(0)} KB`); + + console.log('⏳ Bundling theme CSS…'); + const cssTheme = await esbuild.build({ + entryPoints: [path.join(CREPE_DIR, 'frame-dark', 'style.css')], + bundle: true, write: false, loader: FONT_LOADERS, + }); + fs.writeFileSync(path.join(DIST_DIR, 'milkdown-theme.css'), cssTheme.outputFiles[0].contents); + console.log(`✓ milkdown-theme.css ${(cssTheme.outputFiles[0].contents.byteLength / 1024).toFixed(0)} KB`); + + console.log('\n✓ dist/ ready — run: npx @vscode/vsce package --out blog-editor.vsix --no-dependencies'); +} + +main().catch(err => { console.error(err); process.exit(1); }); diff --git a/tools/blogeditor/editor.html b/tools/blogeditor/editor.html new file mode 100644 index 0000000..911316a --- /dev/null +++ b/tools/blogeditor/editor.html @@ -0,0 +1,755 @@ + + + + + + + Blog Editor + + + + + + + +
+
+
+ + + + + +
+
+
+
+ No file open +
+ +
+
+
+ + + + diff --git a/tools/blogeditor/extension.js b/tools/blogeditor/extension.js new file mode 100644 index 0000000..fe1cc7d --- /dev/null +++ b/tools/blogeditor/extension.js @@ -0,0 +1,509 @@ +'use strict'; + +const vscode = require('vscode'); +const fs = require('fs'); +const path = require('path'); +const crypto = require('crypto'); + +const EXT_DIR = __dirname; +const DIST_DIR = path.join(EXT_DIR, 'dist'); +const ROOT_DIR = path.resolve(EXT_DIR, '..'); + +/** @type {vscode.WebviewPanel | undefined} */ +let panel; + +/** @type {string | undefined} */ +let activeBlogDir; + +/** @type {string | undefined} */ +let pendingOpenSlug; + +/** @type {BlogSidebarProvider | undefined} */ +let sidebarProvider; + +/** + * @implements {vscode.TreeDataProvider} + */ +class BlogSidebarProvider { + constructor() { + this._onDidChangeTreeData = new vscode.EventEmitter(); + this.onDidChangeTreeData = this._onDidChangeTreeData.event; + } + + refresh() { + this._onDidChangeTreeData.fire(undefined); + } + + /** + * @returns {vscode.ProviderResult} + */ + getChildren() { + if (!activeBlogDir || !fs.existsSync(activeBlogDir)) { + const openItem = new vscode.TreeItem('Open Blog Editor', vscode.TreeItemCollapsibleState.None); + openItem.tooltip = 'Open the Blog Editor panel'; + openItem.command = { + command: 'blogEditor.open', + title: 'Open Blog Editor' + }; + openItem.iconPath = new vscode.ThemeIcon('edit'); + return [openItem]; + } + + const posts = fs.readdirSync(activeBlogDir) + .filter(f => f.endsWith('.md') && !f.startsWith('.')) + .map(f => { + const slug = path.basename(f, '.md'); + const meta = parseFrontmatterFromFile(path.join(activeBlogDir, f)); + return { slug, title: meta.title || slug, date: meta.date || '' }; + }) + .sort((a, b) => { + if (a.date && b.date) return b.date.localeCompare(a.date); + if (a.date) return -1; + if (b.date) return 1; + return a.slug.localeCompare(b.slug); + }); + + if (posts.length === 0) { + const empty = new vscode.TreeItem('No posts found', vscode.TreeItemCollapsibleState.None); + empty.iconPath = new vscode.ThemeIcon('circle-slash'); + return [empty]; + } + + return posts.map(({ slug, title, date }) => new BlogPostItem(slug, title, date)); + } + + /** + * @param {vscode.TreeItem} element + * @returns {vscode.TreeItem} + */ + getTreeItem(element) { + return element; + } +} + +/** + * Parses YAML-ish frontmatter from a markdown file. + * @param {string} filePath + * @returns {{ title?: string, date?: string }} + */ +function parseFrontmatterFromFile(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf-8'); + const m = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); + if (!m) return {}; + /** @type {Record} */ + const meta = {}; + for (const line of m[1].split(/\r?\n/)) { + const i = line.indexOf(':'); + if (i > 0) meta[line.slice(0, i).trim()] = line.slice(i + 1).trim().replace(/^["']|["']$/g, ''); + } + return meta; + } catch { return {}; } +} + +/** + * A tree item representing a single blog post. + * Stores the slug separately so context-menu commands can retrieve it + * even when the label displays the human-readable title. + */ +class BlogPostItem extends vscode.TreeItem { + /** + * @param {string} slug + * @param {string} title + * @param {string} date + */ + constructor(slug, title, date) { + super(title || slug, vscode.TreeItemCollapsibleState.None); + this.id = slug; + this.slug = slug; + this.description = date || ''; + this.tooltip = `${slug}.md`; + this.contextValue = 'blogPost'; + this.command = { command: 'blogEditor.openPost', title: 'Open Post', arguments: [slug] }; + this.iconPath = new vscode.ThemeIcon('file'); + } +} + +/** + * Walks up from startDir to find node_modules containing a package. + * @param {string} pkg + * @param {string} startDir + * @returns {string | null} + */ +function resolveFromNearestNodeModules(pkg, startDir) { + let dir = startDir; + while (true) { + const candidate = path.join(dir, 'node_modules', pkg); + if (fs.existsSync(candidate)) return candidate; + const parent = path.dirname(dir); + if (parent === dir) return null; + dir = parent; + } +} + +/** + * @param {vscode.ExtensionContext} context + */ +async function activate(context) { + sidebarProvider = new BlogSidebarProvider(); + context.subscriptions.push( + vscode.window.registerTreeDataProvider('blog-editor-sidebar', sidebarProvider), + vscode.commands.registerCommand('blogEditor.open', () => openEditor(context)), + vscode.commands.registerCommand('blogEditor.openPost', (slug) => openEditor(context, slug)), + vscode.commands.registerCommand('blogEditor.refreshPosts', () => sidebarProvider?.refresh()), + vscode.commands.registerCommand('blogEditor.newPost', () => newPost(context)), + vscode.commands.registerCommand('blogEditor.renamePost', (item) => renamePost(item)) + ); +} + +/** + * Prompts the user for a slug and creates a new blank blog post. + * @param {vscode.ExtensionContext} context + */ +async function newPost(context) { + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + if (!workspaceRoot) { vscode.window.showErrorMessage('No workspace folder open.'); return; } + + const blogDir = path.join(workspaceRoot, 'website', 'data', 'blog'); + + const slug = await vscode.window.showInputBox({ + prompt: 'Enter a slug for the new post (lowercase letters, numbers, hyphens)', + placeHolder: 'my-new-post', + validateInput: v => isValidSlug(v) ? null : 'Use only lowercase letters, numbers, and hyphens (e.g. my-post)' + }); + if (!slug) return; + + const filePath = path.join(blogDir, `${slug}.md`); + if (fs.existsSync(filePath)) { + vscode.window.showErrorMessage(`A post named "${slug}" already exists.`); + return; + } + + const now = new Date().toISOString().slice(0, 10); + const starter = `---\ntitle: "${slug}"\ndate: "${now}"\ntags: []\n---\n\n`; + fs.mkdirSync(blogDir, { recursive: true }); + fs.writeFileSync(filePath, starter, 'utf-8'); + activeBlogDir = blogDir; + sidebarProvider?.refresh(); + openEditor(context, slug); +} + +/** + * Renames a blog post slug via right-click context menu on a sidebar tree item. + * @param {vscode.TreeItem} item + */ +async function renamePost(item) { + const oldSlug = item?.slug ?? item?.id ?? (typeof item?.label === 'string' ? item.label : undefined); + if (!oldSlug || typeof oldSlug !== 'string') { vscode.window.showErrorMessage('Could not determine post slug.'); return; } + + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + if (!workspaceRoot) { vscode.window.showErrorMessage('No workspace folder open.'); return; } + + const blogDir = path.join(workspaceRoot, 'website', 'data', 'blog'); + const oldPath = path.join(blogDir, `${oldSlug}.md`); + + const newSlug = await vscode.window.showInputBox({ + prompt: `Rename "${oldSlug}" to:`, + value: oldSlug, + validateInput: v => isValidSlug(v) ? null : 'Use only lowercase letters, numbers, and hyphens' + }); + if (!newSlug || newSlug === oldSlug) return; + + const newPath = path.join(blogDir, `${newSlug}.md`); + if (fs.existsSync(newPath)) { vscode.window.showErrorMessage(`"${newSlug}" already exists.`); return; } + + fs.renameSync(oldPath, newPath); + sidebarProvider?.refresh(); + + // If this post is currently open in the editor, refresh it with the new slug. + if (panel) { + panel.webview.postMessage({ type: 'openSlug', slug: newSlug }); + } +} + +/** + * Builds the Milkdown JS + CSS bundles into dist/ if they don't exist yet. + * @returns {Promise} + */ +async function ensureBundle() { + if (!fs.existsSync(DIST_DIR)) fs.mkdirSync(DIST_DIR, { recursive: true }); + + const milkdownPath = path.join(DIST_DIR, 'milkdown.js'); + const commonCssPath = path.join(DIST_DIR, 'milkdown-common.css'); + const themeCssPath = path.join(DIST_DIR, 'milkdown-theme.css'); + + // Prefer prebuilt assets in packaged VSIX to avoid requiring esbuild at runtime. + if (fs.existsSync(milkdownPath) && fs.existsSync(commonCssPath) && fs.existsSync(themeCssPath)) return; + + await vscode.window.withProgress( + { location: vscode.ProgressLocation.Notification, title: 'Blog Editor: Bundling Milkdown…' }, + async () => { + const esbuildPkg = resolveFromNearestNodeModules('esbuild', EXT_DIR) + ?? resolveFromNearestNodeModules('esbuild', process.cwd()); + if (!esbuildPkg) { + throw new Error('Missing prebuilt dist assets and esbuild is unavailable. Rebuild the VSIX from the repo root so dist files are packaged.'); + } + const esbuild = require(path.join(esbuildPkg, 'lib', 'main.js')); + const crepePkg = resolveFromNearestNodeModules('@milkdown/crepe', EXT_DIR) + ?? resolveFromNearestNodeModules('@milkdown/crepe', process.cwd()); + if (!crepePkg) { + throw new Error('Cannot find @milkdown/crepe for bundling. Install workspace dependencies or rebuild the VSIX with prebuilt dist.'); + } + const rootDir = path.dirname(path.dirname(esbuildPkg)); + const crepeDir = path.join(crepePkg, 'lib', 'theme'); + const fontLoaders = { '.woff2': 'dataurl', '.woff': 'dataurl', '.ttf': 'dataurl', '.eot': 'dataurl', '.svg': 'dataurl' }; + + const [jsResult, cssCommon, cssTheme] = await Promise.all([ + esbuild.build({ + stdin: { contents: `export { Crepe, CrepeFeature } from '@milkdown/crepe';`, resolveDir: rootDir, loader: 'js' }, + bundle: true, format: 'esm', platform: 'browser', target: 'es2022', minify: true, write: false, + }), + esbuild.build({ + entryPoints: [path.join(crepeDir, 'common', 'style.css')], + bundle: true, write: false, loader: fontLoaders, + }), + esbuild.build({ + entryPoints: [path.join(crepeDir, 'frame-dark', 'style.css')], + bundle: true, write: false, loader: fontLoaders, + }), + ]); + + fs.writeFileSync(path.join(DIST_DIR, 'milkdown.js'), jsResult.outputFiles[0].contents); + fs.writeFileSync(path.join(DIST_DIR, 'milkdown-common.css'), cssCommon.outputFiles[0].contents); + fs.writeFileSync(path.join(DIST_DIR, 'milkdown-theme.css'), cssTheme.outputFiles[0].contents); + } + ); +} + +/** + * @param {vscode.ExtensionContext} context + * @param {string} [initialSlug] + */ +async function openEditor(context, initialSlug) { + if (panel) { + panel.reveal(); + if (initialSlug) { + panel.webview.postMessage({ type: 'openSlug', slug: initialSlug }); + } + return; + } + + const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; + if (!workspaceRoot) { vscode.window.showErrorMessage('No workspace folder open.'); return; } + + await ensureBundle(); + + const websiteDir = path.join(workspaceRoot, 'website'); + const blogDir = path.join(websiteDir, 'data', 'blog'); + activeBlogDir = blogDir; + sidebarProvider?.refresh(); + + if (initialSlug) pendingOpenSlug = initialSlug; + + panel = vscode.window.createWebviewPanel( + 'blogEditor', 'Blog Editor', + vscode.ViewColumn.One, + { + enableScripts: true, + retainContextWhenHidden: true, + localResourceRoots: [ + vscode.Uri.file(DIST_DIR), + vscode.Uri.file(websiteDir), + ], + } + ); + + panel.webview.html = buildHtml(panel.webview); + + panel.webview.onDidReceiveMessage(msg => handleMessage(msg, blogDir, websiteDir), undefined, context.subscriptions); + panel.onDidDispose(() => { + panel = undefined; + pendingOpenSlug = undefined; + }, undefined, context.subscriptions); +} + +/** + * Builds the webview HTML, replacing asset URIs and nonce. + * @param {vscode.Webview} webview + * @returns {string} + */ +function buildHtml(webview) { + const nonce = crypto.randomBytes(16).toString('hex'); + const milkdownJs = webview.asWebviewUri(vscode.Uri.file(path.join(DIST_DIR, 'milkdown.js'))); + const commonCss = webview.asWebviewUri(vscode.Uri.file(path.join(DIST_DIR, 'milkdown-common.css'))); + const themeCss = webview.asWebviewUri(vscode.Uri.file(path.join(DIST_DIR, 'milkdown-theme.css'))); + const csp = webview.cspSource; + + const template = fs.readFileSync(path.join(EXT_DIR, 'editor.html'), 'utf-8'); + return template + .replace(/\{\{NONCE\}\}/g, nonce) + .replace(/\{\{CSP_SOURCE\}\}/g, csp) + .replace('{{MILKDOWN_JS}}', milkdownJs.toString()) + .replace('{{COMMON_CSS}}', commonCss.toString()) + .replace('{{THEME_CSS}}', themeCss.toString()); +} + +/** + * Replaces relative image paths in markdown with webview-safe URIs. + * @param {string} content + * @param {string} websiteBaseUri Result of webview.asWebviewUri(websiteDir).toString() + * @returns {string} + */ +function injectWebviewImageUris(content, websiteBaseUri) { + return content.replace(/(\!\[[^\]]*\]\()([^)]+)(\))/g, (match, open, src, close) => { + if (/^https?:|^data:|^blob:/.test(src)) return match; + return `${open}${websiteBaseUri}/${src.replace(/^\//, '')}${close}`; + }); +} + +/** + * Reverts webview URIs in markdown back to relative paths before saving. + * @param {string} content + * @param {string} websiteBaseUri + * @returns {string} + */ +function revertWebviewImageUris(content, websiteBaseUri) { + const escaped = websiteBaseUri.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return content.replace( + new RegExp(`(\\!\\[[^\\]]*\\]\\()${escaped}/([^)]+)(\\))`, 'g'), + (_m, open, rel, close) => `${open}${rel}${close}` + ); +} + +/** + * Handles messages from the webview. + * @param {{ type: string, slug?: string, content?: string, filename?: string, dataBase64?: string, blobUrl?: string }} msg + * @param {string} blogDir + * @param {string} websiteDir + */ +function handleMessage(msg, blogDir, websiteDir) { + const webview = panel?.webview; + if (!webview) return; + try { + const websiteBaseUri = webview.asWebviewUri(vscode.Uri.file(websiteDir)).toString(); + switch (msg.type) { + case 'getPosts': { + const slugs = fs.readdirSync(blogDir) + .filter(f => f.endsWith('.md') && !f.startsWith('.')) + .map(f => path.basename(f, '.md')) + .sort(); + webview.postMessage({ type: 'posts', slugs }); + break; + } + case 'getPost': { + const filePath = safePostPath(blogDir, msg.slug); + if (!filePath) return; + const raw = fs.readFileSync(filePath, 'utf-8').replace(/!\[[^\]]*\]\(blob:[^)]+\)\r?\n?/g, ''); + // Build imageMap: webviewUri → relativePath, so the browser can reverse blob URLs + const imageMap = {}; + const imgPattern = /!\[[^\]]*\]\(([^)]+)\)/g; + let imgMatch; + while ((imgMatch = imgPattern.exec(raw)) !== null) { + const src = imgMatch[1]; + if (/^https?:|^data:|^blob:/.test(src)) continue; + const absPath = path.join(websiteDir, src.replace(/^\//, '')); + if (fs.existsSync(absPath)) { + const uri = webview.asWebviewUri(vscode.Uri.file(absPath)).toString(); + imageMap[uri] = src; + } + } + const content = injectWebviewImageUris(raw, websiteBaseUri); + webview.postMessage({ type: 'post', slug: msg.slug, content, imageMap }); + break; + } + case 'savePost': { + const filePath = safePostPath(blogDir, msg.slug); + if (!filePath) return; + const content = revertWebviewImageUris(msg.content, websiteBaseUri); + fs.writeFileSync(filePath, content, 'utf-8'); + webview.postMessage({ type: 'saved', slug: msg.slug }); + break; + } + case 'saveMedia': { + const mediaDir = path.join(websiteDir, 'data', 'blog', 'media'); + fs.mkdirSync(mediaDir, { recursive: true }); + const safeName = (msg.filename || 'paste.png').replace(/[^a-z0-9._-]/gi, '_'); + const filePath = path.join(mediaDir, safeName); + fs.writeFileSync(filePath, Buffer.from(msg.dataBase64, 'base64')); + const relativePath = `data/blog/media/${safeName}`; + const savedUri = webview.asWebviewUri(vscode.Uri.file(filePath)).toString(); + webview.postMessage({ type: 'mediaSaved', blobUrl: msg.blobUrl, relativePath, webviewUri: savedUri }); + break; + } + case 'newPost': { + if (!isValidSlug(msg.slug)) { + webview.postMessage({ type: 'error', message: 'Invalid slug.' }); + return; + } + const filePath = path.join(blogDir, `${msg.slug}.md`); + if (fs.existsSync(filePath)) { + webview.postMessage({ type: 'error', message: `"${msg.slug}" already exists.` }); + return; + } + fs.writeFileSync(filePath, msg.content, 'utf-8'); + webview.postMessage({ type: 'created', slug: msg.slug }); + sidebarProvider?.refresh(); + break; + } + case 'renamePost': { + if (!isValidSlug(msg.newSlug)) { + webview.postMessage({ type: 'error', message: 'Invalid slug.' }); + return; + } + const oldFilePath = safePostPath(blogDir, msg.oldSlug); + if (!oldFilePath) return; + const newFilePath = path.join(blogDir, `${msg.newSlug}.md`); + if (!newFilePath.startsWith(blogDir + path.sep)) return; + if (fs.existsSync(newFilePath)) { + webview.postMessage({ type: 'error', message: `"${msg.newSlug}" already exists.` }); + return; + } + fs.renameSync(oldFilePath, newFilePath); + sidebarProvider?.refresh(); + webview.postMessage({ type: 'renamed', oldSlug: msg.oldSlug, newSlug: msg.newSlug }); + break; + } + case 'refreshPosts': { + sidebarProvider?.refresh(); + break; + } + case 'ready': { + if (pendingOpenSlug) { + webview.postMessage({ type: 'openSlug', slug: pendingOpenSlug }); + pendingOpenSlug = undefined; + } + break; + } + } + } catch (err) { + webview.postMessage({ type: 'error', message: String(err) }); + } +} + +/** + * Returns an absolute path to a post file, guarding against path traversal. + * @param {string} blogDir + * @param {string | undefined} slug + * @returns {string | null} + */ +function safePostPath(blogDir, slug) { + if (!isValidSlug(slug)) { + panel?.webview.postMessage({ type: 'error', message: 'Invalid slug.' }); + return null; + } + const resolved = path.resolve(blogDir, `${slug}.md`); + if (!resolved.startsWith(blogDir + path.sep)) return null; + return resolved; +} + +/** + * @param {string | undefined} slug + * @returns {boolean} + */ +function isValidSlug(slug) { + return typeof slug === 'string' && /^[a-z0-9][a-z0-9-]*$/.test(slug) && slug.length <= 100; +} + +function deactivate() {} + +module.exports = { activate, deactivate }; diff --git a/tools/blogeditor/launch.json b/tools/blogeditor/launch.json new file mode 100644 index 0000000..6515d65 --- /dev/null +++ b/tools/blogeditor/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Blog Editor Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}/.vscode" + ] + } + ] +} diff --git a/tools/blogeditor/media/blog-editor.svg b/tools/blogeditor/media/blog-editor.svg new file mode 100644 index 0000000..c168da7 --- /dev/null +++ b/tools/blogeditor/media/blog-editor.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/blogeditor/package-lock.json b/tools/blogeditor/package-lock.json new file mode 100644 index 0000000..99d8b81 --- /dev/null +++ b/tools/blogeditor/package-lock.json @@ -0,0 +1,15 @@ +{ + "name": "blog-editor", + "version": "0.1.3", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "blog-editor", + "version": "0.1.3", + "engines": { + "vscode": "^1.80.0" + } + } + } +} diff --git a/tools/blogeditor/package.json b/tools/blogeditor/package.json new file mode 100644 index 0000000..7de2647 --- /dev/null +++ b/tools/blogeditor/package.json @@ -0,0 +1,84 @@ +{ + "name": "blog-editor", + "displayName": "Blog Editor", + "description": "WYSIWYG Milkdown blog post editor for this workspace", + "version": "0.1.11", + "publisher": "local", + "engines": { "vscode": "^1.80.0" }, + "categories": ["Other"], + "repository": { "type": "git", "url": "https://github.com/local/blog-editor" }, + "activationEvents": [], + "main": "./extension.js", + "contributes": { + "commands": [ + { + "command": "blogEditor.open", + "title": "Open Blog Editor", + "category": "Blog" + }, + { + "command": "blogEditor.openPost", + "title": "Open Blog Post", + "category": "Blog" + }, + { + "command": "blogEditor.refreshPosts", + "title": "Refresh Blog Posts", + "category": "Blog", + "icon": "$(refresh)" + }, + { + "command": "blogEditor.newPost", + "title": "New Post", + "category": "Blog", + "icon": "$(add)" + }, + { + "command": "blogEditor.renamePost", + "title": "Rename Post", + "category": "Blog" + } + ], + "viewsContainers": { + "activitybar": [ + { + "id": "blog-editor-container", + "title": "Blog Editor", + "icon": "media/blog-editor.svg" + } + ] + }, + "views": { + "blog-editor-container": [ + { + "id": "blog-editor-sidebar", + "name": "Posts" + } + ] + }, + "menus": { + "view/title": [ + { + "command": "blogEditor.newPost", + "when": "view == blog-editor-sidebar", + "group": "navigation@1" + }, + { + "command": "blogEditor.refreshPosts", + "when": "view == blog-editor-sidebar", + "group": "navigation@2" + } + ], + "view/item/context": [ + { + "command": "blogEditor.renamePost", + "when": "view == blog-editor-sidebar && viewItem == blogPost", + "group": "inline" + } + ] + } + }, + "scripts": { + "package": "node ../build-dist.js && npx @vscode/vsce package --out blog-editor.vsix --no-dependencies" + } +} diff --git a/website/data/blog/markdown-test.md b/website/data/blog/markdown-test.md index e60bb76..1a526e0 100644 --- a/website/data/blog/markdown-test.md +++ b/website/data/blog/markdown-test.md @@ -1,11 +1,10 @@ --- title: Markdown Formatting Test -date: 2026-04-20 +date: 2026-09-11 author: Test Author tags: test, formatting, markdown --- - -# Heading 1 +# Heading 1 test 123 ## Heading 2 @@ -30,11 +29,15 @@ Here's a [regular link](https://example.com) and here's a [YouTube link](https:/ ## Lists Unordered list: -- First item -- Second item -- Third item + +* First item + +* Second item + +* Third item Ordered list: + 1. First step 2. Second step 3. Third step @@ -42,6 +45,7 @@ Ordered list: ## Code Blocks Standard JavaScript: + ```javascript const hello = "world"; console.log(hello); @@ -52,6 +56,7 @@ function test() { ``` Python with syntax highlighting: + ```python def hello_world(): print("Hello, World!") @@ -59,7 +64,8 @@ def hello_world(): ``` Code with max height (200px): -```javascript {maxHeight: 200} + +```javascript // This is a long code block that will scroll const data = [1, 2, 3, 4, 5]; @@ -92,31 +98,36 @@ const obj = { ## Horizontal Rule ---- +*** ## Images -![Test Image](data/blog/media/test.png) +![1.00](data/blog/media/test.gif) ## Mixed Content -You can mix **bold**, *italic*, and `code` in the same paragraph. Here's a [link with **bold** text](https://example.com) too. +You can mix **bold**, *italic*, and `code` in the same paragraph. Here's a [link with](https://example.com) **[bold](https://example.com)** [text](https://example.com) too. ### Nested Lists -- Top level item -- Another top level - - Nested item (if supported) - - Another nested +* Top level itemsss + +* Another top level + + * Nested item (if supported) + + * Another nested 1. Numbered item 2. Another numbered - - Mixed with bullets - - More bullets + + * Mixed with bullets + + * More bullets ## Special Characters -Testing special chars: < > & " ' +Testing special chars: < > & " ' ## Long Paragraph diff --git a/website/data/blog/media/paste-1778401785819-7erqa.png b/website/data/blog/media/paste-1778401785819-7erqa.png new file mode 100644 index 0000000..ba587e4 Binary files /dev/null and b/website/data/blog/media/paste-1778401785819-7erqa.png differ diff --git a/website/data/blog/media/test.gif b/website/data/blog/media/test.gif new file mode 100644 index 0000000..13482fc Binary files /dev/null and b/website/data/blog/media/test.gif differ diff --git a/website/data/blog/testddd.md b/website/data/blog/testddd.md new file mode 100644 index 0000000..9718e5d --- /dev/null +++ b/website/data/blog/testddd.md @@ -0,0 +1,15 @@ +--- +title: test d d d d +date: 2026-05-10 +author: it me +--- +asdffdsaasdffdsa + +|
|
|
|
| +| :----- | :----- | :----- | -----: | +|
|
|
|
| +|
|
|
|
| + +
+ +this is a test post, should't publish i guess, but who's reading lmao diff --git a/website/data/blog/welcome.md b/website/data/blog/welcome.md index 8251e31..aedc28d 100644 --- a/website/data/blog/welcome.md +++ b/website/data/blog/welcome.md @@ -1,10 +1,9 @@ --- title: Welcome to My Blog -date: 2026-04-19 +date: 2026-05-10 author: Max Litruv Boonzaayer tags: welcome, meta, introduction --- - # Welcome to My Blog This is my first blog post! I'm excited to share my thoughts and experiences with you. @@ -15,15 +14,20 @@ This blog is built using a **custom node-based graph system** where each blog po ### Features -- 📝 Markdown support with YAML front matter -- 📅 Date-based organization -- 🏷️ Tag system for categorization -- 🎨 Interactive node-based visualization -- 📁 Media support in `data/blog/media/` +* 📝 Markdown support with YAML front matter + +* 📅 Date-based organization + +* 🏷️ Tag system for categorization + +* 🎨 Interactive node-based visualization + +* 📁 Media support in `data/blog/media/` ## Technical Details The build system automatically: + 1. Scans the `data/blog/` directory for `.md` files 2. Parses YAML front matter for metadata 3. Generates a `blogs.json` file diff --git a/website/data/blogs.json b/website/data/blogs.json index 1d36227..3279841 100644 --- a/website/data/blogs.json +++ b/website/data/blogs.json @@ -9,7 +9,7 @@ "formatting", "markdown" ], - "content": "\r\n# Heading 1\r\n\r\n## Heading 2\r\n\r\n### Heading 3\r\n\r\n#### Heading 4\r\n\r\n##### Heading 5\r\n\r\n###### Heading 6\r\n\r\n## Text Formatting\r\n\r\nThis is **bold text** and this is *italic text* and this is ***bold italic text***.\r\n\r\nHere's some `inline code` in a sentence.\r\n\r\n## Links\r\n\r\nHere's a [regular link](https://example.com) and here's a [YouTube link](https://youtube.com/watch?v=test).\r\n\r\n## Lists\r\n\r\nUnordered list:\r\n- First item\r\n- Second item\r\n- Third item\r\n\r\nOrdered list:\r\n1. First step\r\n2. Second step\r\n3. Third step\r\n\r\n## Code Blocks\r\n\r\nStandard JavaScript:\r\n```javascript\r\nconst hello = \"world\";\r\nconsole.log(hello);\r\n\r\nfunction test() {\r\n return true;\r\n}\r\n```\r\n\r\nPython with syntax highlighting:\r\n```python\r\ndef hello_world():\r\n print(\"Hello, World!\")\r\n return True\r\n```\r\n\r\nCode with max height (200px):\r\n```javascript {maxHeight: 200}\r\n// This is a long code block that will scroll\r\nconst data = [1, 2, 3, 4, 5];\r\n\r\nfunction processData(arr) {\r\n return arr.map(x => x * 2);\r\n}\r\n\r\nconsole.log(processData(data));\r\n\r\n// Adding more lines to demonstrate scrolling\r\nfor (let i = 0; i < 10; i++) {\r\n console.log(`Iteration ${i}`);\r\n}\r\n\r\n// Even more content\r\nconst obj = {\r\n name: \"Test\",\r\n value: 42,\r\n nested: {\r\n deep: true\r\n }\r\n};\r\n```\r\n\r\n## Blockquotes\r\n\r\n> This is a blockquote.\r\n> It can span multiple lines.\r\n> And continues here.\r\n\r\n## Horizontal Rule\r\n\r\n---\r\n\r\n## Images\r\n\r\n![Test Image](data/blog/media/test.png)\r\n\r\n## Mixed Content\r\n\r\nYou can mix **bold**, *italic*, and `code` in the same paragraph. Here's a [link with **bold** text](https://example.com) too.\r\n\r\n### Nested Lists\r\n\r\n- Top level item\r\n- Another top level\r\n - Nested item (if supported)\r\n - Another nested\r\n\r\n1. Numbered item\r\n2. Another numbered\r\n - Mixed with bullets\r\n - More bullets\r\n\r\n## Special Characters\r\n\r\nTesting special chars: < > & \" ' \r\n\r\n## Long Paragraph\r\n\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\r\n\r\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\r\n" + "content": "\r\n# Heading 1\r\n\r\n## Heading 2\r\n\r\n### Heading 3\r\n\r\n#### Heading 4\r\n\r\n##### Heading 5\r\n\r\n###### Heading 6\r\n\r\n## Text Formatting\r\n\r\nThis is **bold text** and this is *italic text* and this is ***bold italic text***.\r\n\r\nHere's some `inline code` in a sentence.\r\n\r\n## Links\r\n\r\nHere's a [regular link](https://example.com) and here's a [YouTube link](https://youtube.com/watch?v=test).\r\n\r\n## Lists\r\n\r\nUnordered list:\r\n- First item\r\n- Second item\r\n- Third item\r\n\r\nOrdered list:\r\n1. First step\r\n2. Second step\r\n3. Third step\r\n\r\n## Code Blocks\r\n\r\nStandard JavaScript:\r\n```javascript\r\nconst hello = \"world\";\r\nconsole.log(hello);\r\n\r\nfunction test() {\r\n return true;\r\n}\r\n```\r\n\r\nPython with syntax highlighting:\r\n```python\r\ndef hello_world():\r\n print(\"Hello, World!\")\r\n return True\r\n```\r\n\r\nCode with max height (200px):\r\n```javascript {maxHeight: 200}\r\n// This is a long code block that will scroll\r\nconst data = [1, 2, 3, 4, 5];\r\n\r\nfunction processData(arr) {\r\n return arr.map(x => x * 2);\r\n}\r\n\r\nconsole.log(processData(data));\r\n\r\n// Adding more lines to demonstrate scrolling\r\nfor (let i = 0; i < 10; i++) {\r\n console.log(`Iteration ${i}`);\r\n}\r\n\r\n// Even more content\r\nconst obj = {\r\n name: \"Test\",\r\n value: 42,\r\n nested: {\r\n deep: true\r\n }\r\n};\r\n```\r\n\r\n## Blockquotes\r\n\r\n> This is a blockquote.\r\n> It can span multiple lines.\r\n> And continues here.\r\n\r\n## Horizontal Rule\r\n\r\n---\r\n\r\n## Images\r\n\r\n![Test Image](data/blog/media/test.gif)\r\n\r\n## Mixed Content\r\n\r\nYou can mix **bold**, *italic*, and `code` in the same paragraph. Here's a [link with **bold** text](https://example.com) too.\r\n\r\n### Nested Lists\r\n\r\n- Top level item\r\n- Another top level\r\n - Nested item (if supported)\r\n - Another nested\r\n\r\n1. Numbered item\r\n2. Another numbered\r\n - Mixed with bullets\r\n - More bullets\r\n\r\n## Special Characters\r\n\r\nTesting special chars: < > & \" ' \r\n\r\n## Long Paragraph\r\n\r\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\r\n\r\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\r\n" }, { "slug": "welcome", diff --git a/website/index.html b/website/index.html index 8edaa5d..e828000 100644 --- a/website/index.html +++ b/website/index.html @@ -29,17 +29,23 @@ + + + + + + - - - - - - - - - + + + + + + + + +
diff --git a/website/scripts/ItemDragger.js b/website/scripts/ItemDragger.js index 3bda38d..24ee918 100644 --- a/website/scripts/ItemDragger.js +++ b/website/scripts/ItemDragger.js @@ -202,6 +202,13 @@ export class ItemDragger { if (!this.#enabled) return; const target = /** @type {HTMLElement} */ (e.target); if (target.closest(".pin-handle")) return; + + // Allow text selection in blog/info node bodies + const nodeBody = target.closest(".node-body"); + if (nodeBody && (node.type === 'info' || node.type === 'blog_post')) { + return; // Don't drag, allow text selection + } + e.stopPropagation(); const pointerWorld = this.#clientToWorkspace(e.clientX, e.clientY); diff --git a/website/scripts/MarkdownRenderer.js b/website/scripts/MarkdownRenderer.js index d1cf0ea..04e5898 100644 --- a/website/scripts/MarkdownRenderer.js +++ b/website/scripts/MarkdownRenderer.js @@ -91,7 +91,8 @@ export class MarkdownRenderer { const langClass = lang ? ` language-${lang}` : ""; const styleAttr = maxHeight ? ` style="max-height: ${maxHeight}px; overflow-y: auto;"` : ""; - return `
${highlightedCode}
`; + const escapedCode = MarkdownRenderer.#escape(code); + return `
${highlightedCode}
`; } // Horizontal rule @@ -106,6 +107,16 @@ export class MarkdownRenderer { return `${MarkdownRenderer.#renderInline(headingMatch[2])}`; } + // Standalone image + const imgBlockMatch = block.match(/^!\[([^\]]*)\]\(([^)]+)\)$/); + if (imgBlockMatch) { + const alt = MarkdownRenderer.#escape(imgBlockMatch[1]); + const src = MarkdownRenderer.#sanitizeUrl(imgBlockMatch[2]); + if (src) { + return `
${alt}${alt ? `
${alt}
` : ""}
`; + } + } + // Blockquote if (/^> /.test(block)) { const inner = block.replace(/^> ?/gm, ""); @@ -114,20 +125,12 @@ export class MarkdownRenderer { // Unordered list if (/^[-*+] /.test(block)) { - const items = block.split("\n").filter(Boolean).map(line => { - const content = line.replace(/^[-*+]\s+/, ""); - return `
  • ${MarkdownRenderer.#renderInline(content)}
  • `; - }); - return `
      ${items.join("")}
    `; + return MarkdownRenderer.#renderList(block, "ul"); } // Ordered list if (/^\d+\. /.test(block)) { - const items = block.split("\n").filter(Boolean).map(line => { - const content = line.replace(/^\d+\.\s+/, ""); - return `
  • ${MarkdownRenderer.#renderInline(content)}
  • `; - }); - return `
      ${items.join("")}
    `; + return MarkdownRenderer.#renderList(block, "ol"); } // Paragraph (handle single-line line breaks within block) @@ -135,6 +138,57 @@ export class MarkdownRenderer { return `

    ${lines.join("
    ")}

    `; } + /** + * Renders nested lists (ul or ol) with indentation support. + * @param {string} block + * @param {"ul" | "ol"} listType + * @returns {string} + */ + static #renderList(block, listType) { + const lines = block.split("\n").filter(Boolean); + const items = []; + let i = 0; + + while (i < lines.length) { + const line = lines[i]; + const indent = line.match(/^(\s*)/)[1].length; + + // Extract content + let content; + if (listType === "ul") { + content = line.replace(/^\s*[-*+]\s+/, ""); + } else { + content = line.replace(/^\s*\d+\.\s+/, ""); + } + + // Look ahead for nested items (more indented) + let nestedBlock = ""; + let j = i + 1; + while (j < lines.length) { + const nextLine = lines[j]; + const nextIndent = nextLine.match(/^(\s*)/)[1].length; + if (nextIndent > indent) { + nestedBlock += (nestedBlock ? "\n" : "") + nextLine.slice(indent + 2); // Remove parent indent + j++; + } else { + break; + } + } + + // Render item with nested list if present + let itemHtml = MarkdownRenderer.#renderInline(content); + if (nestedBlock) { + const nestedType = /^[-*+] /.test(nestedBlock.trim()) ? "ul" : "ol"; + itemHtml += MarkdownRenderer.#renderList(nestedBlock, nestedType); + } + items.push(`
  • ${itemHtml}
  • `); + i = j; + } + + const tag = listType === "ul" ? "ul" : "ol"; + return `<${tag} class="md-${tag}">${items.join("")}`; + } + // ─── Inline-level ───────────────────────────────────────────────────────── /** @@ -159,6 +213,16 @@ export class MarkdownRenderer { // Italic out = out.replace(/\*(.+?)\*/g, "$1"); + // Images ![alt](url) — must be matched before links + out = out.replace( + /!\[([^\]]*)\]\(([^)]+)\)/g, + (_, alt, url) => { + const safeUrl = MarkdownRenderer.#sanitizeUrl(url); + if (!safeUrl) return MarkdownRenderer.#escape(alt); + return `${MarkdownRenderer.#escape(alt)}`; + } + ); + // Links [text](url) out = out.replace( /\[([^\]]+)\]\(([^)]+)\)/g, @@ -203,7 +267,10 @@ export class MarkdownRenderer { */ static #sanitizeUrl(url) { const trimmed = url.trim(); + // Allow absolute URLs, root-relative, hash links, relative-dot paths, and plain relative paths if (/^(https?:\/\/|mailto:|\/|#|\.)/.test(trimmed)) return trimmed; + // Allow relative paths (e.g. data/blog/media/image.png) — no protocol = safe relative + if (/^[a-zA-Z0-9_\-][a-zA-Z0-9_.\-\/]*$/.test(trimmed)) return trimmed; return null; } } diff --git a/website/scripts/WorkspaceNavigator.js b/website/scripts/WorkspaceNavigator.js index 23b7f38..fbe57df 100644 --- a/website/scripts/WorkspaceNavigator.js +++ b/website/scripts/WorkspaceNavigator.js @@ -481,6 +481,19 @@ export class WorkspaceNavigator { /** @param {PointerEvent} e */ #onPointerDown(e) { if (e.button !== 0 && e.button !== 2) return; + + // Allow text selection in blog/info nodes + const nodeBody = e.target.closest('.node-body'); + if (nodeBody) { + const blueprintNode = nodeBody.closest('.blueprint-node'); + if (blueprintNode) { + const nodeType = blueprintNode.dataset.nodeType; + if (nodeType === 'info' || nodeType === 'blog_post') { + return; // Don't pan, allow text selection + } + } + } + this.#beginPan(e); } diff --git a/website/scripts/nodes/BlogPostNode.js b/website/scripts/nodes/BlogPostNode.js index 0571a72..c7a9a93 100644 --- a/website/scripts/nodes/BlogPostNode.js +++ b/website/scripts/nodes/BlogPostNode.js @@ -100,6 +100,27 @@ export class BlogPostNode extends NodeBase { const { MarkdownRenderer } = await import('../MarkdownRenderer.js'); contentDiv.innerHTML = MarkdownRenderer.render(post.content); + // Add copy button handlers + contentDiv.querySelectorAll('.md-copy-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + e.stopPropagation(); + const code = btn.getAttribute('data-code'); + if (code) { + navigator.clipboard.writeText(code).then(() => { + const originalText = btn.textContent; + btn.textContent = '✓'; + btn.classList.add('copied'); + setTimeout(() => { + btn.textContent = originalText; + btn.classList.remove('copied'); + }, 2000); + }).catch(err => { + console.error('Failed to copy:', err); + }); + } + }); + }); + } catch (error) { body.innerHTML = `

    Error loading blog post: ${error.message}

    `; console.error('Failed to load blog post:', error); diff --git a/website/scripts/nodes/PrintNode.js b/website/scripts/nodes/PrintNode.js index c45a31d..23a7289 100644 --- a/website/scripts/nodes/PrintNode.js +++ b/website/scripts/nodes/PrintNode.js @@ -40,3 +40,5 @@ export class PrintNode extends NodeBase { } NodeRegistry.UCLASS_Register(PrintNode); + + diff --git a/website/styles/index.html b/website/styles/index.html deleted file mode 100644 index a40c94d..0000000 --- a/website/styles/index.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - Personal Site - - - -
    - -
    -
    -
    - -
    - -
    - - -
    - - - - - - - - - - - - - - - - - - diff --git a/website/styles/main.css b/website/styles/main.css index ead079a..7feb0de 100644 --- a/website/styles/main.css +++ b/website/styles/main.css @@ -15,16 +15,70 @@ img { /* ─── Custom Properties ──────────────────────────────────────────────────────── */ :root { - --bg: #101218; + /* Catppuccin Mocha Palette */ + --ctp-rosewater: #f5e0dc; + --ctp-flamingo: #f2cdcd; + --ctp-pink: #f5c2e7; + --ctp-mauve: #cba6f7; + --ctp-red: #f38ba8; + --ctp-maroon: #eba0ac; + --ctp-peach: #fab387; + --ctp-yellow: #f9e2af; + --ctp-green: #a6e3a1; + --ctp-teal: #94e2d5; + --ctp-sky: #89dceb; + --ctp-sapphire: #74c7ec; + --ctp-blue: #89b4fa; + --ctp-lavender: #b4befe; + --ctp-text: #cdd6f4; + --ctp-subtext1: #bac2de; + --ctp-subtext0: #a6adc8; + --ctp-overlay2: #9399b2; + --ctp-overlay1: #7f849c; + --ctp-overlay0: #6c7086; + --ctp-surface2: #585b70; + --ctp-surface1: #45475a; + --ctp-surface0: #313244; + --ctp-base: #1e1e2e; + --ctp-mantle: #181825; + --ctp-crust: #11111b; + + /* Workspace */ + --bg: var(--ctp-crust); --grid-size: 20px; - --grid-color: rgba(255, 255, 255, 0.04); - --grid-color-strong: rgba(255, 255, 255, 0.1); + --grid-color: rgba(205, 214, 244, 0.04); + --grid-color-strong: rgba(205, 214, 244, 0.1); --workspace-zoom: 1; - --hud-bg: rgba(20, 20, 28, 0.75); - --hud-border: rgba(255, 255, 255, 0.08); - --hud-text: rgba(255, 255, 255, 0.7); - --hud-hover: rgba(255, 255, 255, 0.12); + /* HUD */ + --hud-bg: rgba(24, 24, 37, 0.75); + --hud-border: rgba(205, 214, 244, 0.08); + --hud-text: var(--ctp-text); + --hud-hover: rgba(205, 214, 244, 0.12); + + /* Nodes */ + --node-bg: var(--ctp-base); + --node-border: var(--ctp-surface1); + --node-header-text: var(--ctp-text); + --node-body-text: var(--ctp-subtext1); + --node-pin-label: var(--ctp-subtext0); + + /* Panels */ + --panel-bg: rgba(17, 17, 27, 0.95); + --panel-border: rgba(205, 214, 244, 0.1); + --panel-text: var(--ctp-text); + --panel-text-dim: rgba(205, 214, 244, 0.55); + + /* Inputs */ + --input-bg: rgba(49, 50, 68, 0.4); + --input-border: rgba(205, 214, 244, 0.1); + --input-text: var(--ctp-text); + --input-focus-bg: rgba(69, 71, 90, 0.6); + --input-focus-border: var(--ctp-blue); + + /* Buttons */ + --btn-primary-bg: var(--ctp-green); + --btn-primary-text: var(--ctp-crust); } /* ─── Base ────────────────────────────────────────────────────────────────────── */ @@ -35,7 +89,7 @@ html, body { overflow: hidden; background: var(--bg); font-family: system-ui, sans-serif; - color: #fff; + color: var(--ctp-text); } body { @@ -114,14 +168,14 @@ svg.world-image { right: 16px; z-index: 200; min-width: 240px; - background: rgba(10, 11, 16, 0.88); - border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(17, 17, 27, 0.88); + border: 1px solid var(--hud-border); border-radius: 10px; padding: 10px 12px; backdrop-filter: blur(10px); font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 11px; - color: rgba(255, 255, 255, 0.55); + color: var(--ctp-subtext1); flex-direction: column; gap: 3px; user-select: none; @@ -149,7 +203,7 @@ svg.world-image { font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; - color: rgba(255, 255, 255, 0.3); + color: rgba(166, 173, 200, 0.5); } .debug-toggle-btn { @@ -161,15 +215,15 @@ svg.world-image { padding: 0; background: transparent; border: none; - color: rgba(255, 255, 255, 0.4); + color: rgba(166, 173, 200, 0.6); cursor: pointer; border-radius: 4px; transition: all 0.15s ease; } .debug-toggle-btn:hover { - background: rgba(255, 255, 255, 0.08); - color: rgba(255, 255, 255, 0.7); + background: rgba(205, 214, 244, 0.08); + color: rgba(205, 214, 244, 0.9); } .debug-toggle-btn:active { @@ -202,7 +256,7 @@ svg.world-image { .debug-label { flex: 0 0 54px; - color: rgba(255, 255, 255, 0.35); + color: rgba(166, 173, 200, 0.5); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -210,19 +264,19 @@ svg.world-image { } .debug-value { - color: rgba(180, 220, 255, 0.85); + color: var(--ctp-blue); white-space: nowrap; } .debug-divider { height: 1px; - background: rgba(255, 255, 255, 0.07); + background: rgba(205, 214, 244, 0.07); margin: 4px 0; } .debug-draggable-cb { margin: 0; - accent-color: rgba(100, 160, 255, 0.9); + accent-color: var(--ctp-blue); cursor: pointer; } @@ -231,16 +285,16 @@ svg.world-image { padding: 1px 6px; font-family: inherit; font-size: 10px; - background: rgba(255, 255, 255, 0.08); - color: rgba(180, 220, 255, 0.85); - border: 1px solid rgba(255, 255, 255, 0.13); + background: var(--ctp-surface0); + color: var(--ctp-blue); + border: 1px solid var(--hud-border); border-radius: 4px; cursor: pointer; white-space: nowrap; } .debug-copy-btn:hover { - background: rgba(255, 255, 255, 0.15); + background: rgba(69, 71, 90, 0.8); } .debug-copy-json-btn { @@ -250,17 +304,17 @@ svg.world-image { font-family: inherit; font-size: 11px; font-weight: 500; - background: rgba(100, 160, 255, 0.12); - color: rgba(180, 220, 255, 0.95); - border: 1px solid rgba(100, 160, 255, 0.25); + background: rgba(137, 180, 250, 0.12); + color: rgba(137, 180, 250, 0.95); + border: 1px solid rgba(137, 180, 250, 0.25); border-radius: 6px; cursor: pointer; transition: all 0.15s; } .debug-copy-json-btn:hover { - background: rgba(100, 160, 255, 0.2); - color: rgba(200, 230, 255, 1); + background: rgba(137, 180, 250, 0.2); + color: var(--ctp-text); } .debug-copy-json-btn:active { @@ -274,17 +328,17 @@ svg.world-image { font-family: inherit; font-size: 11px; font-weight: 500; - background: rgba(160, 100, 255, 0.12); - color: rgba(200, 180, 255, 0.95); - border: 1px solid rgba(160, 100, 255, 0.25); + background: rgba(203, 166, 247, 0.12); + color: rgba(203, 166, 247, 0.95); + border: 1px solid rgba(203, 166, 247, 0.25); border-radius: 6px; cursor: pointer; transition: all 0.15s; } .debug-show-properties-btn:hover { - background: rgba(160, 100, 255, 0.2); - color: rgba(220, 200, 255, 1); + background: rgba(203, 166, 247, 0.2); + color: var(--ctp-text); } .debug-show-properties-btn:active { @@ -296,7 +350,7 @@ svg.world-image { font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; - color: rgba(255, 255, 255, 0.25); + color: rgba(166, 173, 200, 0.4); margin-top: 4px; margin-bottom: 2px; } @@ -305,9 +359,9 @@ svg.world-image { flex: 1; font-family: inherit; font-size: 11px; - background: rgba(255, 255, 255, 0.05); - color: rgba(180, 220, 255, 0.9); - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--input-bg); + color: var(--ctp-blue); + border: 1px solid var(--input-border); border-radius: 3px; padding: 2px 5px; outline: none; @@ -315,12 +369,12 @@ svg.world-image { } .debug-input:focus { - background: rgba(255, 255, 255, 0.08); - border-color: rgba(100, 160, 255, 0.5); + background: var(--input-focus-bg); + border-color: var(--input-focus-border); } .debug-input:read-only { - color: rgba(255, 255, 255, 0.4); + color: rgba(166, 173, 200, 0.6); cursor: not-allowed; } @@ -338,8 +392,8 @@ svg.world-image { } .debug-pin-item { - background: rgba(255, 255, 255, 0.03); - border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(49, 50, 68, 0.3); + border: 1px solid rgba(205, 214, 244, 0.08); border-radius: 4px; padding: 4px; display: flex; @@ -357,9 +411,9 @@ svg.world-image { flex: 1; font-family: inherit; font-size: 10px; - background: rgba(255, 255, 255, 0.05); - color: rgba(180, 220, 255, 0.9); - border: 1px solid rgba(255, 255, 255, 0.1); + background: rgba(49, 50, 68, 0.4); + color: rgba(137, 180, 250, 0.9); + border: 1px solid rgba(205, 214, 244, 0.1); border-radius: 3px; padding: 2px 4px; outline: none; @@ -367,8 +421,8 @@ svg.world-image { } .debug-pin-input:focus { - background: rgba(255, 255, 255, 0.08); - border-color: rgba(100, 160, 255, 0.5); + background: rgba(69, 71, 90, 0.6); + border-color: rgba(137, 180, 250, 0.5); } .debug-pin-id { @@ -386,36 +440,36 @@ svg.world-image { padding: 0; font-size: 14px; line-height: 1; - background: rgba(255, 80, 80, 0.2); - color: rgba(255, 120, 120, 0.9); - border: 1px solid rgba(255, 80, 80, 0.3); + background: rgba(243, 139, 168, 0.2); + color: rgba(243, 139, 168, 0.9); + border: 1px solid rgba(243, 139, 168, 0.3); border-radius: 3px; cursor: pointer; } .debug-pin-remove:hover { - background: rgba(255, 80, 80, 0.3); + background: rgba(243, 139, 168, 0.3); } .debug-add-btn { font-family: inherit; font-size: 10px; padding: 3px 6px; - background: rgba(100, 160, 255, 0.15); - color: rgba(180, 220, 255, 0.9); - border: 1px solid rgba(100, 160, 255, 0.3); + background: rgba(137, 180, 250, 0.15); + color: rgba(137, 180, 250, 0.9); + border: 1px solid rgba(137, 180, 250, 0.3); border-radius: 4px; cursor: pointer; margin-bottom: 6px; } .debug-add-btn:hover { - background: rgba(100, 160, 255, 0.25); + background: rgba(137, 180, 250, 0.25); } .debug-worldbox-cb { margin: 0; - accent-color: rgba(255, 180, 60, 0.9); + accent-color: var(--ctp-peach); cursor: pointer; } @@ -424,15 +478,15 @@ svg.world-image { font-family: inherit; font-size: 10px; padding: 3px 8px; - background: rgba(100, 160, 255, 0.15); - color: rgba(180, 220, 255, 0.9); - border: 1px solid rgba(100, 160, 255, 0.3); + background: rgba(137, 180, 250, 0.15); + color: rgba(137, 180, 250, 0.9); + border: 1px solid rgba(137, 180, 250, 0.3); border-radius: 4px; cursor: pointer; } .debug-json-editor-btn:hover { - background: rgba(100, 160, 255, 0.25); + background: rgba(137, 180, 250, 0.25); } /* ─── WorldBox Overlay ────────────────────────────────────────────────────────── */ @@ -449,37 +503,37 @@ svg.world-image { .worldbox-rect { fill: none; - stroke: rgba(255, 180, 60, 0.6); + stroke: rgba(250, 179, 135, 0.6); stroke-width: 2; stroke-dasharray: 5, 5; } .worldbox-rect--active { - stroke: rgba(255, 80, 180, 0.95); + stroke: rgba(245, 194, 231, 0.95); stroke-width: 2.5; stroke-dasharray: 5, 5; - fill: rgba(255, 80, 180, 0.06); + fill: rgba(245, 194, 231, 0.06); } .worldbox-label { font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 10px; - fill: rgba(255, 200, 100, 0.9); + fill: rgba(249, 226, 175, 0.9); text-shadow: 0 0 4px rgba(0, 0, 0, 0.8); } .worldbox-label--active { - fill: rgba(255, 120, 210, 1); + fill: var(--ctp-pink); } .worldbox-anchor { - stroke: rgba(255, 100, 60, 0.8); + stroke: rgba(243, 139, 168, 0.8); stroke-width: 2; stroke-linecap: round; } .worldbox-anchor--active { - stroke: rgba(255, 80, 180, 0.95); + stroke: rgba(245, 194, 231, 0.95); } .viewbox-layer { @@ -493,8 +547,8 @@ svg.world-image { } .viewbox-rect { - fill: rgba(100, 200, 255, 0.05); - stroke: rgba(100, 200, 255, 0.7); + fill: rgba(137, 180, 250, 0.05); + stroke: rgba(137, 180, 250, 0.7); stroke-width: 3; stroke-dasharray: 8, 4; } @@ -503,7 +557,7 @@ svg.world-image { font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 11px; font-weight: 600; - fill: rgba(150, 220, 255, 1); + fill: var(--ctp-sky); text-shadow: 0 0 6px rgba(0, 0, 0, 0.9), 0 0 3px rgba(0, 0, 50, 0.8); } @@ -521,7 +575,7 @@ svg.world-image { } .quick-link { - color: rgba(255, 255, 255, 0.5); + color: rgba(205, 214, 244, 0.5); text-decoration: none; font-size: 13px; font-weight: 500; @@ -529,7 +583,7 @@ svg.world-image { } .quick-link:hover { - color: rgba(255, 255, 255, 0.9); + color: rgba(205, 214, 244, 0.9); } /* ─── HUD ─────────────────────────────────────────────────────────────────────── */ @@ -585,12 +639,12 @@ svg.world-image { } .hud-btn-drag.active { - background: rgba(60, 120, 255, 0.9); - border-color: rgba(80, 140, 255, 0.5); + background: rgba(137, 180, 250, 0.9); + border-color: rgba(137, 180, 250, 0.5); } .hud-btn-drag.active:hover { - background: rgba(80, 140, 255, 1); + background: var(--ctp-blue); } .hud-tooltip { @@ -598,14 +652,14 @@ svg.world-image { right: calc(100% + 12px); top: 50%; transform: translateY(-50%); - background: rgba(20, 22, 28, 0.95); - color: rgba(255, 255, 255, 0.9); + background: rgba(24, 24, 37, 0.95); + color: rgba(205, 214, 244, 0.9); padding: 8px 12px; border-radius: 6px; font-size: 13px; white-space: nowrap; pointer-events: none; - border: 1px solid rgba(255, 255, 255, 0.15); + border: 1px solid rgba(205, 214, 244, 0.15); backdrop-filter: blur(10px); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3); opacity: 0; @@ -626,7 +680,7 @@ svg.world-image { transform: translateY(-50%); width: 0; height: 0; - border-left: 9px solid rgba(20, 22, 28, 0.95); + border-left: 9px solid rgba(24, 24, 37, 0.95); border-top: 7px solid transparent; border-bottom: 7px solid transparent; } @@ -639,7 +693,7 @@ svg.world-image { transform: translateY(-50%); width: 0; height: 0; - border-left: 10px solid rgba(255, 255, 255, 0.15); + border-left: 10px solid rgba(205, 214, 244, 0.15); border-top: 8px solid transparent; border-bottom: 8px solid transparent; z-index: -1; @@ -667,8 +721,8 @@ svg.world-image { position: absolute; pointer-events: none; border-radius: 8px; - border: 2px solid rgba(255, 127, 17, 0.6); - background: rgba(255, 127, 17, 0.07); + border: 2px solid rgba(250, 179, 135, 0.6); + background: rgba(250, 179, 135, 0.07); opacity: 0.5; z-index: 5; transition: transform 140ms cubic-bezier(0.22, 0.61, 0.36, 1); @@ -685,11 +739,11 @@ svg.world-image { .blueprint-comment { position: absolute; - border: 1px solid rgba(255, 255, 255, 0.12); + border: 1px solid rgba(205, 214, 244, 0.12); border-radius: 8px; pointer-events: auto; box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.08), + inset 0 1px 0 rgba(205, 214, 244, 0.08), 0 4px 16px rgba(0, 0, 0, 0.3); z-index: 0; overflow: hidden; @@ -707,14 +761,14 @@ svg.world-image { font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; - color: #ffffff; + color: var(--ctp-text); text-shadow: - 0 0 12px rgba(255, 255, 255, 0.4), + 0 0 12px rgba(205, 214, 244, 0.4), 0 1px 2px rgba(0, 0, 0, 0.8); background: linear-gradient(180deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.2) 100%); - border-bottom: 1px solid rgba(255, 255, 255, 0.2); + border-bottom: 1px solid rgba(205, 214, 244, 0.2); position: relative; z-index: 1; } @@ -724,8 +778,8 @@ svg.world-image { .blueprint-node { position: absolute; min-width: 220px; - background: #1d2029; - border: 1px solid #2f3544; + background: var(--node-bg); + border: 1px solid var(--node-border); border-radius: 8px; box-shadow: 0 8px 18px rgba(0, 0, 0, 0.35); display: grid; @@ -742,33 +796,33 @@ svg.world-image { } .blueprint-node:hover { - border-color: rgba(255, 127, 17, 0.15); + border-color: rgba(250, 179, 135, 0.2); } /* ─── Pure node ──────────────────────────────────────────────────────────────── */ .blueprint-node[data-node-type="pure"] { border-radius: 12px; - border-color: rgba(62, 229, 129, 0.3); - background: #1a2120; + border-color: rgba(166, 227, 161, 0.3); + background: var(--ctp-mantle); min-width: 0; } .blueprint-node[data-node-type="pure"]:hover { - border-color: rgba(62, 229, 129, 0.55); + border-color: rgba(166, 227, 161, 0.55); } .blueprint-node[data-node-type="pure"] .node-header { - background: linear-gradient(90deg, rgba(62, 229, 129, 0.14), rgba(62, 229, 129, 0.06)); - border-bottom-color: rgba(62, 229, 129, 0.15); - color: #7effc0; + background: linear-gradient(90deg, rgba(166, 227, 161, 0.14), rgba(166, 227, 161, 0.06)); + border-bottom-color: rgba(166, 227, 161, 0.15); + color: var(--ctp-green); font-size: 0.78rem; padding: 0.35rem 0.7rem; } .node-body--image { padding: 0; - border-top: 1px solid rgba(62, 229, 129, 0.12); + border-top: 1px solid rgba(166, 227, 161, 0.12); overflow: hidden; line-height: 0; } @@ -784,7 +838,7 @@ svg.world-image { .node-body--lottie { padding: 0; - border-top: 1px solid rgba(62, 229, 129, 0.12); + border-top: 1px solid rgba(166, 227, 161, 0.12); overflow: hidden; line-height: 0; } @@ -798,17 +852,17 @@ svg.world-image { .node-body--text { padding: 12px 16px; - border-top: 1px solid rgba(62, 229, 129, 0.12); + border-top: 1px solid rgba(166, 227, 161, 0.12); } .node-name-display { font-size: 14px; font-weight: 500; - color: rgba(255, 255, 255, 0.9); + color: var(--ctp-text); text-align: center; letter-spacing: 0.5px; padding: 4px 8px; - background: rgba(62, 229, 129, 0.08); + background: rgba(166, 227, 161, 0.08); border-radius: 4px; font-family: 'Courier New', monospace; } @@ -850,18 +904,18 @@ svg.world-image { /* ─── Button node ────────────────────────────────────────────────────────────── */ .blueprint-node[data-node-type="button"] { - border-color: rgba(255, 160, 60, 0.35); - background: #201e18; + border-color: rgba(250, 179, 135, 0.35); + background: var(--ctp-base); } .blueprint-node[data-node-type="button"]:hover { - border-color: rgba(255, 160, 60, 0.6); + border-color: rgba(250, 179, 135, 0.6); } .blueprint-node[data-node-type="button"] .node-header { - background: linear-gradient(90deg, rgba(255, 160, 60, 0.18), rgba(255, 160, 60, 0.06)); - border-bottom-color: rgba(255, 160, 60, 0.18); - color: #ffd080; + background: linear-gradient(90deg, rgba(250, 179, 135, 0.18), rgba(250, 179, 135, 0.06)); + border-bottom-color: rgba(250, 179, 135, 0.18); + color: var(--ctp-peach); } .node-run-btn { @@ -870,8 +924,8 @@ svg.world-image { height: 22px; border-radius: 50%; border: none; - background: rgba(255, 160, 60, 0.75); - color: #1a1600; + background: rgba(250, 179, 135, 0.75); + color: var(--ctp-crust); line-height: 0; padding: 0; cursor: pointer; @@ -884,7 +938,7 @@ svg.world-image { } .node-run-btn:hover { - background: rgba(255, 180, 80, 1); + background: var(--ctp-peach); transform: scale(1.12); } @@ -893,9 +947,9 @@ svg.world-image { } @keyframes node-run-flash { - 0% { box-shadow: 0 0 0 0 rgba(255, 180, 80, 0.8); } - 60% { box-shadow: 0 0 0 8px rgba(255, 180, 80, 0); } - 100% { box-shadow: 0 0 0 0 rgba(255, 180, 80, 0); } + 0% { box-shadow: 0 0 0 0 rgba(250, 179, 135, 0.8); } + 60% { box-shadow: 0 0 0 8px rgba(250, 179, 135, 0); } + 100% { box-shadow: 0 0 0 0 rgba(250, 179, 135, 0); } } .node-run-btn--flash { @@ -905,35 +959,35 @@ svg.world-image { /* ─── Print node ─────────────────────────────────────────────────────────────── */ .blueprint-node[data-node-type="print"] { - border-color: rgba(94, 196, 255, 0.25); - background: #181d22; + border-color: rgba(137, 220, 235, 0.25); + background: var(--ctp-mantle); } .blueprint-node[data-node-type="print"]:hover { - border-color: rgba(94, 196, 255, 0.5); + border-color: rgba(137, 220, 235, 0.5); } .blueprint-node[data-node-type="print"] .node-header { - background: linear-gradient(90deg, rgba(94, 196, 255, 0.14), rgba(94, 196, 255, 0.05)); - border-bottom-color: rgba(94, 196, 255, 0.15); - color: #a8e8ff; + background: linear-gradient(90deg, rgba(137, 220, 235, 0.14), rgba(137, 220, 235, 0.05)); + border-bottom-color: rgba(137, 220, 235, 0.15); + color: var(--ctp-sky); } /* ─── Timer node ─────────────────────────────────────────────────────────────── */ .blueprint-node[data-node-type="timer"] { - border-color: rgba(180, 120, 255, 0.3); - background: #1c1a28; + border-color: rgba(203, 166, 247, 0.3); + background: var(--ctp-mantle); } .blueprint-node[data-node-type="timer"]:hover { - border-color: rgba(180, 120, 255, 0.55); + border-color: rgba(203, 166, 247, 0.55); } .blueprint-node[data-node-type="timer"] .node-header { - background: linear-gradient(90deg, rgba(180, 120, 255, 0.16), rgba(180, 120, 255, 0.06)); - border-bottom-color: rgba(180, 120, 255, 0.18); - color: #d4aaff; + background: linear-gradient(90deg, rgba(203, 166, 247, 0.16), rgba(203, 166, 247, 0.06)); + border-bottom-color: rgba(203, 166, 247, 0.18); + color: var(--ctp-mauve); border-top-left-radius: 7px; border-top-right-radius: 7px; overflow: hidden; @@ -945,8 +999,8 @@ svg.world-image { height: 22px; border-radius: 50%; border: none; - background: rgba(180, 120, 255, 0.7); - color: #100a1a; + background: rgba(203, 166, 247, 0.7); + color: var(--ctp-crust); line-height: 0; padding: 0; cursor: pointer; @@ -959,7 +1013,7 @@ svg.world-image { } .node-timer-btn:hover { - background: rgba(200, 150, 255, 1); + background: var(--ctp-mauve); transform: scale(1.12); } @@ -968,14 +1022,14 @@ svg.world-image { } .node-timer-btn[data-running="true"] { - background: rgba(255, 90, 90, 0.8); - color: #fff; + background: rgba(243, 139, 168, 0.8); + color: var(--ctp-text); animation: timer-pulse 1s ease-in-out infinite; } @keyframes timer-pulse { - 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 90, 90, 0.6); } - 50% { box-shadow: 0 0 0 6px rgba(255, 90, 90, 0); } + 0%, 100% { box-shadow: 0 0 0 0 rgba(243, 139, 168, 0.6); } + 50% { box-shadow: 0 0 0 6px rgba(243, 139, 168, 0); } } /* ─── Number pin input chip ──────────────────────────────────────────────────── */ @@ -983,9 +1037,9 @@ svg.world-image { .pin-value--number { font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 0.7rem; - color: #c8a0ff; - background: rgba(180, 120, 255, 0.08); - border: 1px solid rgba(180, 120, 255, 0.25); + color: var(--ctp-mauve); + background: rgba(203, 166, 247, 0.08); + border: 1px solid rgba(203, 166, 247, 0.25); border-radius: 4px; padding: 1px 5px; width: 5ch; @@ -1005,8 +1059,8 @@ svg.world-image { } .pin-value--number:focus { - border-color: rgba(180, 120, 255, 0.7); - background: rgba(180, 120, 255, 0.15); + border-color: rgba(203, 166, 247, 0.7); + background: rgba(203, 166, 247, 0.15); } /* ─── Print speech bubble stack ─────────────────────────────────────────────── */ @@ -1032,15 +1086,15 @@ svg.world-image { left: 50%; transform: translateX(-50%); border: 6px solid transparent; - border-top-color: rgba(94, 196, 255, 0.45); + border-top-color: rgba(137, 220, 235, 0.45); border-bottom: none; } .print-bubble-msg { - background: rgba(16, 26, 38, 0.96); - border: 1px solid rgba(94, 196, 255, 0.4); + background: rgba(17, 17, 27, 0.96); + border: 1px solid rgba(137, 220, 235, 0.4); border-radius: 7px; - color: #a8e8ff; + color: var(--ctp-sky); font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 0.72rem; padding: 4px 10px; @@ -1048,7 +1102,7 @@ svg.world-image { max-width: 260px; overflow: hidden; text-overflow: ellipsis; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5), 0 0 6px rgba(94, 196, 255, 0.08); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5), 0 0 6px rgba(137, 220, 235, 0.08); animation: bubble-enter 0.18s cubic-bezier(0.22, 0.61, 0.36, 1) both; } @@ -1068,13 +1122,13 @@ svg.world-image { .node-header { grid-area: header; - background: linear-gradient(90deg, #1d2029, #242833); + background: linear-gradient(90deg, var(--ctp-base), var(--ctp-surface0)); padding: 0.5rem 0.75rem; font-weight: 600; font-size: 0.85rem; letter-spacing: 0.02em; - border-bottom: 1px solid #2f3544; - color: #f6f9ff; + border-bottom: 1px solid var(--node-border); + color: var(--node-header-text); display: flex; align-items: center; gap: 0.5rem; @@ -1114,7 +1168,7 @@ svg.world-image { } .pin-label { - color: #a8b2cc; + color: var(--node-pin-label); text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.68rem; @@ -1138,13 +1192,13 @@ svg.world-image { width: 18px; height: 18px; border-radius: 50%; - border: 2px solid #2f3544; - background: #242833; + border: 2px solid var(--node-border); + background: var(--ctp-surface0); position: relative; flex-shrink: 0; order: 2; margin: 3px 0; - color: var(--pin-kind-color, #8c919d); + color: var(--pin-kind-color, var(--ctp-overlay2)); } .pin-handle::after { @@ -1249,7 +1303,7 @@ svg.world-image { position: absolute; inset: 2.5px; clip-path: polygon(0% 0%, 60% 0%, 100% 50%, 60% 100%, 0% 100%); - background: #1d2029; + background: var(--node-bg); pointer-events: none; z-index: 1; } @@ -1276,9 +1330,9 @@ svg.world-image { .pin-value { font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 0.7rem; - color: #ff66ff; - background: rgba(255, 102, 255, 0.08); - border: 1px solid rgba(255, 102, 255, 0.25); + color: var(--ctp-pink); + background: rgba(245, 194, 231, 0.08); + border: 1px solid rgba(245, 194, 231, 0.25); border-radius: 4px; padding: 1px 5px; order: 1; @@ -1294,8 +1348,8 @@ svg.world-image { } .pin-value:focus { - border-color: rgba(255, 102, 255, 0.7); - background: rgba(255, 102, 255, 0.15); + border-color: rgba(245, 194, 231, 0.7); + background: rgba(245, 194, 231, 0.15); text-overflow: clip; } @@ -1326,12 +1380,11 @@ svg.world-image { .node-body { grid-area: body; padding: 0.75rem 0.9rem; - border-top: 1px solid #2f3544; - color: #c8d0e8; + border-top: 1px solid var(--node-border); + color: var(--node-body-text); font-size: 0.8rem; line-height: 1.6; user-select: text; - cursor: text; overflow-y: visible; overflow-x: hidden; } @@ -1346,70 +1399,160 @@ svg.world-image { } .node-body::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.2); + background: rgba(205, 214, 244, 0.2); border-radius: 4px; } .node-body::-webkit-scrollbar-thumb:hover { - background: rgba(255, 255, 255, 0.3); + background: rgba(205, 214, 244, 0.3); } .node-body .md-h1, .node-body .md-h2, -.node-body .md-h3 { - color: #f0f4ff; +.node-body .md-h3, +.node-body .md-h4, +.node-body .md-h5, +.node-body .md-h6 { + color: var(--ctp-text); font-weight: 700; margin-bottom: 0.3em; margin-top: 0.6em; letter-spacing: 0.01em; + user-select: text; } .node-body .md-h1 { font-size: 1.4rem; } .node-body .md-h2 { font-size: 0.88rem; } .node-body .md-h3 { font-size: 0.82rem; } +.node-body .md-h4 { font-size: 0.78rem; } +.node-body .md-h5 { font-size: 0.75rem; } +.node-body .md-h6 { font-size: 0.72rem; } .node-body .md-p { margin: 0.4em 0; + user-select: text; + cursor: text; } .node-body .md-ul, .node-body .md-ol { margin: 0.3em 0 0.3em 1.1em; padding: 0; + user-select: text; +} + +.node-body .md-li .md-ul, +.node-body .md-li .md-ol { + margin: 0.2em 0 0.2em 0.8em; } .node-body .md-li { margin: 0.15em 0; + user-select: text; } .node-body .md-blockquote { - border-left: 3px solid rgba(255, 160, 60, 0.5); + border-left: 3px solid rgba(250, 179, 135, 0.5); padding: 0.2em 0.7em; margin: 0.4em 0; - color: rgba(200, 210, 230, 0.7); + color: rgba(186, 194, 222, 0.7); font-style: italic; + user-select: text; +} + +.node-body .md-figure { + margin: 0.6em 0; + text-align: center; +} + +.node-body .md-img { + max-width: 100%; + height: auto; + border-radius: 6px; + display: block; + margin: 0 auto; + user-select: none; +} + +.node-body .md-img--inline { + display: inline; + vertical-align: middle; + border-radius: 3px; + margin: 0 0.15em; +} + +.node-body .md-figcaption { + margin-top: 0.3em; + font-size: 0.75em; + color: var(--ctp-subtext0); + font-style: italic; + user-select: text; } .node-body .md-code { font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; font-size: 0.78em; - background: rgba(255, 255, 255, 0.07); + background: rgba(49, 50, 68, 0.5); border-radius: 3px; padding: 0.1em 0.35em; - color: #a8daff; + color: var(--ctp-sky); + user-select: text; +} + +.node-body strong, +.node-body em { + user-select: text; +} + +.node-body .md-code-block { + position: relative; + margin: 0.4em 0; +} + +.node-body .md-copy-btn { + position: absolute; + top: 0.4em; + right: 0.4em; + background: rgba(49, 50, 68, 0.6); + border: 1px solid rgba(205, 214, 244, 0.12); + border-radius: 4px; + padding: 0.25em 0.5em; + font-size: 0.9em; + cursor: pointer; + opacity: 0; + transition: opacity 0.2s, background 0.15s; + z-index: 10; + user-select: none; +} + +.node-body .md-code-block:hover .md-copy-btn { + opacity: 1; +} + +.node-body .md-copy-btn:hover { + background: rgba(69, 71, 90, 0.8); +} + +.node-body .md-copy-btn:active { + background: rgba(88, 91, 112, 0.9); +} + +.node-body .md-copy-btn.copied { + opacity: 1; } .node-body .md-pre { - background: rgba(0, 0, 0, 0.35); - border: 1px solid #2f3544; + background: rgba(17, 17, 27, 0.5); + border: 1px solid var(--node-border); border-radius: 5px; padding: 0.5em 0.7em; overflow-x: auto; overflow-y: auto; - margin: 0.4em 0; + margin: 0; font-family: "Cascadia Code", "Fira Code", ui-monospace, monospace; + cursor: text; font-size: 0.76em; - color: #a8daff; + color: var(--ctp-sky); scroll-behavior: smooth; } @@ -1424,12 +1567,12 @@ svg.world-image { } .node-body .md-pre::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.15); + background: rgba(205, 214, 244, 0.15); border-radius: 3px; } .node-body .md-pre::-webkit-scrollbar-thumb:hover { - background: rgba(255, 255, 255, 0.25); + background: rgba(205, 214, 244, 0.25); } .node-body .md-pre code { @@ -1438,6 +1581,11 @@ svg.world-image { border-radius: 0; font-size: inherit; font-family: inherit; + user-select: text; +} + +.node-body .md-pre .token { + user-select: text; } /* Prism syntax highlighting overrides */ @@ -1445,11 +1593,11 @@ svg.world-image { .node-body .md-pre .token.prolog, .node-body .md-pre .token.doctype, .node-body .md-pre .token.cdata { - color: #6a9955; + color: var(--ctp-overlay0); } .node-body .md-pre .token.punctuation { - color: #d4d4d4; + color: var(--ctp-text); } .node-body .md-pre .token.property, @@ -1459,7 +1607,7 @@ svg.world-image { .node-body .md-pre .token.constant, .node-body .md-pre .token.symbol, .node-body .md-pre .token.deleted { - color: #b5cea8; + color: var(--ctp-peach); } .node-body .md-pre .token.selector, @@ -1468,7 +1616,7 @@ svg.world-image { .node-body .md-pre .token.char, .node-body .md-pre .token.builtin, .node-body .md-pre .token.inserted { - color: #ce9178; + color: var(--ctp-green); } .node-body .md-pre .token.operator, @@ -1476,44 +1624,45 @@ svg.world-image { .node-body .md-pre .token.url, .node-body .md-pre .language-css .token.string, .node-body .md-pre .style .token.string { - color: #d4d4d4; + color: var(--ctp-sky); } .node-body .md-pre .token.atrule, .node-body .md-pre .token.attr-value, .node-body .md-pre .token.keyword { - color: #569cd6; + color: var(--ctp-mauve); } .node-body .md-pre .token.function, .node-body .md-pre .token.class-name { - color: #dcdcaa; + color: var(--ctp-yellow); } .node-body .md-pre .token.regex, .node-body .md-pre .token.important, .node-body .md-pre .token.variable { - color: #9cdcfe; + color: var(--ctp-pink); } .node-body .md-hr { border: none; - border-top: 1px solid #2f3544; + border-top: 1px solid var(--node-border); margin: 0.6em 0; } .node-body .md-link { - color: rgba(120, 200, 255, 0.9); + color: rgba(137, 180, 250, 0.9); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; display: inline-flex; align-items: center; gap: 0.35em; + user-select: text; } .node-body .md-link:hover { - color: #fff; + color: var(--ctp-text); } /* ─── Socials button links ────────────────────────────────────────────────────── */ @@ -1540,9 +1689,9 @@ svg.world-image { width: 100%; padding: 9px 12px; border-radius: 7px; - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.08); - color: #fff; + background: var(--input-bg); + border: 1px solid var(--input-border); + color: var(--ctp-text); text-decoration: none; transition: background 0.15s, border-color 0.15s; box-sizing: border-box; @@ -1551,9 +1700,9 @@ svg.world-image { } .blueprint-node[data-node-id="socials"] .node-body .md-link:hover { - background: rgba(255, 255, 255, 0.1); - border-color: rgba(255, 255, 255, 0.18); - color: #fff; + background: var(--input-focus-bg); + border-color: rgba(205, 214, 244, 0.18); + color: var(--ctp-text); } .blueprint-node[data-node-id="socials"] .node-body .md-link-icon { @@ -1570,7 +1719,7 @@ svg.world-image { } .node-body .md-error { - color: rgba(255, 100, 100, 0.7); + color: var(--ctp-red); font-size: 0.75em; } @@ -1580,8 +1729,8 @@ svg.world-image { position: relative; width: 320px; height: 100vh; - background: rgba(12, 13, 18, 0.95); - border-left: 1px solid rgba(255, 255, 255, 0.1); + background: var(--panel-bg); + border-left: 1px solid var(--panel-border); backdrop-filter: blur(10px); z-index: 250; display: flex; @@ -1603,15 +1752,15 @@ svg.world-image { transform: translateY(-50%); width: 40px; height: 80px; - background: rgba(12, 13, 18, 0.95); - border: 1px solid rgba(255, 255, 255, 0.1); + background: rgba(17, 17, 27, 0.95); + border: 1px solid rgba(205, 214, 244, 0.1); border-right: none; border-radius: 8px 0 0 8px; display: flex; align-items: center; justify-content: center; cursor: pointer; - color: rgba(255, 255, 255, 0.6); + color: rgba(205, 214, 244, 0.6); transition: all 0.2s ease; opacity: 0; pointer-events: none; @@ -1624,8 +1773,8 @@ svg.world-image { } .properties-panel-tab:hover { - background: rgba(20, 22, 28, 0.98); - color: rgba(255, 255, 255, 0.9); + background: rgba(24, 24, 37, 0.98); + color: rgba(205, 214, 244, 0.9); right: -2px; } @@ -1634,22 +1783,22 @@ svg.world-image { align-items: center; justify-content: space-between; padding: 16px 20px; - border-bottom: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(10, 11, 16, 0.6); + border-bottom: 1px solid rgba(205, 214, 244, 0.08); + background: rgba(17, 17, 27, 0.6); } .properties-title { margin: 0; font-size: 14px; font-weight: 600; - color: rgba(255, 255, 255, 0.9); + color: var(--panel-text); letter-spacing: 0.02em; } .properties-toggle-btn { background: transparent; border: none; - color: rgba(255, 255, 255, 0.5); + color: rgba(205, 214, 244, 0.5); cursor: pointer; padding: 6px; border-radius: 4px; @@ -1660,8 +1809,8 @@ svg.world-image { } .properties-toggle-btn:hover { - background: rgba(255, 255, 255, 0.1); - color: rgba(255, 255, 255, 0.9); + background: rgba(205, 214, 244, 0.1); + color: rgba(205, 214, 244, 0.9); } .properties-panel.collapsed .properties-toggle-btn svg { @@ -1675,7 +1824,7 @@ svg.world-image { } .properties-section { - border-bottom: 1px solid rgba(255, 255, 255, 0.05); + border-bottom: 1px solid rgba(205, 214, 244, 0.05); } .section-header { @@ -1683,7 +1832,7 @@ svg.world-image { align-items: center; justify-content: space-between; padding: 14px 20px; - background: rgba(255, 255, 255, 0.02); + background: rgba(49, 50, 68, 0.2); cursor: default; } @@ -1692,7 +1841,7 @@ svg.world-image { } .section-header.collapsible:hover { - background: rgba(255, 255, 255, 0.04); + background: rgba(69, 71, 90, 0.3); } .section-header h3 { @@ -1701,13 +1850,13 @@ svg.world-image { font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; - color: rgba(255, 255, 255, 0.7); + color: rgba(205, 214, 244, 0.7); } .section-toggle { background: transparent; border: none; - color: rgba(255, 255, 255, 0.4); + color: rgba(205, 214, 244, 0.4); font-size: 10px; cursor: pointer; padding: 4px; @@ -1736,7 +1885,7 @@ svg.world-image { .prop-label { font-size: 11px; font-weight: 500; - color: rgba(255, 255, 255, 0.55); + color: var(--panel-text-dim); letter-spacing: 0.02em; } @@ -1744,9 +1893,9 @@ svg.world-image { width: 100%; font-family: ui-monospace, monospace; font-size: 12px; - background: rgba(255, 255, 255, 0.05); - color: rgba(220, 230, 255, 0.95); - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--input-bg); + color: var(--input-text); + border: 1px solid var(--input-border); border-radius: 5px; padding: 7px 10px; outline: none; @@ -1754,8 +1903,8 @@ svg.world-image { } .prop-input:focus { - background: rgba(255, 255, 255, 0.08); - border-color: rgba(100, 160, 255, 0.5); + background: var(--input-focus-bg); + border-color: var(--input-focus-border); } .prop-input:read-only { @@ -1766,13 +1915,13 @@ svg.world-image { .prop-checkbox { width: 18px; height: 18px; - accent-color: rgba(100, 160, 255, 0.9); + accent-color: var(--ctp-blue); cursor: pointer; } .prop-divider { height: 1px; - background: rgba(255, 255, 255, 0.06); + background: rgba(205, 214, 244, 0.06); margin: 16px 0; } @@ -1781,7 +1930,7 @@ svg.world-image { font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; - color: rgba(255, 255, 255, 0.5); + color: rgba(205, 214, 244, 0.5); margin: 0 0 12px; } @@ -1790,9 +1939,9 @@ svg.world-image { font-family: inherit; font-size: 12px; padding: 8px 12px; - background: rgba(100, 160, 255, 0.15); - color: rgba(180, 220, 255, 0.9); - border: 1px dashed rgba(100, 160, 255, 0.3); + background: rgba(137, 180, 250, 0.15); + color: rgba(137, 180, 250, 0.9); + border: 1px dashed rgba(137, 180, 250, 0.3); border-radius: 5px; cursor: pointer; margin-top: 8px; @@ -1800,7 +1949,7 @@ svg.world-image { } .prop-btn-add:hover { - background: rgba(100, 160, 255, 0.25); + background: rgba(137, 180, 250, 0.25); border-style: solid; } @@ -1810,8 +1959,8 @@ svg.world-image { font-size: 12px; font-weight: 600; padding: 10px 16px; - background: rgba(60, 180, 100, 0.9); - color: white; + background: var(--btn-primary-bg); + color: var(--btn-primary-text); border: none; border-radius: 6px; cursor: pointer; @@ -1819,7 +1968,7 @@ svg.world-image { } .prop-btn-primary:hover { - background: rgba(70, 200, 110, 1); + background: var(--ctp-green); } .breakpoints-list { @@ -1829,8 +1978,8 @@ svg.world-image { } .breakpoint-item { - background: rgba(255, 255, 255, 0.03); - border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(49, 50, 68, 0.3); + border: 1px solid rgba(205, 214, 244, 0.08); border-radius: 6px; padding: 12px; } @@ -1845,13 +1994,13 @@ svg.world-image { .breakpoint-title { font-size: 11px; font-weight: 600; - color: rgba(255, 200, 100, 0.9); + color: rgba(249, 226, 175, 0.9); } .breakpoint-remove { - background: rgba(255, 80, 80, 0.2); - color: rgba(255, 120, 120, 0.9); - border: 1px solid rgba(255, 80, 80, 0.3); + background: rgba(243, 139, 168, 0.2); + color: rgba(243, 139, 168, 0.9); + border: 1px solid rgba(243, 139, 168, 0.3); border-radius: 4px; padding: 3px 8px; font-size: 10px; @@ -1860,13 +2009,13 @@ svg.world-image { } .breakpoint-remove:hover { - background: rgba(255, 80, 80, 0.4); + background: rgba(243, 139, 168, 0.4); } .no-selection { padding: 40px 20px; text-align: center; - color: rgba(255, 255, 255, 0.4); + color: rgba(205, 214, 244, 0.4); } .no-selection p { @@ -1915,23 +2064,23 @@ svg.world-image { } .chat-status-connecting { - background: rgba(251, 191, 36, 0.2); - color: #fbbf24; + background: rgba(249, 226, 175, 0.2); + color: var(--ctp-yellow); } .chat-status-connected { - background: rgba(34, 197, 94, 0.2); - color: #22c55e; + background: rgba(166, 227, 161, 0.2); + color: var(--ctp-green); } .chat-status-disconnected { - background: rgba(148, 163, 184, 0.2); - color: #94a3b8; + background: rgba(108, 112, 134, 0.2); + color: var(--ctp-overlay0); } .chat-status-error { - background: rgba(239, 68, 68, 0.2); - color: #ef4444; + background: rgba(243, 139, 168, 0.2); + color: var(--ctp-red); } .chat-messages { @@ -1953,12 +2102,12 @@ svg.world-image { } .chat-messages::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.2); + background: rgba(205, 214, 244, 0.2); border-radius: 3px; } .chat-messages::-webkit-scrollbar-thumb:hover { - background: rgba(255, 255, 255, 0.3); + background: rgba(205, 214, 244, 0.3); } .chat-msg { @@ -1969,30 +2118,30 @@ svg.world-image { line-height: 1.4; padding: 4px 6px; border-radius: 4px; - background: rgba(255, 255, 255, 0.03); + background: rgba(49, 50, 68, 0.3); } .chat-msg:hover { - background: rgba(255, 255, 255, 0.06); + background: rgba(69, 71, 90, 0.4); } .chat-msg-time { - color: rgba(255, 255, 255, 0.4); + color: rgba(205, 214, 244, 0.4); font-size: 10px; font-family: 'Courier New', monospace; } .chat-msg-sender { - color: rgba(100, 181, 246, 0.9); + color: var(--ctp-blue); font-weight: 600; } .chat-msg-self .chat-msg-sender { - color: rgba(156, 39, 176, 0.9); + color: var(--ctp-mauve); } .chat-msg-content { - color: rgba(255, 255, 255, 0.85); + color: var(--ctp-text); word-wrap: break-word; overflow-wrap: break-word; } @@ -2000,7 +2149,7 @@ svg.world-image { .chat-msg-edited { grid-column: 3; font-size: 10px; - color: rgba(255, 255, 255, 0.3); + color: rgba(205, 214, 244, 0.3); font-style: italic; margin-left: 4px; } @@ -2011,12 +2160,12 @@ svg.world-image { .chat-msg-deleted .chat-msg-content::before { content: "[deleted] "; - color: rgba(239, 68, 68, 0.8); + color: var(--ctp-red); } .chat-msg-system { font-size: 11px; - color: rgba(251, 191, 36, 0.8); + color: var(--ctp-yellow); font-style: italic; padding: 2px 6px; text-align: center; @@ -2024,7 +2173,7 @@ svg.world-image { .chat-msg-error { font-size: 11px; - color: rgba(239, 68, 68, 0.9); + color: var(--ctp-red); font-weight: 600; padding: 2px 6px; text-align: center; @@ -2041,11 +2190,11 @@ svg.world-image { .chat-input { flex: 1; - background: rgba(255, 255, 255, 0.05); - border: 1px solid rgba(255, 255, 255, 0.1); + background: var(--input-bg); + border: 1px solid var(--input-border); border-radius: 4px; padding: 6px 10px; - color: #fff; + color: var(--input-text); font-size: 12px; font-family: inherit; outline: none; @@ -2053,20 +2202,20 @@ svg.world-image { } .chat-input:focus { - background: rgba(255, 255, 255, 0.08); - border-color: rgba(100, 181, 246, 0.5); + background: var(--input-focus-bg); + border-color: var(--input-focus-border); } .chat-input::placeholder { - color: rgba(255, 255, 255, 0.3); + color: rgba(205, 214, 244, 0.3); } .chat-send-btn { - background: rgba(100, 181, 246, 0.2); - border: 1px solid rgba(100, 181, 246, 0.4); + background: rgba(137, 180, 250, 0.2); + border: 1px solid rgba(137, 180, 250, 0.4); border-radius: 4px; padding: 6px 14px; - color: #64b5f6; + color: var(--ctp-blue); font-size: 12px; font-weight: 600; cursor: pointer; @@ -2074,8 +2223,8 @@ svg.world-image { } .chat-send-btn:hover { - background: rgba(100, 181, 246, 0.3); - border-color: rgba(100, 181, 246, 0.6); + background: rgba(137, 180, 250, 0.3); + border-color: rgba(137, 180, 250, 0.6); } .chat-send-btn:active { @@ -2088,11 +2237,11 @@ svg.world-image { } .chat-connect-btn { - background: rgba(34, 197, 94, 0.2); - border: 1px solid rgba(34, 197, 94, 0.4); + background: rgba(166, 227, 161, 0.2); + border: 1px solid rgba(166, 227, 161, 0.4); border-radius: 4px; padding: 6px 14px; - color: #22c55e; + color: var(--ctp-green); font-size: 12px; font-weight: 600; cursor: pointer; @@ -2100,8 +2249,8 @@ svg.world-image { } .chat-connect-btn:hover { - background: rgba(34, 197, 94, 0.3); - border-color: rgba(34, 197, 94, 0.6); + background: rgba(166, 227, 161, 0.3); + border-color: rgba(166, 227, 161, 0.6); } .chat-connect-btn:active { @@ -2120,8 +2269,8 @@ svg.world-image { left: 8px; right: 8px; margin-bottom: 4px; - background: rgba(30, 30, 40, 0.98); - border: 1px solid rgba(255, 255, 255, 0.2); + background: rgba(24, 24, 37, 0.98); + border: 1px solid rgba(205, 214, 244, 0.2); border-radius: 4px; max-height: 200px; overflow-y: auto; @@ -2138,7 +2287,7 @@ svg.world-image { } .autocomplete-popup::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.2); + background: rgba(205, 214, 244, 0.2); border-radius: 3px; } @@ -2148,7 +2297,7 @@ svg.world-image { display: flex; gap: 8px; align-items: center; - border-bottom: 1px solid rgba(255, 255, 255, 0.05); + border-bottom: 1px solid rgba(205, 214, 244, 0.05); } .ac-item:last-child { @@ -2157,23 +2306,23 @@ svg.world-image { .ac-item:hover, .ac-item.selected { - background: rgba(100, 181, 246, 0.2); + background: rgba(137, 180, 250, 0.2); } .ac-label { - color: #64b5f6; + color: var(--ctp-blue); font-weight: 600; font-size: 12px; } .ac-hint { - color: rgba(255, 255, 255, 0.5); + color: rgba(205, 214, 244, 0.5); font-size: 11px; font-family: 'Courier New', monospace; } .ac-desc { - color: rgba(255, 255, 255, 0.6); + color: rgba(205, 214, 244, 0.6); font-size: 11px; flex: 1; text-align: right; @@ -2190,8 +2339,8 @@ svg.world-image { max-width: 320px; max-height: 400px; padding: 0.5rem; - background: rgba(20, 20, 28, 0.98); - border: 1px solid rgba(255, 255, 255, 0.15); + background: rgba(24, 24, 37, 0.98); + border: 1px solid rgba(205, 214, 244, 0.15); border-radius: 8px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6); z-index: 1000; @@ -2205,21 +2354,21 @@ svg.world-image { width: 100%; padding: 0.5rem 0.7rem; border-radius: 6px; - border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(255, 255, 255, 0.06); - color: rgba(255, 255, 255, 0.95); + border: 1px solid var(--input-border); + background: var(--input-bg); + color: var(--input-text); font-size: 0.85rem; outline: none; transition: all 0.15s ease; } .context-menu-search:focus { - background: rgba(255, 255, 255, 0.09); - border-color: rgba(100, 181, 246, 0.5); + background: var(--input-focus-bg); + border-color: var(--input-focus-border); } .context-menu-search::placeholder { - color: rgba(255, 255, 255, 0.4); + color: rgba(205, 214, 244, 0.4); } .context-menu-list { @@ -2241,7 +2390,7 @@ svg.world-image { } .context-menu-list::-webkit-scrollbar-thumb { - background: rgba(255, 255, 255, 0.2); + background: rgba(205, 214, 244, 0.2); border-radius: 3px; } @@ -2253,7 +2402,7 @@ svg.world-image { border: 1px solid transparent; border-radius: 6px; background: transparent; - color: rgba(255, 255, 255, 0.9); + color: var(--ctp-text); font-size: 0.85rem; text-align: left; cursor: pointer; @@ -2262,35 +2411,35 @@ svg.world-image { .context-menu-item:hover, .context-menu-item:focus-visible { - background: rgba(255, 255, 255, 0.08); - border-color: rgba(255, 255, 255, 0.15); + background: rgba(69, 71, 90, 0.5); + border-color: rgba(205, 214, 244, 0.15); outline: none; } .context-menu-item:active { - background: rgba(255, 255, 255, 0.12); + background: rgba(88, 91, 112, 0.6); } .context-menu-item.is-selected, .context-menu-item[aria-selected='true'] { - background: rgba(100, 181, 246, 0.15); - border-color: rgba(100, 181, 246, 0.4); - color: rgba(255, 255, 255, 1); - box-shadow: inset 3px 0 0 #64b5f6; + background: rgba(137, 180, 250, 0.15); + border-color: rgba(137, 180, 250, 0.4); + color: var(--ctp-text); + box-shadow: inset 3px 0 0 var(--ctp-blue); } .context-menu-empty { margin: 0; font-size: 0.8rem; - color: rgba(255, 255, 255, 0.5); + color: rgba(205, 214, 244, 0.5); text-align: center; padding: 1rem 0; } @keyframes node-shake-red { - 0%, 100% { margin-left: 0; filter: drop-shadow(0 0 0 rgba(255, 82, 82, 0)); } - 10%, 30%, 50%, 70%, 90% { margin-left: -4px; filter: drop-shadow(0 0 8px rgba(255, 82, 82, 0.6)); } - 20%, 40%, 60%, 80% { margin-left: 4px; filter: drop-shadow(0 0 8px rgba(255, 82, 82, 0.6)); } + 0%, 100% { margin-left: 0; filter: drop-shadow(0 0 0 rgba(243, 139, 168, 0)); } + 10%, 30%, 50%, 70%, 90% { margin-left: -4px; filter: drop-shadow(0 0 8px rgba(243, 139, 168, 0.6)); } + 20%, 40%, 60%, 80% { margin-left: 4px; filter: drop-shadow(0 0 8px rgba(243, 139, 168, 0.6)); } } .node-shake-red {