diff --git a/package-lock.json b/package-lock.json index a3132364a..839206a34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,32 @@ { "name": "solid-ui", - "version": "3.1.3-15", + "version": "3.1.3-16", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "solid-ui", - "version": "3.1.3-15", + "version": "3.1.3-16", "hasInstallScript": true, "license": "MIT", "dependencies": { "@awesome.me/webawesome": "^3.9.0", + "@codemirror/commands": "^6.10.0", + "@codemirror/lang-css": "^6.3.1", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-javascript": "^6.2.5", + "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-markdown": "^6.3.1", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/language": "^6.12.3", + "@codemirror/legacy-modes": "^6.5.3", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.43.0", "@lit/context": "^1.1.6", "@lit/task": "^1.0.3", "@noble/curves": "^2.2.0", "@noble/hashes": "^2.2.0", + "@uiw/codemirror-theme-vscode": "^4.25.10", "escape-html": "^1.0.3", "lit": "^3.3.3", "mime-types": "^3.0.2", @@ -1941,6 +1953,169 @@ "specificity": "bin/cli.js" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.3", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", + "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.4.tgz", + "integrity": "sha512-Ryk9y9T0FFVF0cUGhAknveAyUOl/A1qReTFi+qPKtOh2Z9F4AUBz3XOrYD4ZEgZirdugVzHvd/2/Wcwy5OliTg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.7.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz", + "integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.1.7" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.12", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.12.tgz", + "integrity": "sha512-pw2ReWKUqSkbvh76RAT4NYxiogRu+PWkR2ukAwO9uOgrm8uipkzjtKKtNpyeAQwHOqxEeSvAXZ6vr3AfyB9y/w==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.12" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz", + "integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz", + "integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-markdown": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.2.tgz", + "integrity": "sha512-AwBOdkWYuA//WcM0xO5PfHPUcmz/O2i5o0Nsg1U69SII/loCJlFI1Romd9xp2HYb1kYJRGZotyqRghuHH5n8Kw==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.3.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/markdown": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.1.0.tgz", + "integrity": "sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==", + "license": "MIT", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.4.tgz", + "integrity": "sha512-1q4PaT+o6PbgpkJt4Q8Fv5XJxTy4FUZ4MWETtyiDw3J0Pyr9E2vqcKL+k9wcvjNTIsauxvE7OfmWj3FRPHQ76A==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/legacy-modes": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/@codemirror/legacy-modes/-/legacy-modes-6.5.3.tgz", + "integrity": "sha512-xCsmIzH78MyWkib9jlPaaun57XNkfbMIhagfaZVd0iLTqlpw3jXaIcbZm72MTmmn64eTZpBVNjbyYh+QXnxRsg==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.7.tgz", + "integrity": "sha512-28/+iWLYxKxsvGYhSYL7zaCZqLz5+FFFDq9tVsvGv9kv8RY4fFAchJ5WX9M3YrrRlTIsECjsXPqeNgnSmNP2dg==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.42.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.7.1.tgz", + "integrity": "sha512-9QzNDgE4EYDnAHfrTlR2lwiPciiOymLtwKK+8yHQzCc7GXhAP9xdEbEJFy2IWB1j9UGUl9BsgMmTo/ImA02T7A==", + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.43.8", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.8.tgz", + "integrity": "sha512-qtItTDssZ/5GFfi94hrILu9j/VUeFPDPkhovEfmWFj2ipTxnzPB8DdHgfbb8HYTzLTYhrndKmyQxXUz/PDLenw==", + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.7.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/cascade-layer-name-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@csstools/cascade-layer-name-parser/-/cascade-layer-name-parser-3.0.0.tgz", @@ -3057,6 +3232,95 @@ "integrity": "sha512-6Ae3AfG45MOqF9Qde+1YxIxKf/GUsRmcriV7iCb/HaR+Mk1YDFYP3RINDRMI8z8YMWW3BnSthOujX9RoOex/Kw==", "license": "MIT" }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "license": "MIT" + }, + "node_modules/@lezer/css": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.6.tgz", + "integrity": "sha512-YJE78Wcg+zX8f10hiHWQ4Az48Qr/c13eId0VtRQYLBpxHDmDeSrXIlkbl+fJGW42rWC/uoUco9mhBZeVWP/A1g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.13", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz", + "integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz", + "integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz", + "integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/markdown": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.7.2.tgz", + "integrity": "sha512-iTkYvoVcKt3WkeL7qUDyXHONZEwLio4wj8KTNi2dnjQEXBZKMV63BpQrPqfsM+OkvuRbiSTAcycYAsQzLhRNoQ==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.6.tgz", + "integrity": "sha512-CdDwirL0OEaStFue/66ZmFSeppuL6Dwjlk8qk153mSQwiSH/Dlri4GNymrNWnUmPl2Um7QfV1FO9KFUyX3Twww==", + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "node_modules/@lit-labs/ssr": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@lit-labs/ssr/-/ssr-4.1.0.tgz", @@ -3139,6 +3403,12 @@ "@lit/reactive-element": "^1.0.0 || ^2.0.0" } }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.3.tgz", + "integrity": "sha512-FY+MKLBoTsLNJF/eLWaOsXGdz6uh3Iu1axjPf6TUq92IYumcTcXWHoS747JARLkcdlJ/Waiaxc5wQfFO8jC6NA==", + "license": "MIT" + }, "node_modules/@mdx-js/react": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", @@ -3600,9 +3870,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.142.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz", - "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==", + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" @@ -3932,9 +4202,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.2.tgz", - "integrity": "sha512-l7x215OGvo1s52JWmR8U/DAVzEDWBCIbTm28aeJV/WDTSHgcKXaZTuBT0hJMs5NggilfJTW3clZVvd24yfKJxA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", "cpu": [ "arm64" ], @@ -3948,9 +4218,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.2.tgz", - "integrity": "sha512-9u9Xv6c1AJZT0FfwH5vrMG5Jjcwhc1MlyrPu0XfTqkzsmqfks2M6W/o5XwAJgVVN/jHpqqngC1WevHKKTIUtIA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", "cpu": [ "arm64" ], @@ -3964,9 +4234,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.2.tgz", - "integrity": "sha512-9W1mbGZAfW3oqd85bhBkmpyHCCzL1TeG/zFFP3vg7b0rlly8cxOcre5nXwz+LHazCwac2MNWgPdPCHndABjpWQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", "cpu": [ "x64" ], @@ -3980,9 +4250,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.2.tgz", - "integrity": "sha512-0p1lhiCSCyaerFwtrdZQUx7NqGk6LQnaRKWX7tFQqwQgvX0rjM15cIkm3pax1UpEakK14C4mOxx/jSqCBdBRqQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", "cpu": [ "x64" ], @@ -3996,9 +4266,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.2.tgz", - "integrity": "sha512-e+cOJXrJ2L3zx6YzqPg+f6Wbk3V1cKB8bOhbaYdVYN3DdquzNdRAmrbETz1qnt5yp/c7JNlNjmITiA2cVneQ7w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", "cpu": [ "arm" ], @@ -4012,9 +4282,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.2.tgz", - "integrity": "sha512-JsSMsj6sNat/MuhG5fnBD7QgbtpHKVe30x5/bAVirDHdhoQRXJkF6xc0Jqk8O4fiCUQAzMOoH9wZi3m60c8wtg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", "cpu": [ "arm64" ], @@ -4028,9 +4298,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.2.tgz", - "integrity": "sha512-B5G/zJdHaoJn9vD50eGHWkiWfmq8Uhi3IiLPJTzmZTrAalk1bztUikSXo0qga18ibE0IXboyeMUnhPjhAJ45wQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", "cpu": [ "arm64" ], @@ -4044,9 +4314,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.2.tgz", - "integrity": "sha512-6mC/awzKka8W6EoekjegpfGkjz8jXWDX63pqu/HYVpyKtZfu65Jsh4QAH3Kej3CAv/c1oGX7psTmFEbr0mDxLA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", "cpu": [ "ppc64" ], @@ -4060,9 +4330,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.2.tgz", - "integrity": "sha512-412MX9fJLdA1IK28EZnc8jYv2HRTleOZgfLQumJ5zy7OeJLZlg/CETwFaXjNmGVxG51cFHpKLqb5LKvBC+HsHA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", "cpu": [ "s390x" ], @@ -4076,9 +4346,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.2.tgz", - "integrity": "sha512-Q/+HI/ToJafZ1iCqGgVQXUEkIjufHCTF0gBQ2a5o3cg7GJ2h0qyq3nvvSmU+bGda2/7ygXpTY4TM6gO9OhQ0ZA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", "cpu": [ "x64" ], @@ -4092,9 +4362,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.2.tgz", - "integrity": "sha512-ZKp/w41n6wCvxzxQHtQSbuphfX3Y4cCvbjkKHusrLx4lh+JWLTU7StSltO/DKARISzbj368d+qUaCjI8K2wzXw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", "cpu": [ "x64" ], @@ -4108,9 +4378,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.2.tgz", - "integrity": "sha512-pxE6xD4KS3eAROkKK5yrhB9/3+vhlhVGMvlQLbdpzrBGDbKrnzx3RLwPaHvasLo6jgaiBLn7e04Df9C4tYhjmA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", "cpu": [ "arm64" ], @@ -4124,9 +4394,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.2.tgz", - "integrity": "sha512-4MqEue5re+xIZzAWsB8sj0P1kqZySWqIuN4t6QaIO/YA6SFwySOLruvWQFzfmqk8LBK2P30KCSJwf6mJCZZ5/A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", "cpu": [ "arm64" ], @@ -4140,9 +4410,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.2.tgz", - "integrity": "sha512-NweNxxD0Nf9t8v7kodun45Ijp3EIwYY+uydPP6qBEYvfBqhIjN6dZMzlQja3tqX/aLs3F3Uz+AxDpKgRhpOZQg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", "cpu": [ "x64" ], @@ -5246,6 +5516,37 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@uiw/codemirror-theme-vscode": { + "version": "4.25.11", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.25.11.tgz", + "integrity": "sha512-fTQ5676L9iV3Y6UyDBDd8Wt9Gewh55aC5rqnCtIpwyVFb6zJEHJScI4g43lzAD2IKhY7HlozB1ucrS3UqBFNEQ==", + "license": "MIT", + "dependencies": { + "@uiw/codemirror-themes": "4.25.11" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-themes": { + "version": "4.25.11", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.25.11.tgz", + "integrity": "sha512-SBNCOgRsCtewGNocRbmjbCkltGXlFcPJsvhxQ351VynQjnWUiPbUrFcEU/haQ3HanROdAAjWXZJPk5bMBxl2jw==", + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@codemirror/language": ">=6.0.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/view": ">=6.0.0" + } + }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", @@ -6698,13 +6999,16 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", - "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.28.1" + "browserslist": "^4.28.7" + }, + "engines": { + "node": ">=6.4.0" }, "funding": { "type": "opencollective", @@ -6729,6 +7033,12 @@ "node": ">=0.10.0" } }, + "node_modules/crelt": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.7.tgz", + "integrity": "sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==", + "license": "MIT" + }, "node_modules/cross-fetch": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", @@ -10903,9 +11213,9 @@ "license": "MIT" }, "node_modules/n3": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/n3/-/n3-2.1.2.tgz", - "integrity": "sha512-8DD60rrjJDmeNgLV/zlTiWubxHXLj7te9+uh/IS611fUIgduz4SoeqkOwCQPPpHZ2E/Y26KE+9rm8q8A5mrWvQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/n3/-/n3-2.2.0.tgz", + "integrity": "sha512-K/Orb5XrUPocfYfhUT+muvK1I0n2AvVMt93fIExlgjo23u7q0lU0eIFrhBJqooyFWAnpEBz3QZqjHzEHMs1RZg==", "license": "MIT", "dependencies": { "buffer": "^6.0.3", @@ -12550,12 +12860,12 @@ } }, "node_modules/rolldown": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.2.tgz", - "integrity": "sha512-opwpo1tQBAcpSUJDt94B7hhLNGOKjCdE//XXjeLrnx9b83bjnw45tXdg1b09yEw/VLFBJGZpwRULMmOZo7ol+A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.142.0", + "@oxc-project/types": "=0.143.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -12565,20 +12875,20 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.2.2", - "@rolldown/binding-darwin-arm64": "1.2.2", - "@rolldown/binding-darwin-x64": "1.2.2", - "@rolldown/binding-freebsd-x64": "1.2.2", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.2", - "@rolldown/binding-linux-arm64-gnu": "1.2.2", - "@rolldown/binding-linux-arm64-musl": "1.2.2", - "@rolldown/binding-linux-ppc64-gnu": "1.2.2", - "@rolldown/binding-linux-s390x-gnu": "1.2.2", - "@rolldown/binding-linux-x64-gnu": "1.2.2", - "@rolldown/binding-linux-x64-musl": "1.2.2", - "@rolldown/binding-openharmony-arm64": "1.2.2", - "@rolldown/binding-win32-arm64-msvc": "1.2.2", - "@rolldown/binding-win32-x64-msvc": "1.2.2" + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" } }, "node_modules/run-applescript": { @@ -13348,6 +13658,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", @@ -14645,6 +14961,12 @@ "integrity": "sha512-XadVyw0xE+oZ5FGApXsdswv96rOhStzKqL53uSe5UaTadABGkWIg1+DTx8kiZ/VqTZTBneoL0l65RcPe4W3ecw==", "license": "MIT" }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", diff --git a/package.json b/package.json index ed207d4fd..5aab66ed3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "solid-ui", - "version": "3.1.3-15", + "version": "3.1.3-16", "description": "UI library for Solid applications", "main": "dist/index.cjs.js", "types": "dist/index.d.ts", @@ -93,10 +93,22 @@ "homepage": "https://github.com/SolidOS/solid-ui", "dependencies": { "@awesome.me/webawesome": "^3.9.0", + "@codemirror/commands": "^6.10.0", + "@codemirror/lang-css": "^6.3.1", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/lang-javascript": "^6.2.5", + "@codemirror/lang-json": "^6.0.2", + "@codemirror/lang-markdown": "^6.3.1", + "@codemirror/lang-xml": "^6.1.0", + "@codemirror/language": "^6.12.3", + "@codemirror/legacy-modes": "^6.5.3", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.43.0", "@lit/context": "^1.1.6", "@lit/task": "^1.0.3", "@noble/curves": "^2.2.0", "@noble/hashes": "^2.2.0", + "@uiw/codemirror-theme-vscode": "^4.25.10", "escape-html": "^1.0.3", "lit": "^3.3.3", "mime-types": "^3.0.2", diff --git a/src/index.ts b/src/index.ts index 639490d84..10b6aac46 100644 --- a/src/index.ts +++ b/src/index.ts @@ -67,3 +67,4 @@ export * from './lib/auth' export * from './lib/components' export * from './lib/dialogs' export * from './lib/file-explorer/context' +export * from './lib/code-editor' diff --git a/src/lib/code-editor/CodeEditor.ts b/src/lib/code-editor/CodeEditor.ts new file mode 100644 index 000000000..8d1cab6a7 --- /dev/null +++ b/src/lib/code-editor/CodeEditor.ts @@ -0,0 +1,161 @@ +import type { ThemeMode } from 'pane-registry' +import { Compartment, EditorState } from '@codemirror/state' +import { EditorView, drawSelection, keymap, lineNumbers } from '@codemirror/view' +import { defaultHighlightStyle, syntaxHighlighting, StreamLanguage } from '@codemirror/language' +import { defaultKeymap, history, historyKeymap } from '@codemirror/commands' +import { css } from '@codemirror/lang-css' +import { html } from '@codemirror/lang-html' +import { javascript } from '@codemirror/lang-javascript' +import { json } from '@codemirror/lang-json' +import { markdown } from '@codemirror/lang-markdown' +import { xml } from '@codemirror/lang-xml' +import { vscodeDark, vscodeLight } from '@uiw/codemirror-theme-vscode' +import { turtle } from '@codemirror/legacy-modes/mode/turtle' +import { sparql } from '@codemirror/legacy-modes/mode/sparql' +import { ntriples } from '@codemirror/legacy-modes/mode/ntriples' + +export class CodeEditor { + private _view: EditorView | null = null + private _languageCompartment: Compartment | null = null + private _editableCompartment: Compartment | null = null + private _onDirtyChange?: (dirty: boolean) => void + private _isDirty = false + + async initialize (container: HTMLElement, initialDoc = '', contentType: string = 'text/turtle', theme: ThemeMode = 'dark', onDirtyChange?: (dirty: boolean) => void) { + if (this._view) { + this._view.destroy() + } + + this._languageCompartment = new Compartment() + this._editableCompartment = new Compartment() + this._onDirtyChange = onDirtyChange + this._isDirty = false + const languageExtension = await this._getLanguageExtension(contentType) + + const state = EditorState.create({ + doc: initialDoc, + extensions: [ + theme === 'dark' ? vscodeDark : vscodeLight, + EditorView.theme({ + '&': { + minHeight: '6lh' + } + }), + this._languageCompartment.of(languageExtension), + this._editableCompartment.of(EditorView.editable.of(true)), + syntaxHighlighting(defaultHighlightStyle, { fallback: true }), + lineNumbers(), + history(), + drawSelection(), + EditorView.lineWrapping, + EditorView.updateListener.of((update) => { + if (update.docChanged && !this._isDirty) { + this._isDirty = true + this._onDirtyChange?.(true) + } + }), + keymap.of([ + ...defaultKeymap, + ...historyKeymap + ]) + ] + }) + + this._view = new EditorView({ + state, + parent: container + }) + } + + destroy () { + this._view?.destroy() + this._view = null + this._isDirty = false + } + + getValue (): string { + return this._view ? this._view.state.doc.toString() : '' + } + + replaceContent (text: string) { + if (!this._view) return + const current = this._view.state.doc.toString() + if (current === text) return + this._view.dispatch({ + changes: { from: 0, to: this._view.state.doc.length, insert: text } + }) + } + + resetDirtyState () { + this._isDirty = false + } + + setReadOnly (readOnly: boolean) { + if (!this._view) return + const editableCompartment = this._editableCompartment + if (!editableCompartment) return + this._view.dispatch({ + effects: editableCompartment.reconfigure(EditorView.editable.of(!readOnly)) + }) + } + + focusEditor () { + this._view?.focus() + } + + async setLanguage (contentType: string) { + if (!this._view) return + const languageCompartment = this._languageCompartment + if (!languageCompartment) return + + const extension = await this._getLanguageExtension(contentType) + this._view.dispatch({ + effects: languageCompartment.reconfigure(extension) + }) + } + + private async _getLanguageExtension (contentType: string) { + switch (contentType) { + case 'text/turtle': + case 'text/n3': + return StreamLanguage.define(turtle) + + case 'application/sparql-update': + case 'application/sparql-query': + return StreamLanguage.define(sparql) + + case 'application/nquads': + case 'application/n-quads': + case 'application/n-triples': + return StreamLanguage.define(ntriples) + + case 'application/json': + case 'application/ld+json': + return json() + + case 'text/html': + case 'application/xhtml+xml': + return html() + + case 'text/markdown': + case 'text/x-markdown': + case 'text/md': + return markdown() + + case 'application/rdf+xml': + case 'application/xml': + return xml() + + case 'text/css': + return css() + + case 'text/javascript': + case 'application/javascript': + case 'application/ecmascript': + return javascript() + + default: + return [] + } + } +} diff --git a/src/lib/code-editor/index.ts b/src/lib/code-editor/index.ts new file mode 100644 index 000000000..51fade8bb --- /dev/null +++ b/src/lib/code-editor/index.ts @@ -0,0 +1 @@ +export * from './CodeEditor' diff --git a/test/unit/codeEditor.test.js b/test/unit/codeEditor.test.js new file mode 100644 index 000000000..872978396 --- /dev/null +++ b/test/unit/codeEditor.test.js @@ -0,0 +1,190 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest' + +vi.mock('@codemirror/state', () => { + class Compartment { + of (value) { + return { type: 'compartment-of', value } + } + + reconfigure (value) { + return { type: 'reconfigure', value } + } + } + + const EditorState = { + create: vi.fn((config) => ({ ...config })) + } + + return { Compartment, EditorState } +}) + +const { createdViews, updateListenerOf } = vi.hoisted(() => ({ + createdViews: [], + updateListenerOf: vi.fn((listener) => ({ type: 'updateListener', listener })) +})) + +vi.mock('@codemirror/view', () => { + class EditorView { + constructor ({ state, parent }) { + this.state = state + this.parent = parent + this.dom = globalThis.document.createElement('div') + this.dispatch = vi.fn((transaction) => { + this.lastTransaction = transaction + if (transaction.changes) { + this.state.doc = transaction.changes.insert + } + }) + this.focus = vi.fn() + this.destroy = vi.fn() + createdViews.push(this) + if (parent) { + parent.appendChild(this.dom) + } + } + } + + EditorView.editable = { + of: vi.fn((value) => ({ type: 'editable', value })) + } + EditorView.theme = vi.fn((spec, options) => ({ type: 'theme', spec, options })) + EditorView.lineWrapping = { type: 'lineWrapping' } + EditorView.updateListener = { + of: updateListenerOf + } + + return { + EditorView, + drawSelection: vi.fn(() => ({ type: 'drawSelection' })), + keymap: { + of: vi.fn((value) => ({ type: 'keymap', value })) + }, + lineNumbers: vi.fn(() => ({ type: 'lineNumbers' })) + } +}) + +vi.mock('@codemirror/language', () => ({ + defaultHighlightStyle: { name: 'defaultHighlightStyle' }, + syntaxHighlighting: vi.fn((style, options) => ({ type: 'syntaxHighlighting', style, options })), + HighlightStyle: { + define: vi.fn(() => ({ type: 'highlightStyle' })) + }, + StreamLanguage: class { + static define (mode) { + return { type: 'stream-language', mode } + } + } +})) + +vi.mock('@codemirror/commands', () => ({ + defaultKeymap: [{ key: 'default' }], + history: vi.fn(() => ({ type: 'history' })), + historyKeymap: [{ key: 'history' }] +})) + +vi.mock('@codemirror/lang-css', () => ({ + css: vi.fn(() => ({ type: 'css' })) +})) + +vi.mock('@codemirror/lang-html', () => ({ + html: vi.fn(() => ({ type: 'html' })) +})) + +vi.mock('@codemirror/lang-javascript', () => ({ + javascript: vi.fn(() => ({ type: 'javascript' })) +})) + +vi.mock('@codemirror/lang-json', () => ({ + json: vi.fn(() => ({ type: 'json' })) +})) + +vi.mock('@codemirror/lang-markdown', () => ({ + markdown: vi.fn(() => ({ type: 'markdown' })) +})) + +vi.mock('@codemirror/lang-xml', () => ({ + xml: vi.fn(() => ({ type: 'xml' })) +})) + +vi.mock('@codemirror/legacy-modes/mode/turtle', () => ({ + turtle: { name: 'turtle' } +})) + +vi.mock('@codemirror/legacy-modes/mode/sparql', () => ({ + sparql: { name: 'sparql' } +})) + +vi.mock('@codemirror/legacy-modes/mode/ntriples', () => ({ + ntriples: { name: 'ntriples' } +})) + +vi.mock('@uiw/codemirror-theme-vscode', () => ({ + vscodeDark: [{ type: 'darkTheme' }], + vscodeLight: [{ type: 'lightTheme' }] +})) + +import { CodeEditor } from '../../src/lib/code-editor' + +describe('CodeEditor', () => { + beforeEach(() => { + createdViews.length = 0 + document.body.innerHTML = '' + vi.clearAllMocks() + }) + + it('initializes with the provided document text', async () => { + const editor = new CodeEditor() + const container = document.createElement('div') + document.body.appendChild(container) + + await editor.initialize(container, 'hello world', 'text/plain') + + expect(editor.getValue()).toBe('hello world') + expect(createdViews).toHaveLength(1) + expect(createdViews[0].state.doc).toBe('hello world') + expect(createdViews[0].parent).toBe(container) + }) + + it('replaces content and toggles read only state', async () => { + const editor = new CodeEditor() + const container = document.createElement('div') + document.body.appendChild(container) + + await editor.initialize(container, 'first', 'text/plain') + const view = createdViews[0] + + editor.replaceContent('second') + expect(editor.getValue()).toBe('second') + expect(view.dispatch).toHaveBeenCalledWith({ + changes: { from: 0, to: 5, insert: 'second' } + }) + + editor.setReadOnly(true) + expect(view.dispatch).toHaveBeenLastCalledWith({ + effects: { type: 'reconfigure', value: { type: 'editable', value: false } } + }) + + editor.focusEditor() + expect(view.focus).toHaveBeenCalled() + }) + + it('reports dirty state once when the document first changes', async () => { + const editor = new CodeEditor() + const container = document.createElement('div') + const onDirtyChange = vi.fn() + + document.body.appendChild(container) + + await editor.initialize(container, 'first', 'text/plain', 'dark', onDirtyChange) + + const updateListener = updateListenerOf.mock.calls[0]?.[0] + expect(updateListener).toBeInstanceOf(Function) + + updateListener({ docChanged: true }) + updateListener({ docChanged: true }) + updateListener({ docChanged: false }) + + expect(onDirtyChange).toHaveBeenCalledTimes(1) + expect(onDirtyChange).toHaveBeenCalledWith(true) + }) +}) diff --git a/test/unit/index.test.ts b/test/unit/index.test.ts index e800108a7..89a6d9818 100644 --- a/test/unit/index.test.ts +++ b/test/unit/index.test.ts @@ -9,6 +9,7 @@ describe('Index', () => { expect(Object.keys(Index).sort()).toEqual([ 'Account', 'CloseDialogEvent', + 'CodeEditor', 'DEFAULT_AUTH_CONTEXT', 'DEFAULT_DIALOG_CONTEXT', 'DEFAULT_SIGNUP_URL', @@ -27,7 +28,7 @@ describe('Index', () => { 'create', 'createTypes', 'customElement', - 'dialogContext', + 'dialogContext', 'dom', 'fileExplorerContext', 'generateId',