diff --git a/packages/shikicode/.gitignore b/packages/shikicode/.gitignore new file mode 100644 index 0000000..bd1aa80 --- /dev/null +++ b/packages/shikicode/.gitignore @@ -0,0 +1,133 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + + +lib/ \ No newline at end of file diff --git a/packages/shikicode/.npmignore b/packages/shikicode/.npmignore new file mode 100644 index 0000000..561e15f --- /dev/null +++ b/packages/shikicode/.npmignore @@ -0,0 +1,133 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +# lib should be included in npm package +# lib/ \ No newline at end of file diff --git a/packages/shikicode/LICENSE b/packages/shikicode/LICENSE new file mode 100644 index 0000000..2ba6364 --- /dev/null +++ b/packages/shikicode/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 magic-akari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/shikicode/README.md b/packages/shikicode/README.md new file mode 100644 index 0000000..60682a5 --- /dev/null +++ b/packages/shikicode/README.md @@ -0,0 +1,9 @@ +# ShikiCode 式コード + +[![NPM version](https://img.shields.io/npm/v/shikicode?color=32A9C3&labelColor=1B3C4A&label=npm)](https://www.npmjs.com/package/shikicode) + +A lightweight, beautiful, and extensible code editor based on [Shiki](https://shiki.style). + +## License + +[MIT](./LICENSE) diff --git a/packages/shikicode/index.html b/packages/shikicode/index.html new file mode 100644 index 0000000..ab5486d --- /dev/null +++ b/packages/shikicode/index.html @@ -0,0 +1,156 @@ + + + + + + Shiki Editor + + + + +
+
+
+ + +
+ +
+
+ + + + + + diff --git a/packages/shikicode/package-lock.json b/packages/shikicode/package-lock.json new file mode 100644 index 0000000..5f449c4 --- /dev/null +++ b/packages/shikicode/package-lock.json @@ -0,0 +1,853 @@ +{ + "name": "shikicode", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "shikicode", + "version": "0.0.0", + "license": "MIT", + "devDependencies": { + "@types/jest": "^29.5.12", + "dprint": "^0.45.0", + "oxlint": "^0.2.14", + "shiki": "^1.2.0", + "typescript": "^5.4.3" + }, + "peerDependencies": { + "shiki": "^1.2.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@dprint/darwin-arm64": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/darwin-arm64/-/darwin-arm64-0.45.0.tgz", + "integrity": "sha512-pkSSmixIKXr5t32bhXIUbpIBm8F8uhsJcUUvfkFNsRbQvNwRp71ribZpE8dKl0ZFOlAFeWD6WLE8smp/QtiGUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@dprint/darwin-x64": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/darwin-x64/-/darwin-x64-0.45.0.tgz", + "integrity": "sha512-PHcXSrRO53KH9N+YPbPtr40NnDo2t7hO7KLMfl2ktRNLjrmKg6F8XDDsr2C7Z11k3jyEEU2Jq8hhpaKHwNapmQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@dprint/linux-arm64-glibc": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-glibc/-/linux-arm64-glibc-0.45.0.tgz", + "integrity": "sha512-NgIpvZHpiQaY4DxSygxknxBtvKE2KLK9dEbUNKNE098yTHhGq7ouPsoM7RtsO34RHJ3tEZLLJEuBHn20XP8LMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/linux-arm64-musl": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-arm64-musl/-/linux-arm64-musl-0.45.0.tgz", + "integrity": "sha512-Y8p+FC0RNyKCGQjy99Uh1LSPrlQtUTvo4brdvU1THF3pyWu6Bg1p6NiP5a6SjE/6t9CMKZJz39zPreQtnDkSDA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/linux-x64-glibc": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-x64-glibc/-/linux-x64-glibc-0.45.0.tgz", + "integrity": "sha512-u03NCZIpJhE5gIl9Q7jNL4sOPBFd/8BLVBiuLoLtbiTZQ+NNudHKgGNATJBU67q1MKpqKnt8/gQm139cJkHhrw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/linux-x64-musl": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/linux-x64-musl/-/linux-x64-musl-0.45.0.tgz", + "integrity": "sha512-DQN8LPtxismkeU1X+sQywa80kWwCBcpQh9fXoJcvTEHrgzHBqbG2SEsUZpM12oKEua1KE/iBh+vgZ+4I3TdI2A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@dprint/win32-x64": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/@dprint/win32-x64/-/win32-x64-0.45.0.tgz", + "integrity": "sha512-aZHIWG2jIlEp4BER1QG6YYqPd6TxT9S77AeUkWJixNiMEo+33mPRVCBcugRWI/WJWveX8yWFVXkToORtnSFeEA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@oxlint/darwin-arm64": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-arm64/-/darwin-arm64-0.2.14.tgz", + "integrity": "sha512-ddCNJDIpwdtDy2EveF76jXmHOs63b2AU8vvzHZ4cw6xtHxXgfGSOTAckWfJLKXq+s5LDROMVL2DXIcuizaXYBw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint/darwin-x64": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-x64/-/darwin-x64-0.2.14.tgz", + "integrity": "sha512-EvHOIjDpNgMXlDGk7Sr/2C0VszHj7riV+VhjGXyZwVCNFfT6jR2CfJNagTUp9AICkyESPY7UtOHYcsEsEKCtAw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint/linux-arm64-gnu": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-gnu/-/linux-arm64-gnu-0.2.14.tgz", + "integrity": "sha512-ptX6gC9wLCI3EMgYJd8cUIbcwTZv7aubuFnCg68bop2SdYAtYZIQQfazsOB/+a1pt/ISkheL19rGeaedmRqaPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-arm64-musl": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-musl/-/linux-arm64-musl-0.2.14.tgz", + "integrity": "sha512-F7hzgZB65C+K1ZJkUG8vgDzo+AD/DVU2cUU7o0pv6/cn1BGjcERiyJECzrPXsnYSgeaT88eXoUgnDZNf5mH7Lw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-x64-gnu": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-gnu/-/linux-x64-gnu-0.2.14.tgz", + "integrity": "sha512-mEkPz/GXOkPC3HNwN5SHGaT+ajk+twTuPHiI6TRKSbNCMHvi4kV9Ftana+t2hV5IfpbieFhnOsO0iH/iUOdKTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-x64-musl": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-musl/-/linux-x64-musl-0.2.14.tgz", + "integrity": "sha512-0jmm/NcD78etW+G9jHAuFjQdl9GW2bXxlOR8/y2jYyYTuCtSuqhzJCK2kWoAcBynacDIsDC+fCZF7qHOPrDHDA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/win32-arm64": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/win32-arm64/-/win32-arm64-0.2.14.tgz", + "integrity": "sha512-P5vaQFjtVnshk94PMaW/kot/FKH9y8fjhd7vwGp6eRO32QOkSMbG7jOtuvlFOb4E9lGyQaihJ9yVbP9vmkvzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxlint/win32-x64": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/@oxlint/win32-x64/-/win32-x64-0.2.14.tgz", + "integrity": "sha512-ORXoR8DpAOWX/3YDBwOCg+yUORu6cK/GUYEq22BpUXn/HRljiFbEBoBWadOhfow/K+/j9OGUxPeepe8zthN2iA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.9.0.tgz", + "integrity": "sha512-cbSoY8P/jgGByG8UOl3jnP/CWg/Qk+1q+eAKWtcrU3pNoILF8wTsLB0jT44qUBV8Ce1SvA9uqcM9Xf+u3fJFBw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=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, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dprint": { + "version": "0.45.0", + "resolved": "https://registry.npmjs.org/dprint/-/dprint-0.45.0.tgz", + "integrity": "sha512-3444h7V47XoA16qgIWjw3CV/Eo/rQbT/XTGlbJ/6vJ+apQyuo0+M3Ai0GS3wu7X9HBUDcA0zIHA3mOxWNz6toA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "dprint": "bin.js" + }, + "optionalDependencies": { + "@dprint/darwin-arm64": "0.45.0", + "@dprint/darwin-x64": "0.45.0", + "@dprint/linux-arm64-glibc": "0.45.0", + "@dprint/linux-arm64-musl": "0.45.0", + "@dprint/linux-x64-glibc": "0.45.0", + "@dprint/linux-x64-musl": "0.45.0", + "@dprint/win32-x64": "0.45.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/oxlint": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-0.2.14.tgz", + "integrity": "sha512-LFOnbhtpitIqtHqyBDYAvT5g3ckm3fZ6xAMU8zkaDwC4ofC29ZpxAPuF42ZFJOw1UnufJPUutECSwMco2ho/Fg==", + "dev": true, + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": ">=14.*" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/darwin-arm64": "0.2.14", + "@oxlint/darwin-x64": "0.2.14", + "@oxlint/linux-arm64-gnu": "0.2.14", + "@oxlint/linux-arm64-musl": "0.2.14", + "@oxlint/linux-x64-gnu": "0.2.14", + "@oxlint/linux-x64-musl": "0.2.14", + "@oxlint/win32-arm64": "0.2.14", + "@oxlint/win32-x64": "0.2.14" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/shiki": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.9.0.tgz", + "integrity": "sha512-i6//Lqgn7+7nZA0qVjoYH0085YdNk4MC+tJV4bo+HgjgRMJ0JmkLZzFAuvVioJqLkcGDK5GAMpghZEZkCnwxpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "1.9.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/typescript": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + } +} diff --git a/packages/shikicode/package.json b/packages/shikicode/package.json new file mode 100644 index 0000000..f05369d --- /dev/null +++ b/packages/shikicode/package.json @@ -0,0 +1,46 @@ +{ + "name": "shikicode", + "version": "0.0.0", + "description": "lightweight code editor powered by shiki", + "main": "lib/index.js", + "type": "module", + "scripts": { + "start": "tsc --watch", + "build": "tsc", + "prepack": "tsc", + "fix:fmt": "dprint fmt", + "check:fmt": "dprint check", + "check:lint": "oxlint src -D correctness -D pedantic" + }, + "keywords": [ + "shiki", + "code", + "editor" + ], + "author": "magic-akari ", + "license": "MIT", + "bugs": "https://github.com/magic-akari/shikicode/issues", + "homepage": "https://github.com/magic-akari/shikicode#readme", + "devDependencies": { + "@types/jest": "^29.5.13", + "dprint": "^0.47.2", + "oxlint": "^0.9.10", + "shiki": "^1.22.0", + "typescript": "^5.6.3" + }, + "peerDependencies": { + "shiki": "^1.2.0" + }, + "exports": { + ".": { + "types": "./lib/index.d.ts", + "default": "./lib/index.js" + }, + "./plugins": { + "types": "./lib/plugins/index.d.ts", + "default": "./lib/plugins/index.js" + }, + "./package.json": "./package.json" + }, + "packageManager": "pnpm@9.5.0+sha512.140036830124618d624a2187b50d04289d5a087f326c9edfc0ccd733d76c4f52c3a313d4fc148794a2a9d81553016004e6742e8cf850670268a7387fc220c903" +} diff --git a/packages/shikicode/pnpm-lock.yaml b/packages/shikicode/pnpm-lock.yaml new file mode 100644 index 0000000..d6b16be --- /dev/null +++ b/packages/shikicode/pnpm-lock.yaml @@ -0,0 +1,868 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@types/jest': + specifier: ^29.5.13 + version: 29.5.13 + dprint: + specifier: ^0.47.2 + version: 0.47.2 + oxlint: + specifier: ^0.9.10 + version: 0.9.10 + shiki: + specifier: ^1.22.0 + version: 1.22.0 + typescript: + specifier: ^5.6.3 + version: 5.6.3 + +packages: + + '@babel/code-frame@7.25.7': + resolution: {integrity: sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.7': + resolution: {integrity: sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.25.7': + resolution: {integrity: sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==} + engines: {node: '>=6.9.0'} + + '@dprint/darwin-arm64@0.47.2': + resolution: {integrity: sha512-mVPFBJsXxGDKHHCAY8wbqOyS4028g1bN15H9tivCnPAjwaZhkUimZHXWejXADjhGn+Xm2SlakugY9PY/68pH3Q==} + cpu: [arm64] + os: [darwin] + + '@dprint/darwin-x64@0.47.2': + resolution: {integrity: sha512-T7wzlc+rBV+6BRRiBjoqoy5Hj4TR2Nv2p2s9+ycyPGs10Kj/JXOWD8dnEHeBgUr2r4qe/ZdcxmsFQ5Hf2n0WuA==} + cpu: [x64] + os: [darwin] + + '@dprint/linux-arm64-glibc@0.47.2': + resolution: {integrity: sha512-B0m1vT5LdVtrNOVdkqpLPrSxuCD+l5bTIgRzPaDoIB1ChWQkler9IlX8C+RStpujjPj6SYvwo5vTzjQSvRdQkA==} + cpu: [arm64] + os: [linux] + + '@dprint/linux-arm64-musl@0.47.2': + resolution: {integrity: sha512-zID6wZZqpg2/Q2Us+ERQkbhLwlW3p3xaeEr00MPf49bpydmEjMiPuSjWPkNv+slQSIyIsVovOxF4lbNZjsdtvw==} + cpu: [arm64] + os: [linux] + + '@dprint/linux-x64-glibc@0.47.2': + resolution: {integrity: sha512-rB3WXMdINnRd33DItIp7mObS7dzHW90ZzeJSsoKJLPp+Z7wXjjb27UUowfqVI4baa/1pd7sdbX54DPohMtfu/A==} + cpu: [x64] + os: [linux] + + '@dprint/linux-x64-musl@0.47.2': + resolution: {integrity: sha512-E0+TNbzYdTXJ/jCVjUctVxkda/faw++aDQLfyWGcmdMJnbM7NZz+W4fUpDXzMPsjy+zTWxXcPK7/q2DZz2gnbg==} + cpu: [x64] + os: [linux] + + '@dprint/win32-arm64@0.47.2': + resolution: {integrity: sha512-K1EieTCFjfOCmyIhw9zFSduE6qVCNHEveupqZEfbSkVGw5T9MJQ1I9+n7MDb3RIDYEUk0enJ58/w82q8oDKCyA==} + cpu: [arm64] + os: [win32] + + '@dprint/win32-x64@0.47.2': + resolution: {integrity: sha512-LhizWr8VrhHvq4ump8HwOERyFmdLiE8C6A42QSntGXzKdaa2nEOq20x/o56ZIiDcesiV+1TmosMKimPcOZHa+Q==} + cpu: [x64] + os: [win32] + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@oxlint/darwin-arm64@0.9.10': + resolution: {integrity: sha512-eOXKZYq5bnCSgDefgM5bzAg+4Fc//Rc4yjgKN8iDWUARweCaChiQXb6TXX8MfEfs6qayEMy6yVj0pqoFz0B1aw==} + cpu: [arm64] + os: [darwin] + + '@oxlint/darwin-x64@0.9.10': + resolution: {integrity: sha512-UeYICDvLUaUOcY+0ugZUEmBMRLP+x8iTgL7TeY6BlpGw2ahbtUOTbyIIRWtr/0O++TnjZ+v8TzhJ9crw6Ij6dg==} + cpu: [x64] + os: [darwin] + + '@oxlint/linux-arm64-gnu@0.9.10': + resolution: {integrity: sha512-0Zn+vqHhrZyufFBfq9WOgiIool0gCR14BLsdS+0Dwd9o+kNxPGA5q7erQFkiC4rpkxtfBHeD3iIKMMt7d29Kyw==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-arm64-musl@0.9.10': + resolution: {integrity: sha512-tkQcWpYwF42bA/uRaV2iMFePHkBjTTgomOgeEaiw6XOSJX4nBEqGIIboqqLBWT4JnKCf/L+IG3y/e1MflhKByw==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-x64-gnu@0.9.10': + resolution: {integrity: sha512-JHbkMUnibqaSMBvLHyqTL5cWxcGW+jw+Ppt2baLISpvo34a6fBR+PI7v/A92sEDWe0W1rPhypzCwA8mKpkQ3DA==} + cpu: [x64] + os: [linux] + + '@oxlint/linux-x64-musl@0.9.10': + resolution: {integrity: sha512-aBBwN7bQzidwHwEXr7BAdVvMTLWstCy5gikerjLnGDeCSXX9r+o6+yUzTOqZvOo66E+XBgOJaVbY8rsL1MLE0g==} + cpu: [x64] + os: [linux] + + '@oxlint/win32-arm64@0.9.10': + resolution: {integrity: sha512-LXDnk7vKHT3IY6G1jq0O7+XMhtcHOYuxLGIx4KP+4xS6vKgBY+Bsq4xV3AtmtKlvnXkP5FxHpfLmcEtm5AWysA==} + cpu: [arm64] + os: [win32] + + '@oxlint/win32-x64@0.9.10': + resolution: {integrity: sha512-w5XRAV4bhgwenjjpGYZGglqzG9Wv/sI+cjQWJBQsvfDXsr2w4vOBXzt1j3/Z3EcSqf4KtkCa/IIuAhQyeShUbA==} + cpu: [x64] + os: [win32] + + '@shikijs/core@1.22.0': + resolution: {integrity: sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==} + + '@shikijs/engine-javascript@1.22.0': + resolution: {integrity: sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==} + + '@shikijs/engine-oniguruma@1.22.0': + resolution: {integrity: sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==} + + '@shikijs/types@1.22.0': + resolution: {integrity: sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==} + + '@shikijs/vscode-textmate@9.3.0': + resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.13': + resolution: {integrity: sha512-wd+MVEZCHt23V0/L642O5APvspWply/rGY5BcW4SUETo2UzPU3Z26qr8jC2qxpimI2jjx9h7+2cj2FwIr01bXg==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/node@22.7.5': + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + dprint@0.47.2: + resolution: {integrity: sha512-geUcVIIrmLaY+YtuOl4gD7J/QCjsXZa5gUqre9sO6cgH0X/Fa9heBN3l/AWVII6rKPw45ATuCSDWz1pyO+HkPQ==} + hasBin: true + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hast-util-to-html@9.0.3: + resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + oniguruma-to-js@0.4.3: + resolution: {integrity: sha512-X0jWUcAlxORhOqqBREgPMgnshB7ZGYszBNspP+tS9hPD3l13CdaXcHbgImoHUHlrvGx/7AvFEkTRhAGYh+jzjQ==} + + oxlint@0.9.10: + resolution: {integrity: sha512-bKiiFN7Hnoaist/rditTRBXz+GXKYuLd53/NB7Q6zHB/bifELJarSoRLkAUGElIJKl4PSr3lTh1g6zehh+rX0g==} + engines: {node: '>=14.*'} + hasBin: true + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + regex@4.3.3: + resolution: {integrity: sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==} + + shiki@1.22.0: + resolution: {integrity: sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@babel/code-frame@7.25.7': + dependencies: + '@babel/highlight': 7.25.7 + picocolors: 1.1.0 + + '@babel/helper-validator-identifier@7.25.7': {} + + '@babel/highlight@7.25.7': + dependencies: + '@babel/helper-validator-identifier': 7.25.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.0 + + '@dprint/darwin-arm64@0.47.2': + optional: true + + '@dprint/darwin-x64@0.47.2': + optional: true + + '@dprint/linux-arm64-glibc@0.47.2': + optional: true + + '@dprint/linux-arm64-musl@0.47.2': + optional: true + + '@dprint/linux-x64-glibc@0.47.2': + optional: true + + '@dprint/linux-x64-musl@0.47.2': + optional: true + + '@dprint/win32-arm64@0.47.2': + optional: true + + '@dprint/win32-x64@0.47.2': + optional: true + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.7.5 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@oxlint/darwin-arm64@0.9.10': + optional: true + + '@oxlint/darwin-x64@0.9.10': + optional: true + + '@oxlint/linux-arm64-gnu@0.9.10': + optional: true + + '@oxlint/linux-arm64-musl@0.9.10': + optional: true + + '@oxlint/linux-x64-gnu@0.9.10': + optional: true + + '@oxlint/linux-x64-musl@0.9.10': + optional: true + + '@oxlint/win32-arm64@0.9.10': + optional: true + + '@oxlint/win32-x64@0.9.10': + optional: true + + '@shikijs/core@1.22.0': + dependencies: + '@shikijs/engine-javascript': 1.22.0 + '@shikijs/engine-oniguruma': 1.22.0 + '@shikijs/types': 1.22.0 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.3 + + '@shikijs/engine-javascript@1.22.0': + dependencies: + '@shikijs/types': 1.22.0 + '@shikijs/vscode-textmate': 9.3.0 + oniguruma-to-js: 0.4.3 + + '@shikijs/engine-oniguruma@1.22.0': + dependencies: + '@shikijs/types': 1.22.0 + '@shikijs/vscode-textmate': 9.3.0 + + '@shikijs/types@1.22.0': + dependencies: + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@9.3.0': {} + + '@sinclair/typebox@0.27.8': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.13': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/node@22.7.5': + dependencies: + undici-types: 6.19.8 + + '@types/stack-utils@2.0.3': {} + + '@types/unist@3.0.3': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@ungap/structured-clone@1.2.0': {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + ccount@2.0.1: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + ci-info@3.9.0: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + comma-separated-tokens@2.0.3: {} + + dequal@2.0.3: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff-sequences@29.6.3: {} + + dprint@0.47.2: + optionalDependencies: + '@dprint/darwin-arm64': 0.47.2 + '@dprint/darwin-x64': 0.47.2 + '@dprint/linux-arm64-glibc': 0.47.2 + '@dprint/linux-arm64-musl': 0.47.2 + '@dprint/linux-x64-glibc': 0.47.2 + '@dprint/linux-x64-musl': 0.47.2 + '@dprint/win32-arm64': 0.47.2 + '@dprint/win32-x64': 0.47.2 + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + graceful-fs@4.2.11: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + hast-util-to-html@9.0.3: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + html-void-elements@3.0.0: {} + + is-number@7.0.0: {} + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.25.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.7.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + js-tokens@4.0.0: {} + + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + + micromark-util-character@2.1.0: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-encode@2.0.0: {} + + micromark-util-sanitize-uri@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + + micromark-util-symbol@2.0.0: {} + + micromark-util-types@2.0.0: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + oniguruma-to-js@0.4.3: + dependencies: + regex: 4.3.3 + + oxlint@0.9.10: + optionalDependencies: + '@oxlint/darwin-arm64': 0.9.10 + '@oxlint/darwin-x64': 0.9.10 + '@oxlint/linux-arm64-gnu': 0.9.10 + '@oxlint/linux-arm64-musl': 0.9.10 + '@oxlint/linux-x64-gnu': 0.9.10 + '@oxlint/linux-x64-musl': 0.9.10 + '@oxlint/win32-arm64': 0.9.10 + '@oxlint/win32-x64': 0.9.10 + + picocolors@1.1.0: {} + + picomatch@2.3.1: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + property-information@6.5.0: {} + + react-is@18.3.1: {} + + regex@4.3.3: {} + + shiki@1.22.0: + dependencies: + '@shikijs/core': 1.22.0 + '@shikijs/engine-javascript': 1.22.0 + '@shikijs/engine-oniguruma': 1.22.0 + '@shikijs/types': 1.22.0 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + + slash@3.0.0: {} + + space-separated-tokens@2.0.2: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + trim-lines@3.0.1: {} + + typescript@5.6.3: {} + + undici-types@6.19.8: {} + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + zwitch@2.0.4: {} diff --git a/packages/shikicode/src/core.ts b/packages/shikicode/src/core.ts new file mode 100644 index 0000000..7768ddf --- /dev/null +++ b/packages/shikicode/src/core.ts @@ -0,0 +1,285 @@ +import type { BundledLanguage, BundledTheme, Highlighter } from 'shiki' +import type { EditorPlugin } from './plugins/index.js' + +import { hookScroll } from './scroll.js' +import { injectStyle } from './style.js' + +export interface IndentOptions { + /** + * The number of spaces a tab is equal to. + * This setting is overridden based on the file contents when `detectIndentation` is on. + * Defaults to 4. + */ + readonly tabSize: number + /** + * Insert spaces when pressing `Tab`. + * This setting is overridden based on the file contents when `detectIndentation` is on. + * Defaults to true. + */ + readonly insertSpaces: boolean +} + +export interface EditorOptions extends IndentOptions { + /** + * Control the rendering of line numbers. + * Defaults to `on`. + */ + readonly lineNumbers: 'on' | 'off' + /** + * Should the editor be read only. + * Defaults to false. + */ + readonly readOnly: boolean + readonly language: BundledLanguage | 'plaintext' | 'txt' | 'text' | 'plain' | (string & {}) + readonly theme: BundledTheme | 'none' | (string & {}) +} + +export interface InitOptions extends Pick { + readonly value?: string +} + +export interface UpdateOptions extends Partial {} + +interface EditorOptionsWithValue extends EditorOptions { + readonly value: string +} + +interface ShikiCodeFactory { + create(domElement: HTMLElement, highlighter: Highlighter, options: InitOptions): ShikiCode + withOptions(options: UpdateOptions): ShikiCodeFactory + withPlugins(...plugins: readonly EditorPlugin[]): ShikiCodeFactory +} + +export interface ShikiCode { + readonly input: HTMLTextAreaElement + readonly output: HTMLDivElement + readonly container: HTMLElement + + /** + * The highlighter instance used by the editor. + */ + readonly highlighter: Highlighter + + /** + * The current value of the editor. + * Setting this value will update the editor and force a re-render. + */ + value: string + forceRender(value?: string): void + + /** + * Make sure the theme or language is loaded before calling this method. + */ + updateOptions(options: UpdateOptions): void + + addPlugin(plugin: EditorPlugin): void + + dispose(): void +} + +const defaultOptions = { + lineNumbers: 'on', + readOnly: false, + tabSize: 4, + insertSpaces: true, +} as const + +export function shikiCode(): ShikiCodeFactory { + const editor_options = { ...defaultOptions } + const plugin_list: EditorPlugin[] = [] + + return { + create(domElement: HTMLElement, highlighter: Highlighter, options: InitOptions): ShikiCode { + return create( + domElement, + highlighter, + { value: '', ...editor_options, ...options }, + plugin_list, + ) + }, + withOptions(options: UpdateOptions): ShikiCodeFactory { + Object.assign(editor_options, options) + return this + }, + withPlugins(...plugins: EditorPlugin[]): ShikiCodeFactory { + plugin_list.push(...plugins) + return this + }, + } +} + +function create( + domElement: HTMLElement, + highlighter: Highlighter, + editor_options: EditorOptionsWithValue, + plugin_list: EditorPlugin[], +): ShikiCode { + const doc = domElement.ownerDocument + + const output = doc.createElement('div') + const input = doc.createElement('textarea') + + initIO(input, output) + initContainer(domElement) + + domElement.append(input) + domElement.append(output) + + updateIO(input, output, editor_options) + updateContainer(domElement, highlighter, editor_options.theme) + + if (editor_options.value) { + input.value = editor_options.value + } + + const forceRender = (value = input.value) => { + render(output, highlighter, value, editor_options.language, editor_options.theme) + } + + const onInput = () => { + forceRender() + } + input.addEventListener('input', onInput) + + forceRender() + + const cleanup = [ + () => { + input.removeEventListener('input', onInput) + }, + hookScroll(input, output), + injectStyle(doc), + ] + + const editor: ShikiCode = { + input, + output, + container: domElement, + + get value() { + return input.value + }, + set value(code) { + input.value = code + forceRender(code) + }, + + get highlighter() { + return highlighter + }, + + forceRender, + updateOptions(newOptions) { + if (shouldUpdateIO(editor_options, newOptions)) { + updateIO(input, output, newOptions) + } + + if (shouldUpdateContainer(editor_options, newOptions)) { + updateContainer(domElement, highlighter, newOptions.theme!) + } + + const should_rerender = shouldRerender(editor_options, newOptions) + + Object.assign(editor_options, newOptions) + + if (should_rerender) { + forceRender() + } + }, + + addPlugin(plugin) { + cleanup.push(plugin(this, editor_options)) + }, + dispose() { + cleanup.forEach(fn => fn()) + input.remove() + output.remove() + }, + } + + for (const plugin of plugin_list) { + cleanup.push(plugin(editor, editor_options)) + } + + return editor +} + +function initContainer(container: HTMLElement) { + container.style.color = 'var(--fg)' + container.style.backgroundColor = 'var(--bg)' + container.style.position = 'relative' +} + +function shouldUpdateContainer(config: EditorOptions, newOptions: UpdateOptions) { + return newOptions.theme !== void 0 && newOptions.theme !== config.theme +} + +function updateContainer(container: HTMLElement, highlighter: Highlighter, theme_name: string) { + const theme = highlighter.getTheme(theme_name) + container.style.setProperty('--fg', theme.fg) + container.style.setProperty('--bg', theme.bg) +} + +function initIO(input: HTMLTextAreaElement, output: HTMLElement) { + input.setAttribute('autocapitalize', 'off') + input.setAttribute('autocomplete', 'off') + input.setAttribute('autocorrect', 'off') + input.setAttribute('spellcheck', 'false') + + input.classList.add('shikicode', 'input') + output.classList.add('shikicode', 'output') + output.setAttribute('inert', '') +} + +function shouldUpdateIO(config: EditorOptions, newOptions: UpdateOptions) { + return ( + (newOptions.lineNumbers !== void 0 && newOptions.lineNumbers !== config.lineNumbers) || + (newOptions.tabSize !== void 0 && newOptions.tabSize !== config.tabSize) || + (newOptions.readOnly !== void 0 && newOptions.readOnly !== config.readOnly) + ) +} + +function updateIO(input: HTMLTextAreaElement, output: HTMLElement, options: UpdateOptions) { + switch (options.lineNumbers) { + case 'on': { + input.classList.add('line-numbers') + output.classList.add('line-numbers') + break + } + case 'off': { + input.classList.remove('line-numbers') + output.classList.remove('line-numbers') + break + } + } + + if (options.tabSize !== void 0) { + input.style.setProperty('--tab-size', options.tabSize.toString()) + output.style.setProperty('--tab-size', options.tabSize.toString()) + } + + if (options.readOnly !== void 0) { + input.readOnly = options.readOnly + } +} + +function render( + output: HTMLElement, + highlighter: Highlighter, + value: string, + lang: string, + theme: string, +) { + const { codeToHtml } = highlighter + output.innerHTML = codeToHtml(value, { + lang, + theme, + }) +} + +function shouldRerender(options: EditorOptions, newOptions: UpdateOptions) { + return ( + (newOptions.theme !== void 0 && newOptions.theme !== options.theme) || + (newOptions.language !== void 0 && newOptions.language !== options.language) + ) +} diff --git a/packages/shikicode/src/index.ts b/packages/shikicode/src/index.ts new file mode 100644 index 0000000..4edf852 --- /dev/null +++ b/packages/shikicode/src/index.ts @@ -0,0 +1 @@ +export * from './core.js' diff --git a/packages/shikicode/src/plugins/autoload.ts b/packages/shikicode/src/plugins/autoload.ts new file mode 100644 index 0000000..0207254 --- /dev/null +++ b/packages/shikicode/src/plugins/autoload.ts @@ -0,0 +1,43 @@ +import type { BundledLanguage, BundledTheme } from 'shiki' +import type { IDisposable, ShikiCode } from './index.js' + +/** + * Automatically load languages and themes when they are not already loaded. + * + * It's recommended to handle shiki highlighter by yourself if you know all the languages and themes you will use. + * This plugin will convert the `updateOptions` method to async method. + */ +export function autoload(editor: ShikiCode): IDisposable { + const updateOptions = editor.updateOptions + + editor.updateOptions = async newOptions => { + const themes = editor.highlighter.getLoadedThemes() + const langs = editor.highlighter.getLoadedLanguages() + + const task_list = [] + + if ( + newOptions.theme !== void 0 && + newOptions.theme !== 'none' && + !themes.includes(newOptions.theme) + ) { + task_list.push(editor.highlighter.loadTheme(newOptions.theme as unknown as BundledTheme)) + } + + if ( + newOptions.language !== void 0 && + newOptions.language !== 'text' && + !langs.includes(newOptions.language) + ) { + task_list.push(editor.highlighter.loadLanguage(newOptions.language as BundledLanguage)) + } + + await Promise.all(task_list) + + updateOptions(newOptions) + } + + return () => { + editor.updateOptions = updateOptions + } +} diff --git a/packages/shikicode/src/plugins/closing_pairs.ts b/packages/shikicode/src/plugins/closing_pairs.ts new file mode 100644 index 0000000..55ac654 --- /dev/null +++ b/packages/shikicode/src/plugins/closing_pairs.ts @@ -0,0 +1,216 @@ +import { setRangeText } from './common.js' +import type { EditorPlugin } from './index.js' + +export type ClosingPair = readonly [open: string, close: string] + +export type ClosingPairsRules = { + readonly language: string + readonly pairs: ClosingPair[] +} + +interface ResolvedClosingPairsRules { + auto_closing_pairs_open: Map + auto_closing_pairs_close: Map + auto_closing_pairs: Set +} + +const should_auto_close = ' \t\n.,;)]}>=' + +/** + * A plugin that automatically inserts closing pairs. + */ +export function hookClosingPairs(...pairs_rule_list: readonly ClosingPairsRules[]): EditorPlugin { + const rules = new Map() + + const list = default_pairs.concat(pairs_rule_list) + + for (const { language, pairs } of list) { + const auto_closing_pairs_open = new Map() + const auto_closing_pairs_close = new Map() + const auto_closing_pairs = new Set() + pairs.forEach(([open, close]) => { + auto_closing_pairs_open.set(open, close) + auto_closing_pairs_close.set(close, open) + auto_closing_pairs.add(open + close) + }) + rules.set(language, { + auto_closing_pairs_open, + auto_closing_pairs_close, + auto_closing_pairs, + }) + } + + return ({ input }, options) => { + const onKeydown = (e: KeyboardEvent) => { + const config = rules.get(options.language) + if (!config) { + return + } + + const { selectionStart, selectionEnd } = input + + if (isBackspace(e)) { + if (selectionStart !== selectionEnd) { + return + } + + const slice = input.value.slice(selectionStart - 1, selectionStart + 1) + if (config.auto_closing_pairs.has(slice)) { + input.setSelectionRange(selectionStart - 1, selectionStart + 1) + } + return + } + + if ( + !config.auto_closing_pairs_open.has(e.key) && + !config.auto_closing_pairs_close.has(e.key) + ) { + return + } + + // add pairs surrounding the selection + if (selectionStart !== selectionEnd && config.auto_closing_pairs_open.has(e.key)) { + e.preventDefault() + const text = input.value.slice(selectionStart, selectionEnd) + const left = e.key + const right = config.auto_closing_pairs_open.get(left)! + setRangeText(input, left + text + right, selectionStart, selectionEnd, 'select') + input.dispatchEvent(new Event('input')) + input.dispatchEvent(new Event('change')) + input.setSelectionRange(selectionStart + 1, selectionEnd + 1) + return + } + + // add pairs at the cursor + if ( + selectionStart === selectionEnd && + config.auto_closing_pairs_open.has(e.key) && + should_auto_close.includes(input.value[selectionStart] || '') + ) { + e.preventDefault() + const left = e.key + const right = config.auto_closing_pairs_open.get(left)! + setRangeText(input, left + right, selectionStart, selectionEnd, 'start') + input.dispatchEvent(new Event('input')) + input.dispatchEvent(new Event('change')) + input.setSelectionRange(selectionStart + 1, selectionEnd + 1) + return + } + + // skip right pairs + if ( + selectionStart === selectionEnd && + selectionStart > 0 && + config.auto_closing_pairs.has(input.value.slice(selectionStart - 1, selectionStart + 1)) + ) { + input.setSelectionRange(selectionStart, selectionEnd + 1) + } + } + + input.addEventListener('keydown', onKeydown) + + return () => { + input.removeEventListener('keydown', onKeydown) + } + } +} + +function isBackspace(e: KeyboardEvent) { + return e.key === 'Backspace' && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey +} + +export const pairs_parentheses = ['(', ')'] satisfies ClosingPair +export const pairs_brackets = ['[', ']'] satisfies ClosingPair +export const pairs_braces = ['{', '}'] satisfies ClosingPair +export const pairs_angle = ['<', '>'] satisfies ClosingPair +export const pairs_quotes = ['"', '"'] satisfies ClosingPair +export const pairs_single_quotes = ["'", "'"] satisfies ClosingPair +export const pairs_backticks = ['`', '`'] satisfies ClosingPair + +const c_lang_pairs: ClosingPair[] = [ + pairs_parentheses, + pairs_brackets, + pairs_braces, + pairs_quotes, + pairs_single_quotes, +] + +const c_lang_pairs_with_backticks: ClosingPair[] = [ + pairs_parentheses, + pairs_brackets, + pairs_braces, + pairs_quotes, + pairs_single_quotes, + pairs_backticks, +] + +export const default_pairs: readonly ClosingPairsRules[] = [ + { + language: 'c', + pairs: c_lang_pairs, + }, + { + language: 'cpp', + pairs: c_lang_pairs, + }, + { + language: 'css', + pairs: c_lang_pairs, + }, + { + language: 'csharp', + pairs: c_lang_pairs, + }, + { + language: 'dart', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'go', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'java', + pairs: c_lang_pairs, + }, + { + language: 'json', + pairs: [pairs_brackets, pairs_braces, pairs_quotes], + }, + { + language: 'javascript', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'typescript', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'jsx', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'tsx', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'php', + pairs: c_lang_pairs, + }, + { + language: 'python', + pairs: c_lang_pairs, + }, + { + language: 'rust', + pairs: [pairs_parentheses, pairs_brackets, pairs_braces, pairs_quotes], + }, + { + language: 'ruby', + pairs: c_lang_pairs_with_backticks, + }, + { + language: 'sql', + pairs: c_lang_pairs_with_backticks, + }, +] diff --git a/packages/shikicode/src/plugins/common.ts b/packages/shikicode/src/plugins/common.ts new file mode 100644 index 0000000..43dcf2b --- /dev/null +++ b/packages/shikicode/src/plugins/common.ts @@ -0,0 +1,131 @@ +export function floorTab(width: number, tabSize: number): number { + switch (tabSize) { + case 2: + return width & ~1 + case 4: + return width & ~3 + case 8: + return width & ~7 + } + return Math.floor(width / tabSize) * tabSize +} + +export function ceilTab(width: number, tabSize: number): number { + switch (tabSize) { + case 2: + return (width + 1) & ~1 + case 4: + return (width + 3) & ~3 + case 8: + return (width + 7) & ~7 + } + return Math.ceil(width / tabSize) * tabSize +} + +/** + * A offset in a position is the gap between two adjacent characters. The methods here + * work with a concept called "visible width". A visible width is a very rough approximation + * of the horizontal screen position of a offset. For example, using a tab size of 4: + * ```txt + * |||T|ext + * | | | \---- offset = 3, visible width = 9 + * | | \------ offset = 2, visible width = 8 + * | \------------ offset = 1, visible width = 4 + * \------------------ offset = 0, visible width = 0 + * ``` + * + * **ATTENTION**: This offset is 0-based + * + * **NOTE**: Visual columns do not work well for RTL text or variable-width fonts or characters. + * + */ +export function visibleWidthFromLeft( + content: string, + offset: number, + tabSize: number, + left?: number, +): [width: number, span: number] { + if (left === void 0) { + left = offset + while (left > 0 && content[left - 1] !== '\n') { + left-- + } + } + let width = 0 + for (let i = left; i < offset; i++) { + width++ + if (content[i] === '\t') { + width = ceilTab(width, tabSize) + } + } + return [width, offset - left] +} + +export function visibleWidthLeadingSpace( + line: string, + tabSize: number, +): [width: number, span: number] { + let width = 0 + let i = 0 + while (i < line.length) { + if (line[i] === ' ') { + width++ + } else if (line[i] === '\t') { + width = ceilTab(width + 1, tabSize) + } else { + break + } + i++ + } + return [width, i] +} + +/** + * Instead of using the `setRangeText` method, + * prefer to use the `execCommand` method to preserve the undo stack. + */ +export function setRangeText( + input: HTMLTextAreaElement, + replacement: string, + start: number, + end: number, + selectionMode?: SelectionMode, +) { + input.setSelectionRange(start, end) + input.ownerDocument.execCommand('insertText', false, replacement) + switch (selectionMode) { + case 'start': { + input.setSelectionRange(start, start) + break + } + case 'end': { + input.setSelectionRange(start + replacement.length, start + replacement.length) + break + } + + case 'select': + default: { + input.setSelectionRange(start, start + replacement.length) + break + } + } +} + +export interface InputState { + /** + * The whole text content. + */ + value: string + /** + * The start of the selection. + */ + selectionStart: number + /** + * The end of the selection. + */ + selectionEnd: number + /** + * The direction of the selection. + */ + selectionDirection?: 'forward' | 'backward' | 'none' +} diff --git a/packages/shikicode/src/plugins/index.ts b/packages/shikicode/src/plugins/index.ts new file mode 100644 index 0000000..ccaf05a --- /dev/null +++ b/packages/shikicode/src/plugins/index.ts @@ -0,0 +1,12 @@ +import type { EditorOptions, ShikiCode } from '../core.js' + +export type IDisposable = () => void +export type { EditorOptions, IndentOptions, ShikiCode } from '../core.js' + +export type EditorPlugin = { + (editor: ShikiCode, options: EditorOptions): IDisposable +} + +export * from './autoload.js' +export * from './closing_pairs.js' +export * from './tab.js' diff --git a/packages/shikicode/src/plugins/tab.ts b/packages/shikicode/src/plugins/tab.ts new file mode 100644 index 0000000..99910c8 --- /dev/null +++ b/packages/shikicode/src/plugins/tab.ts @@ -0,0 +1,445 @@ +import { + ceilTab, + floorTab, + setRangeText, + visibleWidthFromLeft, + visibleWidthLeadingSpace, + type InputState, +} from './common.js' +import type { IDisposable, IndentOptions, ShikiCode } from './index.js' + +export interface PatchAction { + value: string + start: number + end: number + mode?: SelectionMode +} + +export interface SelectAction { + start: number + end: number + direction?: 'forward' | 'backward' | 'none' +} + +export interface Action { + /** + * The patched text content. + */ + patch?: PatchAction + /** + * The new selection. + */ + select?: SelectAction +} + +const empty_action: Action = {} + +export function indentText(input: InputState, options: IndentOptions): Action { + if ( + input.selectionStart !== input.selectionEnd && + (bothEndsSelected(input.value, input.selectionStart, input.selectionEnd) || + input.value.slice(input.selectionStart, input.selectionEnd).includes('\n')) + ) { + return blockIndentText(input, options) + } + + return simpleIndentText(input, options) +} + +function simpleIndentText(input: InputState, options: IndentOptions): Action { + const { value, selectionStart, selectionEnd } = input + const { tabSize, insertSpaces } = options + + if (!insertSpaces) { + return { + patch: { + value: '\t', + start: selectionStart, + end: selectionEnd, + mode: 'end', + }, + } + } + + const [width_from_left] = visibleWidthFromLeft(value, selectionStart, tabSize) + const indent = ' '.repeat(ceilTab(width_from_left + 1, tabSize) - width_from_left) + return { + patch: { + value: indent, + start: selectionStart, + end: selectionEnd, + mode: 'end', + }, + } +} + +function blockIndentText(input: InputState, options: IndentOptions): Action { + const { tabSize, insertSpaces } = options + const { value, selectionStart, selectionEnd, selectionDirection } = input + + const block_start = getLineStart(value, selectionStart) + const block_end = getBlockLineEnd(value, selectionEnd) + + const block = value.slice(block_start, block_end) + + const replacement = block.replaceAll(/^[ \t]*/gm, (leading, offset, str) => { + if (str[offset] === '\n' || str[offset] === '\r' || offset === block_end) return leading + + let [tab_width] = visibleWidthFromLeft(leading, leading.length, tabSize, 0) + tab_width = ceilTab(tab_width + 1, tabSize) + + if (insertSpaces) { + return ' '.repeat(tab_width) + } + return '\t'.repeat(tab_width / tabSize) + }) + + const patch = { + value: replacement, + start: block_start, + end: block_end, + mode: 'end', + } satisfies PatchAction + + // restore selection + // By default, the selection is anchored at both ends. + const select = { + start: selectionStart, + end: selectionEnd + replacement.length - block.length, + direction: selectionDirection, + } satisfies SelectAction + + if (selectionStart !== block_start) { + const line_start = block_start + const cursor_offset = selectionStart - line_start + const line = value.slice(line_start, selectionStart) + const [, old_leading_offset] = visibleWidthLeadingSpace(line, tabSize) + const [, max_leading_offset] = visibleWidthLeadingSpace(replacement, tabSize) + + if (cursor_offset > old_leading_offset) { + // |||T|ext + // ^ + select.start += max_leading_offset - old_leading_offset + } else if (cursor_offset > max_leading_offset) { + // | | |Text (old) + // ^ + // ||||Text (new) + // ^ + select.start = line_start + max_leading_offset + } + } + + if (selectionEnd < block_end) { + const line_start = getLineStart(value, selectionEnd) + const cursor_offset = selectionEnd - line_start + const line = value.slice(line_start, selectionEnd) + const [, old_leading_offset] = visibleWidthLeadingSpace(line, tabSize) + + const new_bottom_line_offset = getLineStart(replacement, replacement.length) + const new_bottom_line = replacement.slice(new_bottom_line_offset) + const [, max_leading_offset] = visibleWidthLeadingSpace(new_bottom_line, tabSize) + + if (cursor_offset <= old_leading_offset) { + select.end = block_start + new_bottom_line_offset + cursor_offset + + if (cursor_offset > max_leading_offset) { + select.end += max_leading_offset - old_leading_offset + } + } + } + + return { + patch, + select, + } satisfies Action +} + +export function outdentText(input: InputState, options: IndentOptions): Action { + const { tabSize, insertSpaces } = options + const { value, selectionStart, selectionEnd, selectionDirection } = input + + const block_start = getLineStart(value, selectionStart) + const block_end = getBlockLineEnd(value, Math.max(selectionEnd, selectionStart + 1)) + + const block = value.slice(block_start, block_end) + + const replacement = block.replaceAll(/^[ \t]*/gm, leading => { + let [tab_width] = visibleWidthFromLeft(leading, leading.length, tabSize, 0) + tab_width = floorTab(tab_width - 1, tabSize) + + if (tab_width <= 0) return '' + + if (insertSpaces) { + return ' '.repeat(tab_width) + } + return '\t'.repeat(tab_width / tabSize) + }) + if (replacement === block) return empty_action + + const patch = { + value: replacement, + start: block_start, + end: block_end, + mode: 'end', + } satisfies PatchAction + + // restore selection + // By default, the selection is anchored at both ends. + const select = { + start: selectionStart, + end: selectionEnd + replacement.length - block.length, + direction: selectionDirection, + } satisfies SelectAction + + if (selectionStart !== block_start) { + const line_start = block_start + const cursor_offset = selectionStart - line_start + const line = value.slice(line_start, selectionStart) + const [, old_leading_offset] = visibleWidthLeadingSpace(line, tabSize) + const [, max_leading_offset] = visibleWidthLeadingSpace(replacement, tabSize) + + if (cursor_offset > old_leading_offset) { + // |||T|ext + // ^ + select.start += max_leading_offset - old_leading_offset + } else if (cursor_offset > max_leading_offset) { + // | | |Text (old) + // ^ + // ||||Text (new) + // ^ + select.start = line_start + max_leading_offset + } + } + + if (selectionEnd < block_end) { + const line_start = getLineStart(value, selectionEnd) + const cursor_offset = selectionEnd - line_start + const line = value.slice(line_start, selectionEnd) + const [, old_leading_offset] = visibleWidthLeadingSpace(line, tabSize) + + const new_bottom_line_offset = getLineStart(replacement, replacement.length) + const new_bottom_line = replacement.slice(new_bottom_line_offset) + const [, max_leading_offset] = visibleWidthLeadingSpace(new_bottom_line, tabSize) + + if (cursor_offset <= old_leading_offset) { + select.end = block_start + new_bottom_line_offset + cursor_offset + + if (cursor_offset > max_leading_offset) { + select.end += max_leading_offset - old_leading_offset + } + } + } + + return { + patch, + select, + } satisfies Action +} + +function enter(input: InputState, options: IndentOptions): Action { + if (input.selectionStart !== input.selectionEnd) { + return empty_action + } + const { value, selectionStart } = input + const line_start = getLineStart(value, selectionStart) + if (line_start === selectionStart) { + return empty_action + } + + const line = value.slice(line_start, selectionStart) + let [leading_space] = visibleWidthLeadingSpace(line, options.tabSize) + leading_space = floorTab(leading_space, options.tabSize) + let indent_space = leading_space + + switch (value[selectionStart - 1]) { + case '(': + case '[': + case '{': { + indent_space += options.tabSize + } + } + + let replacement = '\n' + if (options.insertSpaces) { + replacement += ' '.repeat(indent_space) + } else { + replacement += '\t'.repeat(indent_space / options.tabSize) + } + + let select: SelectAction | undefined + + switch (value.slice(selectionStart - 1, selectionStart + 1)) { + case '{}': + case '[]': + case '()': { + select = { + start: selectionStart + replacement.length, + end: selectionStart + replacement.length, + direction: 'none', + } + + if (options.insertSpaces) { + replacement += '\n' + ' '.repeat(leading_space) + } else { + replacement += '\n' + '\t'.repeat(leading_space / options.tabSize) + } + } + } + + return { + patch: { + value: replacement, + start: selectionStart, + end: selectionStart, + mode: 'end', + }, + select, + } +} + +function backspace(input: InputState, options: IndentOptions): Action { + const { value, selectionStart, selectionEnd } = input + if (selectionStart !== selectionEnd) { + return empty_action + } + + if (value[selectionStart - 1] !== ' ') { + return empty_action + } + + const line_start = getLineStart(value, selectionStart) + let width = 0 + let last_tab_stop = line_start + for (let i = line_start; i < selectionStart - 1; i++) { + switch (value[i]) { + case ' ': { + width++ + if (width % options.tabSize === 0) { + last_tab_stop = i + } + break + } + case '\t': { + last_tab_stop = i + width = ceilTab(width + 1, options.tabSize) + break + } + default: { + return empty_action + } + } + } + + return { + select: { + start: last_tab_stop, + end: selectionStart, + direction: 'none', + }, + } +} + +function bothEndsSelected(text: string, start: number, end: number): boolean { + const is_start = start === 0 || text[start - 1] === '\n' + const is_end = end === text.length || text[end] === '\n' || text[end] === '\r' + return start !== end && is_start && is_end +} + +function getLineStart(text: string, index: number): number { + while (index > 0 && text[index - 1] !== '\n') { + index-- + } + return index +} + +/** + * Get the end index of the line. + * - all suffix "\n" and "\r" are ignored. + * - text[end] === "\n" || text[end] === "\r" || end === text.length + * - text.slice(start, end) should not include "\n" at the end. + */ +function getBlockLineEnd(text: string, index: number): number { + if (text[index - 1] === '\n') { + index-- + } + + while (index > 0 && (index === text.length || text[index] === '\n' || text[index] === '\r')) { + index-- + } + + return getLineEnd(text, index) +} + +function getLineEnd(text: string, index: number): number { + while (index < text.length && text[index] !== '\n' && text[index] !== '\r') { + index++ + } + + return index +} + +/** + * A plugin that automatically inserts or removes indentation. + */ +export function hookTab({ input }: ShikiCode, options: IndentOptions): IDisposable { + const onKeydown = (e: KeyboardEvent) => { + switch (e.key) { + case 'Tab': { + e.preventDefault() + + const action = e.shiftKey ? outdentText : indentText + const { patch, select } = action(e.target as HTMLTextAreaElement, options) + if (patch) { + setRangeText(input, patch.value, patch.start, patch.end, patch.mode) + input.dispatchEvent(new Event('input')) + input.dispatchEvent(new Event('change')) + } + if (select) { + input.setSelectionRange(select.start, select.end, select.direction) + input.dispatchEvent(new Event('selectionchange')) + } + break + } + + case 'Enter': { + const { patch, select } = enter(e.target as HTMLTextAreaElement, options) + if (patch || select) { + e.preventDefault() + } + if (patch) { + setRangeText(input, patch.value, patch.start, patch.end, patch.mode) + input.dispatchEvent(new Event('input')) + input.dispatchEvent(new Event('change')) + } + if (select) { + input.setSelectionRange(select.start, select.end, select.direction) + input.dispatchEvent(new Event('selectionchange')) + } + break + } + + case 'Backspace': { + const { select } = backspace(e.target as HTMLTextAreaElement, options) + if (select) { + input.setSelectionRange(select.start, select.end, select.direction) + input.dispatchEvent(new Event('selectionchange')) + } + + break + } + + case 'Escape': { + input.blur() + break + } + + default: + return + } + } + + input.addEventListener('keydown', onKeydown) + return () => { + input.removeEventListener('keydown', onKeydown) + } +} diff --git a/packages/shikicode/src/scroll.ts b/packages/shikicode/src/scroll.ts new file mode 100644 index 0000000..cd63efd --- /dev/null +++ b/packages/shikicode/src/scroll.ts @@ -0,0 +1,11 @@ +export function hookScroll(input: HTMLElement, output: HTMLElement) { + const onScroll = () => { + output.scrollTo(input.scrollLeft, input.scrollTop) + } + + input.addEventListener('scroll', onScroll) + + return () => { + input.removeEventListener('scroll', onScroll) + } +} diff --git a/packages/shikicode/src/style.ts b/packages/shikicode/src/style.ts new file mode 100644 index 0000000..512e811 --- /dev/null +++ b/packages/shikicode/src/style.ts @@ -0,0 +1,113 @@ +const style = `.shikicode.input, .shikicode.output { + position: absolute; + margin: 0; + inset: 0; + border: 0; + padding: 0; + font-size: inherit; + line-height: inherit; + tab-size: var(--tab-size); +} + +.shikicode.input, .shikicode.output, .shikicode.output code { + font-family: var(--font-family, monospace); +} + +.shikicode.input { + box-sizing: border-box; + outline: none; + background-color: transparent; + padding-left: 2em; + width: 100%; + height: 100%; + overflow: auto; + resize: none; + color: transparent; + caret-color: var(--fg, black); + white-space: pre; +} + +.shikicode.output { + counter-reset: shiki-line 0; + overflow: hidden; + pointer-events: none; +} + +.shikicode.output > pre { + display: contents; +} + +.shikicode.output .line { + counter-increment: shiki-line 1; +} + +.shikicode.output .line::before { + display: inline-block; + position: sticky; + left: 0; + box-sizing: border-box; + background-color: var(--bg); + width: 2em; + content: counter(shiki-line); + color: var(--bg); + text-align: right; +} + +.shikicode.output.line-numbers .line::before { + padding-right: 2em; + width: 5em; + color: var(--fg); +} + +.shikicode.input.line-numbers { + padding-left: 5em; +} +` + +function noop() {} + +export function injectStyle(doc: Document) { + const hash = `shikicode-${djb2(style).toString(36)}` + if (doc.getElementById(hash)) return noop + const element = doc.createElement('style') + element.id = hash + element.append(doc.createTextNode('')) + doc.head.append(element) + + try { + const sheet = getSheet(element, doc) + sheet.insertRule(style) + } catch (e) { + element.append(doc.createTextNode(style)) + } + return () => { + element.remove() + } +} + +function djb2(s: string, hash = 5381) { + let i = s.length + + while (i) { + hash = (hash * 33) ^ s.charCodeAt(--i) + } + + return hash +} + +function getSheet(tag: HTMLStyleElement, doc: Document): CSSStyleSheet { + if (tag.sheet) { + return tag.sheet + } + + // Avoid Firefox quirk where the style element might not have a sheet property + const { styleSheets } = doc + for (let i = 0, l = styleSheets.length; i < l; i++) { + const sheet = styleSheets[i] + if (sheet.ownerNode === tag) { + return sheet + } + } + + throw new Error('Could not find CSSStyleSheet object') +} diff --git a/packages/shikicode/test/__snapshots__/tab.test.ts.snap b/packages/shikicode/test/__snapshots__/tab.test.ts.snap new file mode 100644 index 0000000..2e41d0a --- /dev/null +++ b/packages/shikicode/test/__snapshots__/tab.test.ts.snap @@ -0,0 +1,745 @@ +// Bun Snapshot v1, https://goo.gl/fbAQLP + +exports[`Editor Commands - ShiftCommand basic usage 1`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 0, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 4, + "selectionStart": 4, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand basic usage 2`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 2, + "selectionStart": 2, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 4, + "selectionStart": 4, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand basic usage 3`] = ` +{ + "config": { + "insertSpaces": false, + "tabSize": 2, + }, + "input": { + "selectionEnd": 33, + "selectionStart": 33, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 34, + "selectionStart": 34, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand single line 1`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 13, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 17, + "selectionStart": 0, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand single line 2`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 14, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 18, + "selectionStart": 0, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand single line 3`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 31, + "selectionStart": 14, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 41, + "selectionStart": 14, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand multiple lines 1`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 14, + "selectionStart": 3, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 18, + "selectionStart": 7, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand multiple lines 2`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 18, + "selectionStart": 9, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 32, + "selectionStart": 13, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand multiple lines 3`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 31, + "selectionStart": 9, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 45, + "selectionStart": 13, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand multiple lines 4`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 15, + "selectionStart": 3, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 19, + "selectionStart": 7, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand multiple lines 5`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 33, + "selectionStart": 15, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 43, + "selectionStart": 15, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - ShiftCommand multiple lines 6`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 50, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 72, + "selectionStart": 0, + "value": [ + " My First Line", + " My Second Line", + " Third Line", + "", + " 123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand basic usage 1`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 0, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 0, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand basic usage 2`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 2, + "selectionStart": 2, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 2, + "selectionStart": 2, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand basic usage 3`] = ` +{ + "config": { + "insertSpaces": false, + "tabSize": 2, + }, + "input": { + "selectionEnd": 33, + "selectionStart": 33, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 32, + "selectionStart": 32, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand single line 1`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 13, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 13, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand single line 2`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 14, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 14, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand single line 3`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 31, + "selectionStart": 14, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 33, + "selectionStart": 14, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand multiple lines 1`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 14, + "selectionStart": 3, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 14, + "selectionStart": 3, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand multiple lines 2`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 18, + "selectionStart": 9, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 20, + "selectionStart": 9, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand multiple lines 3`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 31, + "selectionStart": 9, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 33, + "selectionStart": 9, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand multiple lines 4`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 15, + "selectionStart": 3, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 15, + "selectionStart": 3, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand multiple lines 5`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 33, + "selectionStart": 15, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 33, + "selectionStart": 15, + "value": [ + "My First Line", + " My Second Line", + "Third Line", + "", + "123", + ], + }, +} +`; + +exports[`Editor Commands - UnShiftCommand multiple lines 6`] = ` +{ + "config": { + "insertSpaces": true, + "tabSize": 4, + }, + "input": { + "selectionEnd": 50, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + " Third Line", + "", + "123", + ], + }, + "output": { + "selectionEnd": 48, + "selectionStart": 0, + "value": [ + "My First Line", + " My Second Line", + "Third Line", + "", + "123", + ], + }, +} +`; diff --git a/packages/shikicode/test/tab.test.ts b/packages/shikicode/test/tab.test.ts new file mode 100644 index 0000000..bfca6c9 --- /dev/null +++ b/packages/shikicode/test/tab.test.ts @@ -0,0 +1,239 @@ +import { Action, PatchAction, SelectAction, State, indentText, outdentText } from '../src/plugins' + +interface TabConfig { + tabSize: number + insertSpaces: boolean +} + +const space_4 = { + tabSize: 4, + insertSpaces: true, +} + +const tab_4 = { + tabSize: 4, + insertSpaces: false, +} + +const space_2 = { + tabSize: 2, + insertSpaces: true, +} + +const tab_2 = { + tabSize: 2, + insertSpaces: false, +} + +function setRangeText(state: State, patch: PatchAction): State { + const [start, mid, end] = [ + state.value.slice(0, patch.start), + patch.value, + state.value.slice(patch.end), + ] + + const new_state = { ...state } + + switch (patch.mode) { + case 'start': + new_state.selectionStart = new_state.selectionEnd = start.length + break + case 'end': + new_state.selectionStart = new_state.selectionEnd = start.length + mid.length + break + case 'select': + default: + // Unfortunately, we cannot mimic the behavior of `preserve`. + new_state.selectionStart = start.length + new_state.selectionEnd = start.length + mid.length + break + } + + new_state.value = start + mid + end + return new_state +} + +function setSelectionRange(state: State, select: SelectAction): State { + return { value: state.value, selectionStart: select.start, selectionEnd: select.end } +} + +function applyEdit(state: State, action?: Action): State { + if (!action) { + return state + } + if (action.patch) { + state = setRangeText(state, action.patch) + } + if (action.select) { + state = setSelectionRange(state, action.select) + } + return state +} + +const simpleText = 'My First Line\n\t\tMy Second Line\n Third Line\n\n123' + +describe('Editor Commands - ShiftCommand', () => { + test('basic usage', () => { + testShiftCommand(simpleText, 0, 0, space_4) + }) + + test('basic usage', () => { + testShiftCommand(simpleText, 2, 2, space_4) + }) + + test('basic usage', () => { + const select = simpleText.indexOf('Third Line') - 2 + testShiftCommand(simpleText, select, select, tab_2) + }) + + test('single line', () => { + const select = 'My First Line' + testShiftCommand(simpleText, 0, select.length, space_4) + }) + + test('single line', () => { + const select = 'My First Line\n' + testShiftCommand(simpleText, 0, select.length, space_4) + }) + + test('single line', () => { + const select = '\t\tMy Second Line\n' + const start = simpleText.indexOf(select) + testShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'First Line\n' + const start = simpleText.indexOf(select) + testShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'Line\n\t\tMy' + const start = simpleText.indexOf(select) + testShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'Line\n\t\tMy Second Line\n' + const start = simpleText.indexOf(select) + testShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'First Line\n\t' + const start = simpleText.indexOf(select) + testShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = '\tMy Second Line\n ' + const start = simpleText.indexOf(select) + testShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + testShiftCommand(simpleText, 0, simpleText.length, space_4) + }) +}) + +describe('Editor Commands - UnShiftCommand', () => { + test('basic usage', () => { + testUnShiftCommand(simpleText, 0, 0, space_4) + }) + + test('basic usage', () => { + testUnShiftCommand(simpleText, 2, 2, space_4) + }) + + test('basic usage', () => { + const select = simpleText.indexOf('Third Line') - 2 + testUnShiftCommand(simpleText, select, select, tab_2) + }) + + test('single line', () => { + const select = 'My First Line' + testUnShiftCommand(simpleText, 0, select.length, space_4) + }) + + test('single line', () => { + const select = 'My First Line\n' + testUnShiftCommand(simpleText, 0, select.length, space_4) + }) + + test('single line', () => { + const select = '\t\tMy Second Line\n' + const start = simpleText.indexOf(select) + testUnShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'First Line\n' + const start = simpleText.indexOf(select) + testUnShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'Line\n\t\tMy' + const start = simpleText.indexOf(select) + testUnShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'Line\n\t\tMy Second Line\n' + const start = simpleText.indexOf(select) + testUnShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = 'First Line\n\t' + const start = simpleText.indexOf(select) + testUnShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + const select = '\tMy Second Line\n ' + const start = simpleText.indexOf(select) + testUnShiftCommand(simpleText, start, start + select.length, space_4) + }) + + test('multiple lines', () => { + testUnShiftCommand(simpleText, 0, simpleText.length, space_4) + }) +}) + +function testShiftCommand( + value: string, + selectionStart: number, + selectionEnd: number, + config: TabConfig, +): void { + const state = { value, selectionStart, selectionEnd } + + const action = indentText(state, config) + const result = applyEdit(state, action) + + expect({ config, input: handleState(state), output: handleState(result) }).toMatchSnapshot() +} + +function testUnShiftCommand( + value: string, + selectionStart: number, + selectionEnd: number, + config: TabConfig, +): void { + const state = { value, selectionStart, selectionEnd } + + const action = outdentText(state, config) + const result = applyEdit(state, action) + + expect({ config, input: handleState(state), output: handleState(result) }).toMatchSnapshot() +} + +function handleState(state: State) { + const lines = state.value.split(/\r\n|\n/) + return { + ...state, + value: lines, + } +} diff --git a/packages/shikicode/test/test.html b/packages/shikicode/test/test.html new file mode 100644 index 0000000..b8d44f5 --- /dev/null +++ b/packages/shikicode/test/test.html @@ -0,0 +1,75 @@ + +
+ + + diff --git a/packages/shikicode/tsconfig.json b/packages/shikicode/tsconfig.json new file mode 100644 index 0000000..27074b9 --- /dev/null +++ b/packages/shikicode/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "strict": true, + "skipLibCheck": true, + "target": "esnext", + "module": "esnext", + "moduleResolution": "bundler", + "forceConsistentCasingInFileNames": true, + "rootDir": "./src", + "outDir": "./lib", + "sourceMap": true, + "declaration": true, + "declarationMap": true + }, + "include": ["src"] +} diff --git a/playgrounds/app/package.json b/playgrounds/app/package.json index 409d322..3cb8087 100644 --- a/playgrounds/app/package.json +++ b/playgrounds/app/package.json @@ -32,11 +32,13 @@ "ohash": "^1.1.4", "postcss": "^8.4.38", "remotion": "^4.0.221", - "shiki": "^1.21.0", + "shiki": "^1.22.0", "shiki-magic-move": "workspace:*", + "shikicode": "workspace:*", "solid-color": "^0.0.4", "solid-icons": "^1.1.0", "solid-js": "^1.9.1", + "solid-shiki-textarea": "^0.1.6", "solid-sonner": "^0.2.8", "tailwind-merge": "^2.5.3", "tailwindcss": "^3.4.3", diff --git a/playgrounds/app/src/components/Editor.tsx b/playgrounds/app/src/components/Editor.tsx index 5cb3d80..896d8dc 100644 --- a/playgrounds/app/src/components/Editor.tsx +++ b/playgrounds/app/src/components/Editor.tsx @@ -14,12 +14,7 @@ import { } from '~/components/ui/combobox' import { Button } from '~/components/ui/button' import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/components/ui/tabs' -import { - TextField, - TextFieldInput, - TextFieldLabel, - TextFieldTextArea, -} from '~/components/ui/text-field' +import { TextField, TextFieldInput } from '~/components/ui/text-field' import { MagicMoveElement } from 'shiki-magic-move/types' import { Slider, @@ -51,6 +46,7 @@ import { toast } from 'solid-sonner' import { Separator } from './ui/separator' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select' import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './ui/accordion' +import ShikiCodeBlock from './ui/shiki-code-block' const animationSeconds = 1 const animationFPS = 10 @@ -686,23 +682,26 @@ export default function Editor(props: EditorProps) {
- - Start Code - - - - - End Code - - +
+

Start Code

+ +
+
+

End Code

+ +
diff --git a/playgrounds/app/src/components/ui/shiki-code-block.tsx b/playgrounds/app/src/components/ui/shiki-code-block.tsx new file mode 100644 index 0000000..c89082b --- /dev/null +++ b/playgrounds/app/src/components/ui/shiki-code-block.tsx @@ -0,0 +1,67 @@ +import { createSignal, onMount, createEffect } from 'solid-js' +import { createHighlighter } from 'shiki' +import { autoload, hookClosingPairs, hookTab, ShikiCode } from 'shikicode/plugins' +import { shikiCode } from 'shikicode' + +import { cn } from '~/lib/utils' + +interface ShikiCodeBlockProps { + code: string + lang: string + theme: string + class?: string + onChange?: (value: string) => void +} + +const ShikiCodeBlock = (props: ShikiCodeBlockProps) => { + const [source, setSource] = createSignal(props.code) + const [theme, setTheme] = createSignal(props.theme) + const [lang, setLang] = createSignal(props.lang) + + let containerRef: HTMLDivElement | undefined + let editor: ShikiCode + + onMount(async () => { + const highlighter = await createHighlighter({ + langs: [lang()], + themes: [theme()], + }) + editor = shikiCode() + .withPlugins(hookClosingPairs(), hookTab, autoload) + .create(containerRef!, highlighter, { + value: source(), // Initial code value + language: lang(), + theme: theme(), + }) + + editor.input.addEventListener('input', (e: Event) => { + const value = (e.target as HTMLTextAreaElement).value + setSource(value) + props.onChange?.(value) + }) + }) + + createEffect(() => { + const { code, theme: newTheme, lang: newLang } = props + + setSource(code) + setTheme(newTheme) + setLang(newLang) + + if (editor) { + editor.updateOptions({ + theme: newTheme, + language: newLang, + }) + } + }) + + return ( +
+ ) +} + +export default ShikiCodeBlock diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1bbffd..4698a03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -172,6 +172,24 @@ importers: specifier: ^2.1.6 version: 2.1.6(typescript@5.6.3) + packages/shikicode: + devDependencies: + '@types/jest': + specifier: ^29.5.13 + version: 29.5.14 + dprint: + specifier: ^0.47.2 + version: 0.47.5 + oxlint: + specifier: ^0.9.10 + version: 0.9.10 + shiki: + specifier: ^1.22.0 + version: 1.22.0 + typescript: + specifier: ^5.6.3 + version: 5.6.3 + playgrounds/app: dependencies: '@corvu/resizable': @@ -241,11 +259,14 @@ importers: specifier: ^4.0.221 version: 4.0.221(react-dom@18.3.1(react@18.3.1))(react@18.3.1) shiki: - specifier: ^1.21.0 + specifier: ^1.22.0 version: 1.22.0 shiki-magic-move: specifier: workspace:* version: link:../../packages/shiki-magic-move + shikicode: + specifier: workspace:* + version: link:../../packages/shikicode solid-color: specifier: ^0.0.4 version: 0.0.4(solid-js@1.9.2) @@ -255,6 +276,9 @@ importers: solid-js: specifier: ^1.9.1 version: 1.9.2 + solid-shiki-textarea: + specifier: ^0.1.6 + version: 0.1.6(@babel/core@7.25.8)(@types/react@18.3.11)(shiki@1.22.0)(solid-js@1.9.2) solid-sonner: specifier: ^0.2.8 version: 0.2.8(solid-js@1.9.2) @@ -608,6 +632,46 @@ packages: '@deno/shim-deno@0.19.2': resolution: {integrity: sha512-q3VTHl44ad8T2Tw2SpeAvghdGOjlnLPDNO2cpOxwMrBE/PVas6geWpbpIgrM+czOCH0yejp0yi8OaTuB+NU40Q==} + '@dprint/darwin-arm64@0.47.5': + resolution: {integrity: sha512-aVa3F//dkvEeNA7DCSlVcLxB0CV6zXpfbJZ/xsd+xgbayCXFuFr7qt0M6T4WP3gkQn5D7Zu8/pbXfRXQXo9qlQ==} + cpu: [arm64] + os: [darwin] + + '@dprint/darwin-x64@0.47.5': + resolution: {integrity: sha512-84lmSLM/idIQ4UBkBHU1chP0WTldRjzLOEN22/XbdB1JGOIVN1pJIIU0lsmVWXaNI4SvGfty+thhGn73SSlQwA==} + cpu: [x64] + os: [darwin] + + '@dprint/linux-arm64-glibc@0.47.5': + resolution: {integrity: sha512-Zk7Ut9Trgl2ssGWx0u3YegnRQFXivKaK1fPEimg/uMwdaLtWFGvNs6DACAJk34d883zmDkTQvllqY1kc78CeBg==} + cpu: [arm64] + os: [linux] + + '@dprint/linux-arm64-musl@0.47.5': + resolution: {integrity: sha512-KmCu1yX5+/2MbT9n0iAgSK1gc6sQBcDayq8QRO7TRSs+gTDAZ/yQXHkhLdlk5fWsTR1mDQPVRG+2nAjHDhk8EA==} + cpu: [arm64] + os: [linux] + + '@dprint/linux-x64-glibc@0.47.5': + resolution: {integrity: sha512-oBwENMikvcM+eT6JdliMIM+TOiV4VuBJGK+AN1sTOW45VeiYvmzGPOQwCxVeFq4MnZkMfrycC/PAY3C7Vcuh6w==} + cpu: [x64] + os: [linux] + + '@dprint/linux-x64-musl@0.47.5': + resolution: {integrity: sha512-B1IGyaP0k25JDhqmR/UpvgyNtnclBoXV7ZNQbvygehBkTeC69afwzpUxjQ2pKj2F9bl1Rby//fhsAFOg60PzsA==} + cpu: [x64] + os: [linux] + + '@dprint/win32-arm64@0.47.5': + resolution: {integrity: sha512-tKSPwGWsKc+QAdsx6UQav9AY8WXm+B5Mx23ujliJJMRss6Dnlmg17NjbAnSBSqXSrfqaMeQx6d4gujPpOS3F9A==} + cpu: [arm64] + os: [win32] + + '@dprint/win32-x64@0.47.5': + resolution: {integrity: sha512-ljbrGv5rDR00ziBFY6V+qLhtLHm2dsjgiFG9OU7kr3vHEj4eN31nwxU5W2mh0eMoRk7IbcJ5ahTJDLgoYdvfgw==} + cpu: [x64] + os: [win32] + '@drizzle-team/brocli@0.10.1': resolution: {integrity: sha512-AHy0vjc+n/4w/8Mif+w86qpppHuF3AyXbcWW+R/W7GNA3F5/p2nuhlkCJaTXSLZheB4l1rtHzOfr9A7NwoR/Zg==} @@ -1727,10 +1791,18 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/schemas@29.6.3': resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jridgewell/gen-mapping@0.3.5': resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} engines: {node: '>=6.0.0'} @@ -1822,6 +1894,11 @@ packages: cpu: [x64] os: [win32] + '@lume/element@0.11.9': + resolution: {integrity: sha512-YR4sLA8vCu1bZo5jN4sua2AB66RrDUisMMWOV79KRfLiM8Q3Nxxmb3S1Kocdy56XWz/eZr1scITMiAQNqpN+dg==} + peerDependencies: + '@types/react': '*' + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -1859,6 +1936,46 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oxlint/darwin-arm64@0.9.10': + resolution: {integrity: sha512-eOXKZYq5bnCSgDefgM5bzAg+4Fc//Rc4yjgKN8iDWUARweCaChiQXb6TXX8MfEfs6qayEMy6yVj0pqoFz0B1aw==} + cpu: [arm64] + os: [darwin] + + '@oxlint/darwin-x64@0.9.10': + resolution: {integrity: sha512-UeYICDvLUaUOcY+0ugZUEmBMRLP+x8iTgL7TeY6BlpGw2ahbtUOTbyIIRWtr/0O++TnjZ+v8TzhJ9crw6Ij6dg==} + cpu: [x64] + os: [darwin] + + '@oxlint/linux-arm64-gnu@0.9.10': + resolution: {integrity: sha512-0Zn+vqHhrZyufFBfq9WOgiIool0gCR14BLsdS+0Dwd9o+kNxPGA5q7erQFkiC4rpkxtfBHeD3iIKMMt7d29Kyw==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-arm64-musl@0.9.10': + resolution: {integrity: sha512-tkQcWpYwF42bA/uRaV2iMFePHkBjTTgomOgeEaiw6XOSJX4nBEqGIIboqqLBWT4JnKCf/L+IG3y/e1MflhKByw==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-x64-gnu@0.9.10': + resolution: {integrity: sha512-JHbkMUnibqaSMBvLHyqTL5cWxcGW+jw+Ppt2baLISpvo34a6fBR+PI7v/A92sEDWe0W1rPhypzCwA8mKpkQ3DA==} + cpu: [x64] + os: [linux] + + '@oxlint/linux-x64-musl@0.9.10': + resolution: {integrity: sha512-aBBwN7bQzidwHwEXr7BAdVvMTLWstCy5gikerjLnGDeCSXX9r+o6+yUzTOqZvOo66E+XBgOJaVbY8rsL1MLE0g==} + cpu: [x64] + os: [linux] + + '@oxlint/win32-arm64@0.9.10': + resolution: {integrity: sha512-LXDnk7vKHT3IY6G1jq0O7+XMhtcHOYuxLGIx4KP+4xS6vKgBY+Bsq4xV3AtmtKlvnXkP5FxHpfLmcEtm5AWysA==} + cpu: [arm64] + os: [win32] + + '@oxlint/win32-x64@0.9.10': + resolution: {integrity: sha512-w5XRAV4bhgwenjjpGYZGglqzG9Wv/sI+cjQWJBQsvfDXsr2w4vOBXzt1j3/Z3EcSqf4KtkCa/IIuAhQyeShUbA==} + cpu: [x64] + os: [win32] + '@parcel/watcher-android-arm64@2.4.1': resolution: {integrity: sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==} engines: {node: '>= 10.0.0'} @@ -2159,6 +2276,11 @@ packages: peerDependencies: solid-js: ^1.6.12 + '@solid-primitives/list@0.0.100': + resolution: {integrity: sha512-SZsGouBzUkrZJlJkjVf1rDgRA6FD/+Qar3s7yD1h5uTe1ZIQM89D4RiGxnVjA+KUdfBFQtocT6J76eQ1aIbJxQ==} + peerDependencies: + solid-js: ^1.6.12 + '@solid-primitives/map@0.4.13': resolution: {integrity: sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew==} peerDependencies: @@ -2313,6 +2435,18 @@ packages: '@types/http-proxy@1.17.15': resolution: {integrity: sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -2352,6 +2486,9 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -2361,6 +2498,12 @@ packages: '@types/ws@8.5.12': resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@typescript-eslint/eslint-plugin@8.8.1': resolution: {integrity: sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2978,6 +3121,9 @@ packages: class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} + classy-solid@0.3.9: + resolution: {integrity: sha512-QVAERy8PtkA2eozU/XCCeLamaokprPlCYS5Q7gK05eeE5/gCmIuiGV1F9SMurLpnVy9w6ZKSnNjxUd69btorzQ==} + clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} @@ -3368,6 +3514,10 @@ packages: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} + dprint@0.47.5: + resolution: {integrity: sha512-EAP3OLYZXiW66HKMlhu6Gu0o7mzBVTWyMyuAAgT7dBtMX+W+pPJmIwyRUnTRQNyyFO4S7bAaa21rzIgo97Bg9A==} + hasBin: true + drizzle-kit@0.26.2: resolution: {integrity: sha512-cMq8omEKywjIy5KcqUo6LvEFxkl8/zYHsgYjFVXjmPWWtuW4blcz+YW9+oIhoaALgs2ebRjzXwsJgN9i6P49Dw==} hasBin: true @@ -3576,6 +3726,10 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -3903,6 +4057,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} @@ -4400,6 +4558,18 @@ packages: resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jiti@1.21.6: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true @@ -4535,7 +4705,6 @@ packages: libsql@0.4.6: resolution: {integrity: sha512-F5M+ltteK6dCcpjMahrkgT96uFJvVI8aQ4r9f2AzHQjC7BkAYtvfMSTWGvRBezRgMUIU2h1Sy0pF9nOGOD5iyA==} - cpu: [x64, arm64, wasm32] os: [darwin, linux, win32] lilconfig@2.1.0: @@ -4647,6 +4816,12 @@ packages: loupe@3.1.2: resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} + lowclass@7.0.1: + resolution: {integrity: sha512-MUCYry/VsWP3jfShf0TUyQ9tnmo6qsNUGnxbRo02GHtnyz1pq12ZlI7ep+H1s+FqpoDgA/TVrGqSScrvYhaWAQ==} + + lowclass@8.0.2: + resolution: {integrity: sha512-F/SMc8Kn34lNfjhlMDZYiOqmdtROR8sndSl7I/HJooxBekpgFxBcZL7LFsugc/sSGg0PV+or74+M5Q1/F4dP9g==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -5090,6 +5265,11 @@ packages: outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + oxlint@0.9.10: + resolution: {integrity: sha512-bKiiFN7Hnoaist/rditTRBXz+GXKYuLd53/NB7Q6zHB/bifELJarSoRLkAUGElIJKl4PSr3lTh1g6zehh+rX0g==} + engines: {node: '>=14.*'} + hasBin: true + p-filter@2.1.0: resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} engines: {node: '>=8'} @@ -5876,6 +6056,13 @@ packages: peerDependencies: solid-js: ^1.3 + solid-shiki-textarea@0.1.6: + resolution: {integrity: sha512-SyXGpQ/zlMy0LDPBcPeMapSI/Oyo1WgYe84MSTcxyOdE5UJB+5eLucyyXRX/riDBUS6WS08sR9h86HL3aX/0hQ==} + engines: {node: '>=18', pnpm: '>=9.0.0'} + peerDependencies: + shiki: ^1.6.2 + solid-js: ^1.6.0 + solid-sonner@0.2.8: resolution: {integrity: sha512-EQ2EIznvHHpAmkYh2CTu0AdCgmPJRJWLGFRWygE8j+vMEfvIV2wotHU5qgWzqzVTG1SODGsay2Lwq6ENWx/rPA==} peerDependencies: @@ -5936,6 +6123,10 @@ packages: stable-hash@0.0.4: resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -7339,6 +7530,30 @@ snapshots: '@deno/shim-deno-test': 0.5.0 which: 4.0.0 + '@dprint/darwin-arm64@0.47.5': + optional: true + + '@dprint/darwin-x64@0.47.5': + optional: true + + '@dprint/linux-arm64-glibc@0.47.5': + optional: true + + '@dprint/linux-arm64-musl@0.47.5': + optional: true + + '@dprint/linux-x64-glibc@0.47.5': + optional: true + + '@dprint/linux-x64-musl@0.47.5': + optional: true + + '@dprint/win32-arm64@0.47.5': + optional: true + + '@dprint/win32-x64@0.47.5': + optional: true + '@drizzle-team/brocli@0.10.1': {} '@es-joy/jsdoccomment@0.48.0': @@ -8066,10 +8281,23 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.8 + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.7.5 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 @@ -8183,6 +8411,16 @@ snapshots: '@libsql/win32-x64-msvc@0.4.6': optional: true + '@lume/element@0.11.9(@babel/core@7.25.8)(@types/react@18.3.11)': + dependencies: + '@types/react': 18.3.11 + babel-preset-solid: 1.9.2(@babel/core@7.25.8) + classy-solid: 0.3.9 + lowclass: 7.0.1 + solid-js: 1.9.2 + transitivePeerDependencies: + - '@babel/core' + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.25.7 @@ -8239,6 +8477,30 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 + '@oxlint/darwin-arm64@0.9.10': + optional: true + + '@oxlint/darwin-x64@0.9.10': + optional: true + + '@oxlint/linux-arm64-gnu@0.9.10': + optional: true + + '@oxlint/linux-arm64-musl@0.9.10': + optional: true + + '@oxlint/linux-x64-gnu@0.9.10': + optional: true + + '@oxlint/linux-x64-musl@0.9.10': + optional: true + + '@oxlint/win32-arm64@0.9.10': + optional: true + + '@oxlint/win32-x64@0.9.10': + optional: true + '@parcel/watcher-android-arm64@2.4.1': optional: true @@ -8524,6 +8786,10 @@ snapshots: dependencies: solid-js: 1.9.2 + '@solid-primitives/list@0.0.100(solid-js@1.9.2)': + dependencies: + solid-js: 1.9.2 + '@solid-primitives/map@0.4.13(solid-js@1.9.2)': dependencies: '@solid-primitives/trigger': 1.1.0(solid-js@1.9.2) @@ -8714,6 +8980,21 @@ snapshots: dependencies: '@types/node': 22.7.5 + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/json-schema@7.0.15': {} '@types/jsonwebtoken@9.0.7': @@ -8755,6 +9036,8 @@ snapshots: '@types/resolve@1.20.2': {} + '@types/stack-utils@2.0.3': {} + '@types/unist@3.0.3': {} '@types/web-bluetooth@0.0.20': {} @@ -8763,6 +9046,12 @@ snapshots: dependencies: '@types/node': 22.7.5 + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@8.8.1(@typescript-eslint/parser@8.8.1(eslint@9.12.0(jiti@2.3.3))(typescript@5.6.3))(eslint@9.12.0(jiti@2.3.3))(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.11.1 @@ -9582,6 +9871,11 @@ snapshots: dependencies: clsx: 2.0.0 + classy-solid@0.3.9: + dependencies: + lowclass: 8.0.2 + solid-js: 1.9.2 + clean-regexp@1.0.0: dependencies: escape-string-regexp: 1.0.5 @@ -9925,6 +10219,17 @@ snapshots: dotenv@16.4.5: {} + dprint@0.47.5: + optionalDependencies: + '@dprint/darwin-arm64': 0.47.5 + '@dprint/darwin-x64': 0.47.5 + '@dprint/linux-arm64-glibc': 0.47.5 + '@dprint/linux-arm64-musl': 0.47.5 + '@dprint/linux-x64-glibc': 0.47.5 + '@dprint/linux-x64-musl': 0.47.5 + '@dprint/win32-arm64': 0.47.5 + '@dprint/win32-x64': 0.47.5 + drizzle-kit@0.26.2: dependencies: '@drizzle-team/brocli': 0.10.1 @@ -10193,6 +10498,8 @@ snapshots: escape-string-regexp@1.0.5: {} + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} escape-string-regexp@5.0.0: {} @@ -10693,6 +11000,14 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + extendable-error@0.1.7: {} external-editor@3.1.0: @@ -11229,6 +11544,34 @@ snapshots: jest-get-type@29.6.3: {} + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.25.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.7.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + jiti@1.21.6: {} jiti@2.0.0-beta.3: {} @@ -11508,6 +11851,10 @@ snapshots: loupe@3.1.2: {} + lowclass@7.0.1: {} + + lowclass@8.0.2: {} + lru-cache@10.4.3: {} lru-cache@11.0.1: {} @@ -12188,6 +12535,17 @@ snapshots: outdent@0.5.0: {} + oxlint@0.9.10: + optionalDependencies: + '@oxlint/darwin-arm64': 0.9.10 + '@oxlint/darwin-x64': 0.9.10 + '@oxlint/linux-arm64-gnu': 0.9.10 + '@oxlint/linux-arm64-musl': 0.9.10 + '@oxlint/linux-x64-gnu': 0.9.10 + '@oxlint/linux-x64-musl': 0.9.10 + '@oxlint/win32-arm64': 0.9.10 + '@oxlint/win32-x64': 0.9.10 + p-filter@2.1.0: dependencies: p-map: 2.1.0 @@ -12919,6 +13277,17 @@ snapshots: transitivePeerDependencies: - supports-color + solid-shiki-textarea@0.1.6(@babel/core@7.25.8)(@types/react@18.3.11)(shiki@1.22.0)(solid-js@1.9.2): + dependencies: + '@lume/element': 0.11.9(@babel/core@7.25.8)(@types/react@18.3.11) + '@solid-primitives/list': 0.0.100(solid-js@1.9.2) + clsx: 2.1.1 + shiki: 1.22.0 + solid-js: 1.9.2 + transitivePeerDependencies: + - '@babel/core' + - '@types/react' + solid-sonner@0.2.8(solid-js@1.9.2): dependencies: solid-js: 1.9.2 @@ -12974,6 +13343,10 @@ snapshots: stable-hash@0.0.4: {} + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + stackback@0.0.2: {} stackframe@1.3.4: {}