Skip to content

Commit bf57bfe

Browse files
authored
refactor(code-editor): update to Codemirror 6 (#421)
* refactor(code-editor): update to Codemirror 6 * feat(editor): enable adding codemirror extensions
1 parent a300acb commit bf57bfe

31 files changed

+3189
-1562
lines changed

.eslintignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
/internal/
99
/service-worker/
1010
/shared/
11-
/src/themes/
1211
/test/
1312
/themes/
1413
/typescript-worker/

.github/workflows/deploy-demo.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
with:
1616
node-version: 20
1717
cache: npm
18-
- uses: google/wireit@setup-github-actions-caching/v1
18+
- uses: google/wireit@setup-github-actions-caching/v2
1919

2020
- run: npm ci
2121
- run: npx playwright install-deps

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
with:
1313
node-version: 20
1414
cache: npm
15-
- uses: google/wireit@setup-github-actions-caching/v1
15+
- uses: google/wireit@setup-github-actions-caching/v2
1616

1717
- run: npm ci
1818
- run: npm run lint

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
with:
1313
node-version: 20
1414
cache: npm
15-
- uses: google/wireit@setup-github-actions-caching/v1
15+
- uses: google/wireit@setup-github-actions-caching/v2
1616

1717
- run: npm ci
1818
- run: npx playwright install-deps

.github/workflows/version-module.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
with:
1313
node-version: 20
1414
cache: npm
15-
- uses: google/wireit@setup-github-actions-caching/v1
15+
- uses: google/wireit@setup-github-actions-caching/v2
1616

1717
- run: npm ci
1818
- run: npx playwright install-deps

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
/playground-*.js
1717
/playground-*.d.ts
1818
/playground-*.d.ts.map
19+
/codemirror-extension*.js
20+
/codemirror-extension*.d.ts
21+
/codemirror-extension*.d.ts.map
22+
/cm-lang-lit.js
23+
/cm-lang-lit.d.ts
24+
/cm-lang-lit.d.ts.map
1925
/test/
2026
/_codemirror/
2127
/themes/
@@ -25,7 +31,6 @@
2531
.tsbuildinfo
2632
/playground-service-worker.*
2733
/playground-service-worker-proxy.*
28-
/src/playground-styles.ts
2934
/*.tgz
3035
/.wireit
3136
/.eslintcache

.prettierignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
/internal/
1010
/service-worker/
1111
/shared/
12-
/src/configurator/themes.ts
1312
/src/playground-styles.ts
14-
/src/themes/
1513
/test/
1614
/themes/
1715
/typescript-worker/

CHANGELOG.md

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,27 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111
-->
1212

1313
<!-- ## [X.Y.Z] - YYYY-MM-DD -->
14-
<!-- ## [Unreleased] -->
15-
<!-- ### Added -->
16-
<!-- ### Fixed -->
14+
15+
## [Unreleased]
16+
17+
### Added
18+
19+
- Added `extensions` property to `<playground-ide>`,
20+
`<playground-file-editor>`, and `<playground-code-editor>` for applying
21+
programmatic CodeMirror extensions.
22+
- Added an `extensions` slot to `<playground-ide>`,
23+
`<playground-file-editor>`, and `<playground-code-editor>` for applying
24+
declarative CodeMirror extensions.
25+
- Exported `codemirrorExtensionMixin` for creating declarative CodeMirror
26+
extensions.
27+
- Upgraded CodeMirror to v6
28+
29+
### Fixed
30+
31+
- Safari cursor issues
32+
- Cursor selection and visiblity was broken in Safari
33+
- Fixed by updating to Codemirror 6
34+
1735
<!-- ### Removed -->
1836

1937
## [0.20.0] - 2025-03-31

README.md

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
• <a href="#typescript">TypeScript</a>
2222
• <a href="#hiding--folding">Hiding & Folding</a>
2323
• <a href="#custom-layouts">Custom layouts</a>
24+
• <a href="#extending-the-editor">Extending the editor</a>
2425
• <a href="#bundling">Bundling</a>
2526
• <a href="#sandbox-security">Sandbox security</a>
2627
• <a href="#components">Components</a>
@@ -517,6 +518,60 @@ Finally, add a little style:
517518
</style>
518519
```
519520

521+
## Extending the editor
522+
523+
Playground's code editor is built on [CodeMirror 6](https://codemirror.net/), and can be extended with any CodeMirror extension. This allows for deep customization of the editor's behavior, such as adding new themes, keymaps, autocompletion sources, and more.
524+
525+
There are two ways to apply extensions: programmatically and declaratively.
526+
527+
### Programmatic extensions
528+
529+
The `<playground-ide>`, `<playground-file-editor>`, and `<playground-code-editor>` components all have an `extensions` property which accepts a CodeMirror `Extension` object (or an array of them).
530+
531+
```js
532+
import {EditorView} from '@codemirror/view';
533+
534+
const ide = document.querySelector('playground-ide');
535+
const myTheme = EditorView.theme({
536+
'&': {
537+
backgroundColor: 'lightpink',
538+
},
539+
});
540+
ide.extensions = myTheme;
541+
```
542+
543+
### Declarative extensions
544+
545+
For simpler use-cases, or for when you want to package an extension as a reusable HTML element, you can use declarative extensions.
546+
547+
A declarative extension is a custom element that provides one or more CodeMirror extensions. Playground elements will automatically find any declarative extension elements placed in their `extensions` slot and apply them.
548+
549+
Here's an example of a custom theme packaged as a declarative extension:
550+
551+
```html
552+
<playground-ide>
553+
<my-theme-extension slot="extensions"></my-theme-extension>
554+
</playground-ide>
555+
556+
<script type="module">
557+
import {codemirrorExtensionMixin} from 'playground-elements';
558+
import {EditorView} from '@codemirror/view';
559+
560+
class MyTheme extends codemirrorExtensionMixin(HTMLElement) {
561+
getExtensions() {
562+
return EditorView.theme({
563+
'&': {
564+
backgroundColor: 'lightpink',
565+
},
566+
});
567+
}
568+
}
569+
customElements.define('my-theme-extension', MyTheme);
570+
</script>
571+
```
572+
573+
The `codemirrorExtensionMixin` handles the communication with the playground editor. Your class just needs to implement the `getExtensions()` method.
574+
520575
## Bundling
521576

522577
Playground uses a [Web
@@ -692,12 +747,14 @@ All-in-one project, editor, file switcher, and preview with a horizontal side-by
692747
| `modified` | `boolean` | `false` | Whether the user has modified, added, or removed any project files. Resets whenever a new project is loaded. |
693748
| `htmlFile` | `string` | `"index.html"` | The HTML file used in the preview. |
694749
| `noCompletions` | `boolean` | `false` | If interactive code completions should be shown. This setting only applies to TypeScript files. |
750+
| `extensions` | `Extension \| Extension[]` | `undefined` | A CodeMirror extension to apply to the editor ([details](#extending-the-editor)). |
695751

696752
### Slots
697753

698-
| Name | Description |
699-
| --------- | ----------------------------------------- |
700-
| `default` | Inline files ([details](#inline-scripts)) |
754+
| Name | Description |
755+
| ------------ | --------------------------------------------------------------------- |
756+
| `default` | Inline files ([details](#inline-scripts)). |
757+
| `extensions` | Declarative CodeMirror extensions ([details](#extending-the-editor)). |
701758

702759
---
703760

@@ -769,6 +826,13 @@ project element.
769826
| `pragmas` | `"on" \| "off" \| "off-visible"` | `"on"` | How to handle `playground-hide` and `playground-fold` comments ([details](#hiding--folding)). |
770827
| `readonly` | `boolean` | `false` | Do not allow edits |
771828
| `noCompletions` | `boolean` | `false` | If interactive code completions should be shown. This setting only applies to TypeScript files. |
829+
| `extensions` | `Extension \| Extension[]` | `undefined` | A CodeMirror extension to apply to the editor ([details](#extending-the-editor)). |
830+
831+
### Slots
832+
833+
| Name | Description |
834+
| ------------ | --------------------------------------------------------------------- |
835+
| `extensions` | Declarative CodeMirror extensions ([details](#extending-the-editor)). |
772836

773837
---
774838

@@ -787,6 +851,13 @@ A pure text editor based on CodeMirror with syntax highlighting for HTML, CSS, J
787851
| `pragmas` | `"on" \| "off" \| "off-visible"` | `"on"` | How to handle `playground-hide` and `playground-fold` comments ([details](#hiding--folding)). |
788852
| `documentKey` | `object` | `undefined` | Editor history for undo/redo is isolated per `documentKey`. Default behavior is a single instance. |
789853
| `noCompletions` | `boolean` | `false` | If interactive code completions should be shown. This setting only applies to TypeScript files. |
854+
| `extensions` | `Extension \| Extension[]` | `undefined` | A CodeMirror extension to apply to the editor ([details](#extending-the-editor)). |
855+
856+
### Slots
857+
858+
| Name | Description |
859+
| ------------ | --------------------------------------------------------------------- |
860+
| `extensions` | Declarative CodeMirror extensions ([details](#extending-the-editor)). |
790861

791862
### Events
792863

0 commit comments

Comments
 (0)