diff --git a/apps/repl/app/templates/edit/editor/code-mirror.ts b/apps/repl/app/templates/edit/editor/code-mirror.ts index a4c77080e..d0c9edacd 100644 --- a/apps/repl/app/templates/edit/editor/code-mirror.ts +++ b/apps/repl/app/templates/edit/editor/code-mirror.ts @@ -7,7 +7,7 @@ import { syntaxHighlighting } from '@codemirror/language'; import Modifier from 'ember-modifier'; import { getCompiler } from 'ember-repl'; -import { HorizonSyntaxTheme, HorizonTheme } from './theme.ts'; +import { DisabledSyntaxTheme, HorizonTheme } from './theme.ts'; import type RouterService from '@ember/routing/router-service'; import type EditorService from 'limber/services/editor'; @@ -171,7 +171,7 @@ class CodeMirror extends Modifier { text: value, format: formatFromURL, handleUpdate: updateText, - extensions: [HorizonTheme, syntaxHighlighting(HorizonSyntaxTheme)], + extensions: [HorizonTheme, syntaxHighlighting(DisabledSyntaxTheme)], }); if (isDestroyed(this) || isDestroying(this)) return; diff --git a/apps/repl/app/templates/edit/editor/theme.ts b/apps/repl/app/templates/edit/editor/theme.ts index 16f1f9043..5c4795720 100644 --- a/apps/repl/app/templates/edit/editor/theme.ts +++ b/apps/repl/app/templates/edit/editor/theme.ts @@ -4,6 +4,8 @@ import { tags as t } from '@lezer/highlight'; import { alpha, syntax, ui } from '@nullvoxpopuli/horizon-theme'; +export const DisabledSyntaxTheme = HighlightStyle.define([]); + export const HorizonSyntaxTheme = HighlightStyle.define([ { tag: [t.meta, t.comment], color: `${syntax.gray}${alpha.medLow}` }, { tag: t.number, color: `${syntax.apricot}${alpha.high}` }, diff --git a/packages/repl-sdk/package.json b/packages/repl-sdk/package.json index 24185c547..9900f97ab 100644 --- a/packages/repl-sdk/package.json +++ b/packages/repl-sdk/package.json @@ -94,6 +94,8 @@ "@lezer/html": "^1.3.10", "@lezer/markdown": "^1.4.1", "@replit/codemirror-lang-svelte": "^6.0.0", + "@shikijs/langs": "^3.13.0", + "@shikijs/themes": "^3.13.0", "change-case": "^5.4.4", "codemirror": "^6.0.2", "codemirror-lang-glimdown": "workspace:*", @@ -101,12 +103,14 @@ "codemirror-lang-glimmer-js": "workspace:*", "codemirror-lang-mermaid": "^0.5.0", "codemirror-languageserver": "^1.12.1", + "codemirror-shiki": "^0.3.0", "comlink": "^4.4.2", "es-module-shims": "^2.6.1", "mime": "^4.0.7", "package-name-regex": "^4.0.3", "resolve.exports": "^2.0.3", "resolve.imports": "^2.0.3", + "shiki": "^3.13.0", "tarparser": "^0.0.5" }, "volta": { diff --git a/packages/repl-sdk/src/codemirror.js b/packages/repl-sdk/src/codemirror.js index 5920b7ab0..35427a852 100644 --- a/packages/repl-sdk/src/codemirror.js +++ b/packages/repl-sdk/src/codemirror.js @@ -6,6 +6,9 @@ import { keymap } from '@codemirror/view'; import { basicSetup, EditorView } from 'codemirror'; // @ts-ignore import { foldByIndent } from 'codemirror-lang-mermaid'; +import shiki from 'codemirror-shiki'; +import { createHighlighterCore } from 'shiki/core'; +import { createOnigurumaEngine } from 'shiki/engine/oniguruma'; /** * Builds and creates a codemirror instance for the given element @@ -35,6 +38,7 @@ export async function buildCodemirror({ const languageConf = new Compartment(); const supportConf = new Compartment(); const tabSize = new Compartment(); + const shikiConf = new Compartment(); const updateListener = EditorView.updateListener.of(({ state, docChanged }) => { if (docChanged) { @@ -77,6 +81,32 @@ export async function buildCodemirror({ supportForFormat(format), ]); + const highlighter = createHighlighterCore({ + langs: [ + import('@shikijs/langs/javascript'), + import('@shikijs/langs/glimmer-js'), + import('@shikijs/langs/markdown'), + import('@shikijs/langs/svelte'), + import('@shikijs/langs/vue'), + ], + themes: [import('@shikijs/themes/one-dark-pro')], + engine: createOnigurumaEngine(import('shiki/wasm')), + }); + + const formatToLanguage = { + js: 'javascript', + jsx: 'javascript', + ts: 'typescript', + tsx: 'typescript', + gdm: 'markdown', + gmd: 'markdown', + glimdown: 'markdown', + svelte: 'svelte', + vue: 'vue', + gjs: 'glimmer-js', + gts: 'glimmer-ts', + }; + const editorExtensions = [ // features basicSetup, @@ -89,6 +119,15 @@ export async function buildCodemirror({ EditorView.lineWrapping, keymap.of([indentWithTab, ...completionKeymap, ...markdownKeymap]), + shikiConf.of( + shiki({ + highlighter, + // @ts-ignore + language: formatToLanguage[format] || 'javascript', + theme: 'one-dark-pro', + }) + ), + // TODO: lsp, ...(extensions ?? []), @@ -121,7 +160,18 @@ export async function buildCodemirror({ to: view.state.doc.length, insert: text, }, - effects: [languageConf.reconfigure(language), supportConf.reconfigure(support)], + effects: [ + languageConf.reconfigure(language), + supportConf.reconfigure(support), + shikiConf.reconfigure([ + shiki({ + highlighter, + // @ts-ignore + language: formatToLanguage[format] || 'javascript', + theme: 'one-dark-pro', + }), + ]), + ], }); }; @@ -139,7 +189,18 @@ export async function buildCodemirror({ console.debug(`Codemirror changing to ${format}: ${language ? 'ok' : 'not ok'}`); view.dispatch({ - effects: [languageConf.reconfigure(language), supportConf.reconfigure(support)], + effects: [ + languageConf.reconfigure(language), + supportConf.reconfigure(support), + shikiConf.reconfigure([ + shiki({ + highlighter, + // @ts-ignore + language: formatToLanguage[format] || 'javascript', + theme: 'one-dark-pro', + }), + ]), + ], }); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af292643d..6526878f2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -472,7 +472,7 @@ importers: version: 0.40.0(26a482c5f89fb72edd76dffe317483fb) ember-repl: specifier: latest - version: 7.0.0(d19b4f53cae6558f7d34488bf8cc1673) + version: 7.0.1(6e3ff2842ba468e8d1332163fa22ba88) ember-resources: specifier: ^7.0.7 version: 7.0.7(0b2137a339483510843f9f1309186110) @@ -1295,6 +1295,12 @@ importers: '@replit/codemirror-lang-svelte': specifier: ^6.0.0 version: 6.0.0(5458bb07fcb4199f68819c59557bf066) + '@shikijs/langs': + specifier: ^3.13.0 + version: 3.13.0 + '@shikijs/themes': + specifier: ^3.13.0 + version: 3.13.0 change-case: specifier: ^5.4.4 version: 5.4.4 @@ -1316,6 +1322,9 @@ importers: codemirror-languageserver: specifier: ^1.12.1 version: 1.12.1(encoding@0.1.13) + codemirror-shiki: + specifier: ^0.3.0 + version: 0.3.0(4a832fb061dee512392c52b479686556) comlink: specifier: ^4.4.2 version: 4.4.2 @@ -1334,6 +1343,9 @@ importers: resolve.imports: specifier: ^2.0.3 version: 2.0.3 + shiki: + specifier: ^3.13.0 + version: 3.13.0 tarparser: specifier: ^0.0.5 version: 0.0.5 @@ -4344,6 +4356,9 @@ packages: '@shikijs/core@3.12.2': resolution: {integrity: sha512-L1Safnhra3tX/oJK5kYHaWmLEBJi1irASwewzY3taX5ibyXyMkkSDZlq01qigjryOBwrXSdFgTiZ3ryzSNeu7Q==} + '@shikijs/core@3.13.0': + resolution: {integrity: sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA==} + '@shikijs/core@3.7.0': resolution: {integrity: sha512-yilc0S9HvTPyahHpcum8eonYrQtmGTU0lbtwxhA6jHv4Bm1cAdlPFRCJX4AHebkCm75aKTjjRAW+DezqD1b/cg==} @@ -4353,6 +4368,9 @@ packages: '@shikijs/engine-javascript@3.12.2': resolution: {integrity: sha512-Nm3/azSsaVS7hk6EwtHEnTythjQfwvrO5tKqMlaH9TwG1P+PNaR8M0EAKZ+GaH2DFwvcr4iSfTveyxMIvXEHMw==} + '@shikijs/engine-javascript@3.13.0': + resolution: {integrity: sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg==} + '@shikijs/engine-javascript@3.7.0': resolution: {integrity: sha512-0t17s03Cbv+ZcUvv+y33GtX75WBLQELgNdVghnsdhTgU3hVcWcMsoP6Lb0nDTl95ZJfbP1mVMO0p3byVh3uuzA==} @@ -4362,6 +4380,9 @@ packages: '@shikijs/engine-oniguruma@3.12.2': resolution: {integrity: sha512-hozwnFHsLvujK4/CPVHNo3Bcg2EsnG8krI/ZQ2FlBlCRpPZW4XAEQmEwqegJsypsTAN9ehu2tEYe30lYKSZW/w==} + '@shikijs/engine-oniguruma@3.13.0': + resolution: {integrity: sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==} + '@shikijs/engine-oniguruma@3.7.0': resolution: {integrity: sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==} @@ -4371,6 +4392,9 @@ packages: '@shikijs/langs@3.12.2': resolution: {integrity: sha512-bVx5PfuZHDSHoBal+KzJZGheFuyH4qwwcwG/n+MsWno5cTlKmaNtTsGzJpHYQ8YPbB5BdEdKU1rga5/6JGY8ww==} + '@shikijs/langs@3.13.0': + resolution: {integrity: sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==} + '@shikijs/langs@3.7.0': resolution: {integrity: sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==} @@ -4383,6 +4407,9 @@ packages: '@shikijs/themes@3.12.2': resolution: {integrity: sha512-fTR3QAgnwYpfGczpIbzPjlRnxyONJOerguQv1iwpyQZ9QXX4qy/XFQqXlf17XTsorxnHoJGbH/LXBvwtqDsF5A==} + '@shikijs/themes@3.13.0': + resolution: {integrity: sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==} + '@shikijs/themes@3.7.0': resolution: {integrity: sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==} @@ -4392,6 +4419,9 @@ packages: '@shikijs/types@3.12.2': resolution: {integrity: sha512-K5UIBzxCyv0YoxN3LMrKB9zuhp1bV+LgewxuVwHdl4Gz5oePoUFrr9EfgJlGlDeXCU1b/yhdnXeuRvAnz8HN8Q==} + '@shikijs/types@3.13.0': + resolution: {integrity: sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==} + '@shikijs/types@3.7.0': resolution: {integrity: sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==} @@ -5973,6 +6003,13 @@ packages: codemirror-languageserver@1.12.1: resolution: {integrity: sha512-B71XofYRsVsyUpkiWtdTcHIwVoEpws01PqHpkr/o5k4EET9kQEpRqDH/G+f+hQI4eZxwONOx8n5Dz2fsf02PrA==} + codemirror-shiki@0.3.0: + resolution: {integrity: sha512-KSrfcm8RNSgTl3+Vgq+HuGA/bQGbxBMGosoFXL77yWc6r8JjLygIBndqL9evCv2ED9EOoeZozROcXNanN7Mabg==} + peerDependencies: + '@codemirror/state': ^6 + '@codemirror/view': ^6 + shiki: '>=2.0.0' + codemirror@6.0.2: resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==} @@ -6949,8 +6986,8 @@ packages: '@glint/template': optional: true - ember-repl@7.0.0: - resolution: {integrity: sha512-sodaNV1tXyQIaw5Q6a1ECnPcdfIN+hac3YNL6xn1LMSCzuyJeKiGv/Q80SJuXzN5M8SM0fJdrXUxwQyKAvXl/g==} + ember-repl@7.0.1: + resolution: {integrity: sha512-U5UkG3C8XSpL4HZeCBZStzsffqCcCW1H5KJzjTFfo7RP1HnuIOmB58Dv4Iz6dTztVgwWUM6wvBKFgnp8jVdK8g==} peerDependencies: '@glint/template': '>= 1.5.2 || ^1.6.0-alpha.1' peerDependenciesMeta: @@ -10527,6 +10564,9 @@ packages: shiki@3.12.2: resolution: {integrity: sha512-uIrKI+f9IPz1zDT+GMz+0RjzKJiijVr6WDWm9Pe3NNY6QigKCfifCEv9v9R2mDASKKjzjQ2QpFLcxaR3iHSnMA==} + shiki@3.13.0: + resolution: {integrity: sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g==} + shiki@3.7.0: resolution: {integrity: sha512-ZcI4UT9n6N2pDuM2n3Jbk0sR4Swzq43nLPgS/4h0E3B/NrFn2HKElrDtceSf8Zx/OWYOo7G1SAtBLypCp+YXqg==} @@ -14756,6 +14796,13 @@ snapshots: '@types/hast': 3.0.4 hast-util-to-html: 9.0.5 + '@shikijs/core@3.13.0': + dependencies: + '@shikijs/types': 3.13.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.5 + '@shikijs/core@3.7.0': dependencies: '@shikijs/types': 3.7.0 @@ -14775,6 +14822,12 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 oniguruma-to-es: 4.3.3 + '@shikijs/engine-javascript@3.13.0': + dependencies: + '@shikijs/types': 3.13.0 + '@shikijs/vscode-textmate': 10.0.2 + oniguruma-to-es: 4.3.3 + '@shikijs/engine-javascript@3.7.0': dependencies: '@shikijs/types': 3.7.0 @@ -14791,6 +14844,11 @@ snapshots: '@shikijs/types': 3.12.2 '@shikijs/vscode-textmate': 10.0.2 + '@shikijs/engine-oniguruma@3.13.0': + dependencies: + '@shikijs/types': 3.13.0 + '@shikijs/vscode-textmate': 10.0.2 + '@shikijs/engine-oniguruma@3.7.0': dependencies: '@shikijs/types': 3.7.0 @@ -14804,6 +14862,10 @@ snapshots: dependencies: '@shikijs/types': 3.12.2 + '@shikijs/langs@3.13.0': + dependencies: + '@shikijs/types': 3.13.0 + '@shikijs/langs@3.7.0': dependencies: '@shikijs/types': 3.7.0 @@ -14825,6 +14887,10 @@ snapshots: dependencies: '@shikijs/types': 3.12.2 + '@shikijs/themes@3.13.0': + dependencies: + '@shikijs/types': 3.13.0 + '@shikijs/themes@3.7.0': dependencies: '@shikijs/types': 3.7.0 @@ -14839,6 +14905,11 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + '@shikijs/types@3.13.0': + dependencies: + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + '@shikijs/types@3.7.0': dependencies: '@shikijs/vscode-textmate': 10.0.2 @@ -16909,6 +16980,12 @@ snapshots: - encoding - utf-8-validate + codemirror-shiki@0.3.0(4a832fb061dee512392c52b479686556): + dependencies: + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.0 + shiki: 3.13.0 + codemirror@6.0.2: dependencies: '@codemirror/autocomplete': 6.18.6 @@ -17981,7 +18058,7 @@ snapshots: - '@glimmer/component' - supports-color - ember-repl@7.0.0(d19b4f53cae6558f7d34488bf8cc1673): + ember-repl@7.0.1(6e3ff2842ba468e8d1332163fa22ba88): dependencies: '@ember/test-helpers': 5.2.2(f9dfbf4fac3dbc0e0370b14ce6056988) '@ember/test-waiters': 4.1.1(@glint/template@1.6.1) @@ -17993,7 +18070,7 @@ snapshots: ember-primitives: 0.40.0(26a482c5f89fb72edd76dffe317483fb) ember-resolver: 13.1.1 ember-resources: 7.0.7(0b2137a339483510843f9f1309186110) - repl-sdk: 1.0.0(b911f762b840833cafb152ec0acffb75) + repl-sdk: 1.0.0(59341cc0c192dad95cd11861b1678c69) optionalDependencies: '@glint/template': 1.6.1 transitivePeerDependencies: @@ -22100,7 +22177,7 @@ snapshots: repeat-string@1.6.1: {} - repl-sdk@1.0.0(b911f762b840833cafb152ec0acffb75): + repl-sdk@1.0.0(59341cc0c192dad95cd11861b1678c69): dependencies: '@codemirror/autocomplete': 6.18.6 '@codemirror/commands': 6.8.1 @@ -22585,6 +22662,17 @@ snapshots: '@shikijs/vscode-textmate': 10.0.2 '@types/hast': 3.0.4 + shiki@3.13.0: + dependencies: + '@shikijs/core': 3.13.0 + '@shikijs/engine-javascript': 3.13.0 + '@shikijs/engine-oniguruma': 3.13.0 + '@shikijs/langs': 3.13.0 + '@shikijs/themes': 3.13.0 + '@shikijs/types': 3.13.0 + '@shikijs/vscode-textmate': 10.0.2 + '@types/hast': 3.0.4 + shiki@3.7.0: dependencies: '@shikijs/core': 3.7.0