@fusion.dev/helix-sandbox 0.0.0-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/api.json +1 -0
- package/custom-elements.json +1182 -0
- package/dist/code-block/code-block-highlight.d.ts +16 -0
- package/dist/code-block/code-block-highlight.d.ts.map +1 -0
- package/dist/code-block/code-block-highlight.js +10 -0
- package/dist/code-block/code-block-highlight.js.map +1 -0
- package/dist/code-block/index.d.ts +2 -0
- package/dist/code-block/index.d.ts.map +1 -0
- package/dist/code-block/index.js +5 -0
- package/dist/code-block/index.js.map +1 -0
- package/dist/editor/index.d.ts +2 -0
- package/dist/editor/index.d.ts.map +1 -0
- package/dist/editor/index.js +2 -0
- package/dist/editor/index.js.map +1 -0
- package/dist/editor/root/editor-root.css.d.ts +2 -0
- package/dist/editor/root/editor-root.css.d.ts.map +1 -0
- package/dist/editor/root/editor-root.css.js +3 -0
- package/dist/editor/root/editor-root.css.js.map +1 -0
- package/dist/editor/root/editor-root.d.ts +146 -0
- package/dist/editor/root/editor-root.d.ts.map +1 -0
- package/dist/editor/root/editor-root.js +199 -0
- package/dist/editor/root/editor-root.js.map +1 -0
- package/dist/highlight/highlight.d.ts +25 -0
- package/dist/highlight/highlight.d.ts.map +1 -0
- package/dist/highlight/highlight.js +97 -0
- package/dist/highlight/highlight.js.map +1 -0
- package/dist/highlight/index.d.ts +4 -0
- package/dist/highlight/index.d.ts.map +1 -0
- package/dist/highlight/index.js +4 -0
- package/dist/highlight/index.js.map +1 -0
- package/dist/highlight/language.d.ts +26 -0
- package/dist/highlight/language.d.ts.map +1 -0
- package/dist/highlight/language.js +21 -0
- package/dist/highlight/language.js.map +1 -0
- package/dist/highlight/shell.d.ts +10 -0
- package/dist/highlight/shell.d.ts.map +1 -0
- package/dist/highlight/shell.js +31 -0
- package/dist/highlight/shell.js.map +1 -0
- package/dist/highlight/stream.d.ts +10 -0
- package/dist/highlight/stream.d.ts.map +1 -0
- package/dist/highlight/stream.js +178 -0
- package/dist/highlight/stream.js.map +1 -0
- package/dist/highlight/syntax.d.ts +10 -0
- package/dist/highlight/syntax.d.ts.map +1 -0
- package/dist/highlight/syntax.js +100 -0
- package/dist/highlight/syntax.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/sandbox/editor/sandbox-editor.css.d.ts +2 -0
- package/dist/sandbox/editor/sandbox-editor.css.d.ts.map +1 -0
- package/dist/sandbox/editor/sandbox-editor.css.js +3 -0
- package/dist/sandbox/editor/sandbox-editor.css.js.map +1 -0
- package/dist/sandbox/editor/sandbox-editor.d.ts +147 -0
- package/dist/sandbox/editor/sandbox-editor.d.ts.map +1 -0
- package/dist/sandbox/editor/sandbox-editor.js +199 -0
- package/dist/sandbox/editor/sandbox-editor.js.map +1 -0
- package/examples.json +1 -0
- package/lint.json +1 -0
- package/package.json +116 -0
- package/types/jsx.d.ts +638 -0
- package/types/svelte.d.ts +36 -0
- package/types/vue.d.ts +134 -0
- package/types/words.d.ts +22 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type CSSResult } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Highlights a block's code by its `language`, in any case and by any name
|
|
4
|
+
* `languageOf` reads, such as `ts`, `TypeScript` or `bash`, or returns
|
|
5
|
+
* `undefined` for a language no grammar here reads, which the block then
|
|
6
|
+
* draws plain.
|
|
7
|
+
*
|
|
8
|
+
* **In the editor's own style**, so a snippet in a block and the same snippet
|
|
9
|
+
* open in the sandbox are colored by one source: the classes are the ones
|
|
10
|
+
* `syntaxHighlighter` gives each token, and `codeBlockSheet` holds the rules
|
|
11
|
+
* for them, in the `--helix-color-syntax-*` tokens.
|
|
12
|
+
*/
|
|
13
|
+
export declare const codeBlockHighlighter: (code: string, language: string) => string | undefined;
|
|
14
|
+
/** The rules that color `codeBlockHighlighter`'s classes, for a block to adopt. */
|
|
15
|
+
export declare const codeBlockSheet: CSSResult;
|
|
16
|
+
//# sourceMappingURL=code-block-highlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-highlight.d.ts","sourceRoot":"","sources":["../../src/code-block/code-block-highlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,KAAK,CAAA;AAK/C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,SAAU,MAAM,YAAY,MAAM,KAAG,MAAM,GAAG,SAG9E,CAAA;AAED,mFAAmF;AACnF,eAAO,MAAM,cAAc,EAAE,SAAkC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { unsafeCSS } from 'lit';
|
|
2
|
+
import { highlight } from '../highlight/highlight.js';
|
|
3
|
+
import { languageOf } from '../highlight/language.js';
|
|
4
|
+
import { syntaxHighlighter, syntaxRules } from '../highlight/syntax.js';
|
|
5
|
+
export const codeBlockHighlighter = (code, language) => {
|
|
6
|
+
const grammar = languageOf(language);
|
|
7
|
+
return grammar ? highlight(code, grammar, syntaxHighlighter) : undefined;
|
|
8
|
+
};
|
|
9
|
+
export const codeBlockSheet = unsafeCSS(syntaxRules);
|
|
10
|
+
//# sourceMappingURL=code-block-highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-block-highlight.js","sourceRoot":"","sources":["../../src/code-block/code-block-highlight.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAE,MAAM,KAAK,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAavE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAsB,EAAE;IACzF,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACpC,OAAO,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC1E,CAAC,CAAA;AAGD,MAAM,CAAC,MAAM,cAAc,GAAc,SAAS,CAAC,WAAW,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/code-block/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { registerHighlighter } from '@fusion.dev/helix-headless/code-block';
|
|
2
|
+
import { codeBlockHighlighter, codeBlockSheet } from './code-block-highlight.js';
|
|
3
|
+
registerHighlighter(codeBlockHighlighter, codeBlockSheet);
|
|
4
|
+
export { codeBlockHighlighter, codeBlockSheet } from './code-block-highlight.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/code-block/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAA;AAC3E,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAEhF,mBAAmB,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAA;AAEzD,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/editor/index.ts"],"names":[],"mappings":"AASA,cAAc,qCAAqC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/editor/index.ts"],"names":[],"mappings":"AASA,cAAc,qCAAqC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-root.css.d.ts","sourceRoot":"","sources":["../../../src/editor/root/editor-root.css.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM,yBAAihC,CAAA"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { createSheet } from '@fusion.dev/helix-core';
|
|
2
|
+
export const styles = createSheet(`:host {display: block;min-block-size: 0;overflow: hidden}[part="editor"] {block-size: 100%;font-family: var(--helix-font-mono);font-size: var(--helix-text-sm)}[part="editor"] .cm-editor {block-size: 100%}[part="editor"] .cm-scroller {font-family: inherit;line-height: var(--helix-leading-normal)}[part="editor"] .cm-gutters {background-color: transparent;border: none;color: var(--helix-color-foreground-muted)}[part="editor"] .cm-activeLineGutter, [part="editor"] .cm-activeLine {background-color: var(--helix-color-surface-sunken)}[part="editor"] .cm-content {caret-color: var(--helix-color-primary)}[part="editor"] .cm-cursor {border-left-color: var(--helix-color-primary)}[part="editor"] .cm-selectionBackground, [part="editor"] .cm-editor.cm-focused .cm-selectionBackground {background-color: var(--helix-color-primary-subtle)}[part="editor"] .cm-editor.cm-focused {outline: none}:host([readonly]) [part="editor"] .cm-cursor {border-left-color: var(--helix-color-foreground-subtle)}@media print {:host {display: none}}`);
|
|
3
|
+
//# sourceMappingURL=editor-root.css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-root.css.js","sourceRoot":"","sources":["../../../src/editor/root/editor-root.css.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAEpD,MAAM,CAAC,MAAM,MAAM,GAAG,WAAW,CAAC,igCAAigC,CAAC,CAAA"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { type CaretDetail, HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* A language the editor knows, by the name a file or a sandbox pane carries.
|
|
5
|
+
*
|
|
6
|
+
* **Written out, where `keyof typeof` would hide the values.** The manifest
|
|
7
|
+
* records a property's type as the text somebody wrote, so a type derived from
|
|
8
|
+
* a record's keys reached it as a name with nothing in it and the reference
|
|
9
|
+
* page listed no values. A union on one line resolves for every reader of these
|
|
10
|
+
* sources without a type system, the `axes` rule included.
|
|
11
|
+
*
|
|
12
|
+
* The names are the panes': `js`, `jsx`, `mjs`, `ts` and `tsx` beside `css`,
|
|
13
|
+
* `html` and `sh`, and `javascript`. The editor reads every name `languageOf`
|
|
14
|
+
* from `@fusion.dev/helix-sandbox/highlight` reads, such as `TypeScript` or
|
|
15
|
+
* `bash`, and `jsx` as `tsx`.
|
|
16
|
+
*/
|
|
17
|
+
export type EditorLanguage = 'css' | 'html' | 'javascript' | 'js' | 'jsx' | 'mjs' | 'sh' | 'ts' | 'tsx';
|
|
18
|
+
/**
|
|
19
|
+
* @summary An editable pane of source, with highlighting and line numbers.
|
|
20
|
+
*
|
|
21
|
+
* @description
|
|
22
|
+
* CodeMirror, not a `<textarea>`. A textarea cannot highlight what it holds,
|
|
23
|
+
* number its lines, or say where the cursor is, and a status bar reading line
|
|
24
|
+
* and column has to ask something.
|
|
25
|
+
*
|
|
26
|
+
* **On its own path.** This is `@fusion.dev/helix-sandbox/editor`, and the
|
|
27
|
+
* package's root exports its class as a type only, because CodeMirror is most
|
|
28
|
+
* of what the package weighs over the wire. A sandbox with no editable pane
|
|
29
|
+
* pays for none, and neither does a site that registers its elements once.
|
|
30
|
+
*
|
|
31
|
+
* `language` names the grammar by the name a file or a sandbox pane carries:
|
|
32
|
+
* `css`, `html`, `js`, `jsx`, `mjs`, `sh`, `ts` or `tsx`. A name the editor
|
|
33
|
+
* does not read draws the source plain, and the console says so once.
|
|
34
|
+
*
|
|
35
|
+
* Each edit a reader makes is `helix-before-edit` first, which you can cancel
|
|
36
|
+
* to refuse the edit, and `helix-edit` once the source holds it, as
|
|
37
|
+
* `helix-sandbox-source` sends them. A `value` set from outside is the source the editor is given, and
|
|
38
|
+
* sends neither. **The editor is `:state(modified)` while its source differs
|
|
39
|
+
* from the source it was given**, the first `value` or the last one set from
|
|
40
|
+
* outside, and `reset()` puts that source back as an edit.
|
|
41
|
+
*
|
|
42
|
+
* The view is built once and reconfigured, not rebuilt. Replacing it on every
|
|
43
|
+
* change would throw away the undo history, the scroll position, and the
|
|
44
|
+
* selection, which is most of what an editor is.
|
|
45
|
+
*
|
|
46
|
+
* @since 0.1.0
|
|
47
|
+
* @status experimental
|
|
48
|
+
* @category tooling
|
|
49
|
+
* @aliases Code editor, Source pane
|
|
50
|
+
* @documentation https://fusion.dev/helix/docs/sandbox
|
|
51
|
+
*
|
|
52
|
+
* @event {HelixBeforeEditEvent} helix-before-edit - Fired before the source is edited. Cancelable: refusing it takes the decision and nothing moves.
|
|
53
|
+
* @event {HelixCaretEvent} helix-caret - Fired when the cursor moves, with its line and column.
|
|
54
|
+
* @event {HelixEditEvent} helix-edit - Fired after the source was edited, with the new source.
|
|
55
|
+
*
|
|
56
|
+
* @csspart editor - The element CodeMirror is mounted into.
|
|
57
|
+
*
|
|
58
|
+
* @cssstate modified - While the source differs from the source the editor was given, until `reset()` or a new `value`.
|
|
59
|
+
*/
|
|
60
|
+
export declare class HelixSandboxEditor extends HelixElement {
|
|
61
|
+
/**
|
|
62
|
+
* The key the editor's words are registered under, its tag:
|
|
63
|
+
* `registerWords('de', { 'helix-sandbox-editor': { fieldLabel: 'Quelltext' } })`.
|
|
64
|
+
*/
|
|
65
|
+
static words: string;
|
|
66
|
+
/**
|
|
67
|
+
* Accessible name for the editable region.
|
|
68
|
+
*/
|
|
69
|
+
fieldLabel: string;
|
|
70
|
+
/**
|
|
71
|
+
* The language of the source, which decides how it is highlighted. A name
|
|
72
|
+
* the editor does not read draws the source plain.
|
|
73
|
+
*/
|
|
74
|
+
language: EditorLanguage;
|
|
75
|
+
/**
|
|
76
|
+
* Which source this pane holds, echoed in every change.
|
|
77
|
+
*/
|
|
78
|
+
name: string;
|
|
79
|
+
/**
|
|
80
|
+
* Whether the text can be changed.
|
|
81
|
+
*
|
|
82
|
+
* `EditorState.readOnly` rather than removing the editor's focus or its
|
|
83
|
+
* keymap: a reader still needs to select the text, scroll it, and put a
|
|
84
|
+
* cursor in it to read a long line. What it stops is the typing.
|
|
85
|
+
*/
|
|
86
|
+
readOnly: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The source being edited.
|
|
89
|
+
*/
|
|
90
|
+
value: string;
|
|
91
|
+
private readonly readOnly$;
|
|
92
|
+
private view;
|
|
93
|
+
private readonly language$;
|
|
94
|
+
/** The editable region's name, which follows `field-label` and the words registered for it. */
|
|
95
|
+
private readonly name$;
|
|
96
|
+
/** The source the editor was given: its first `value`, or the last one set from outside. */
|
|
97
|
+
private baseline;
|
|
98
|
+
/** The source the last edit left, while `value` still holds it. */
|
|
99
|
+
private edited;
|
|
100
|
+
/** The `language` last reported as one the editor does not read. */
|
|
101
|
+
private unread;
|
|
102
|
+
/**
|
|
103
|
+
* Whether the source differs from the source the editor was given: its
|
|
104
|
+
* first `value`, or the last one set from outside.
|
|
105
|
+
*/
|
|
106
|
+
get modified(): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Puts back the source the editor was given, as an edit: `helix-before-edit`
|
|
109
|
+
* is sent first and can refuse it, and a sandbox passes it to its preview.
|
|
110
|
+
*/
|
|
111
|
+
reset(): void;
|
|
112
|
+
/**
|
|
113
|
+
* What `language` turns on: its grammar, or nothing for a name the editor
|
|
114
|
+
* does not read, which it reports once for each name.
|
|
115
|
+
*/
|
|
116
|
+
private grammar;
|
|
117
|
+
/** Where the cursor is, counted from one, as an editor reports it. */
|
|
118
|
+
get caret(): CaretDetail;
|
|
119
|
+
private get mount();
|
|
120
|
+
/**
|
|
121
|
+
* Builds the view once the mount exists.
|
|
122
|
+
*
|
|
123
|
+
* `root` is the shadow root rather than the document, or CodeMirror puts its
|
|
124
|
+
* stylesheet where this element cannot see it and the editor renders unstyled.
|
|
125
|
+
*/
|
|
126
|
+
private create;
|
|
127
|
+
/**
|
|
128
|
+
* Moves focus into the text, not onto the host.
|
|
129
|
+
*
|
|
130
|
+
* The host is not focusable: what a reader types into is CodeMirror's
|
|
131
|
+
* contenteditable, several nodes down inside this shadow root. Without this,
|
|
132
|
+
* `editor.focus()` from outside silently does nothing.
|
|
133
|
+
*/
|
|
134
|
+
focus(): void;
|
|
135
|
+
disconnectedCallback(): void;
|
|
136
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
137
|
+
protected updated(changed: PropertyValues): void;
|
|
138
|
+
protected render(): TemplateResult;
|
|
139
|
+
static styles: CSSResultGroup;
|
|
140
|
+
}
|
|
141
|
+
declare global {
|
|
142
|
+
interface HTMLElementTagNameMap {
|
|
143
|
+
'helix-sandbox-editor': HelixSandboxEditor;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=editor-root.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-root.d.ts","sourceRoot":"","sources":["../../../src/editor/root/editor-root.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,KAAK,WAAW,EAKhB,YAAY,EAGb,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,KAAK,CAAA;AAQzE;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,MAAM,GACN,YAAY,GACZ,IAAI,GACJ,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,CAAA;AA0BT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBACa,kBAAmB,SAAQ,YAAY;IAClD;;;OAGG;IACH,MAAM,CAAC,KAAK,SAAyB;IAErC;;OAEG;IAGH,UAAU,SAAmB;IAE7B;;;OAGG;IAEH,QAAQ,EAAE,cAAc,CAAS;IAEjC;;OAEG;IAEH,IAAI,SAAS;IAEb;;;;;;OAMG;IAEH,QAAQ,UAAQ;IAEhB;;OAEG;IAEH,KAAK,SAAK;IAEV,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAE9C,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAE9C,+FAA+F;IAC/F,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAE1C,4FAA4F;IAC5F,OAAO,CAAC,QAAQ,CAAK;IAErB,mEAAmE;IACnE,OAAO,CAAC,MAAM,CAAoB;IAElC,oEAAoE;IACpE,OAAO,CAAC,MAAM,CAAoB;IAElC;;;OAGG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;;OAGG;IACH,KAAK,IAAI,IAAI,CAKZ;IAED;;;OAGG;IACH,OAAO,CAAC,OAAO;IAkBf,sEAAsE;IACtE,IAAI,KAAK,IAAI,WAAW,CAQvB;IAED,OAAO,KAAK,KAAK,GAEhB;IAED;;;;;OAKG;IACH,OAAO,CAAC,MAAM;IAiFd;;;;;;OAMG;IACM,KAAK,IAAI,IAAI,CAErB;IAEQ,oBAAoB,IAAI,IAAI,CAIpC;IAED,UAAmB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAQ3D;IAED,UAAmB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAwCxD;IAED,UAAmB,MAAM,IAAI,cAAc,CAE1C;IAED,OAAgB,MAAM,EAAE,cAAc,CAAmC;CAC1E;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,kBAAkB,CAAA;KAC3C;CACF"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';
|
|
8
|
+
import { css } from '@codemirror/lang-css';
|
|
9
|
+
import { html as htmlLanguage } from '@codemirror/lang-html';
|
|
10
|
+
import { javascript } from '@codemirror/lang-javascript';
|
|
11
|
+
import { indentUnit, StreamLanguage, syntaxHighlighting } from '@codemirror/language';
|
|
12
|
+
import { Annotation, Compartment, EditorState } from '@codemirror/state';
|
|
13
|
+
import { EditorView, keymap, lineNumbers } from '@codemirror/view';
|
|
14
|
+
import { customElement, HelixBeforeEditEvent, HelixCaretEvent, HelixEditEvent, HelixElement, reportRuntime, words, } from '@fusion.dev/helix-core';
|
|
15
|
+
import { html, unsafeCSS } from 'lit';
|
|
16
|
+
import { property } from 'lit/decorators.js';
|
|
17
|
+
import { languageOf } from '../../highlight/language.js';
|
|
18
|
+
import { shellMode, shellTokens } from '../../highlight/shell.js';
|
|
19
|
+
import { syntaxHighlighter, syntaxRules } from '../../highlight/syntax.js';
|
|
20
|
+
import { styles } from './editor-root.css.js';
|
|
21
|
+
const shellLanguage = StreamLanguage.define({ ...shellMode, tokenTable: shellTokens });
|
|
22
|
+
const LANGUAGES = {
|
|
23
|
+
css: () => css(),
|
|
24
|
+
html: () => htmlLanguage(),
|
|
25
|
+
js: () => javascript(),
|
|
26
|
+
sh: () => shellLanguage,
|
|
27
|
+
ts: () => javascript({ typescript: true }),
|
|
28
|
+
tsx: () => javascript({ jsx: true, typescript: true }),
|
|
29
|
+
};
|
|
30
|
+
const given = Annotation.define();
|
|
31
|
+
let HelixSandboxEditor = class HelixSandboxEditor extends HelixElement {
|
|
32
|
+
constructor() {
|
|
33
|
+
super(...arguments);
|
|
34
|
+
this.fieldLabel = 'Example source';
|
|
35
|
+
this.language = 'html';
|
|
36
|
+
this.name = 'html';
|
|
37
|
+
this.readOnly = false;
|
|
38
|
+
this.value = '';
|
|
39
|
+
this.readOnly$ = new Compartment();
|
|
40
|
+
this.language$ = new Compartment();
|
|
41
|
+
this.name$ = new Compartment();
|
|
42
|
+
this.baseline = '';
|
|
43
|
+
}
|
|
44
|
+
static { this.words = 'helix-sandbox-editor'; }
|
|
45
|
+
get modified() {
|
|
46
|
+
return this.value === this.edited && this.value !== this.baseline;
|
|
47
|
+
}
|
|
48
|
+
reset() {
|
|
49
|
+
const view = this.view;
|
|
50
|
+
if (view && this.modified) {
|
|
51
|
+
view.dispatch({ changes: { from: 0, insert: this.baseline, to: view.state.doc.length } });
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
grammar() {
|
|
55
|
+
const read = languageOf(typeof this.language === 'string' ? this.language : '');
|
|
56
|
+
if (read !== undefined) {
|
|
57
|
+
return LANGUAGES[read]();
|
|
58
|
+
}
|
|
59
|
+
if (this.unread !== this.language) {
|
|
60
|
+
this.unread = this.language;
|
|
61
|
+
reportRuntime({
|
|
62
|
+
kind: 'unknown-language',
|
|
63
|
+
message: `<${this.localName} language="${this.language}"> names no language the editor reads, ` +
|
|
64
|
+
'so its source is drawn plain. Use css, html, js, jsx, mjs, sh, ts or tsx.',
|
|
65
|
+
tag: this.localName,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
get caret() {
|
|
71
|
+
const state = this.view?.state;
|
|
72
|
+
if (!state) {
|
|
73
|
+
return { column: 1, line: 1 };
|
|
74
|
+
}
|
|
75
|
+
const head = state.selection.main.head;
|
|
76
|
+
const line = state.doc.lineAt(head);
|
|
77
|
+
return { column: head - line.from + 1, line: line.number };
|
|
78
|
+
}
|
|
79
|
+
get mount() {
|
|
80
|
+
return this.renderRoot.querySelector('[part="editor"]');
|
|
81
|
+
}
|
|
82
|
+
create() {
|
|
83
|
+
const parent = this.mount;
|
|
84
|
+
if (!parent || this.view) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.view = new EditorView({
|
|
88
|
+
parent,
|
|
89
|
+
root: this.shadowRoot ?? document,
|
|
90
|
+
state: EditorState.create({
|
|
91
|
+
doc: this.value,
|
|
92
|
+
extensions: [
|
|
93
|
+
lineNumbers(),
|
|
94
|
+
history(),
|
|
95
|
+
indentUnit.of(' '),
|
|
96
|
+
EditorState.tabSize.of(2),
|
|
97
|
+
keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab]),
|
|
98
|
+
syntaxHighlighting(syntaxHighlighter, { fallback: true }),
|
|
99
|
+
this.language$.of(this.grammar()),
|
|
100
|
+
this.readOnly$.of(EditorState.readOnly.of(this.readOnly)),
|
|
101
|
+
EditorView.lineWrapping,
|
|
102
|
+
EditorState.transactionFilter.of((transaction) => {
|
|
103
|
+
if (!transaction.docChanged || transaction.annotation(given)) {
|
|
104
|
+
return transaction;
|
|
105
|
+
}
|
|
106
|
+
const next = transaction.newDoc.toString();
|
|
107
|
+
const request = new HelixBeforeEditEvent({ value: next });
|
|
108
|
+
return this.dispatchEvent(request) ? transaction : [];
|
|
109
|
+
}),
|
|
110
|
+
EditorView.updateListener.of((update) => {
|
|
111
|
+
const edit = update.docChanged &&
|
|
112
|
+
!update.transactions.some((transaction) => transaction.annotation(given));
|
|
113
|
+
if (edit) {
|
|
114
|
+
const next = update.state.doc.toString();
|
|
115
|
+
this.edited = next;
|
|
116
|
+
this.value = next;
|
|
117
|
+
this.dispatchEvent(new HelixEditEvent({ value: next }));
|
|
118
|
+
}
|
|
119
|
+
if (update.selectionSet || update.docChanged || update.focusChanged) {
|
|
120
|
+
this.dispatchEvent(new HelixCaretEvent(this.caret));
|
|
121
|
+
}
|
|
122
|
+
}),
|
|
123
|
+
this.name$.of(EditorView.contentAttributes.of({ 'aria-label': this.fieldLabel })),
|
|
124
|
+
],
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
this.dispatchEvent(new HelixCaretEvent(this.caret));
|
|
128
|
+
}
|
|
129
|
+
focus() {
|
|
130
|
+
this.view?.focus();
|
|
131
|
+
}
|
|
132
|
+
disconnectedCallback() {
|
|
133
|
+
super.disconnectedCallback();
|
|
134
|
+
this.view?.destroy();
|
|
135
|
+
this.view = undefined;
|
|
136
|
+
}
|
|
137
|
+
willUpdate(changed) {
|
|
138
|
+
super.willUpdate(changed);
|
|
139
|
+
if (this.value !== this.edited) {
|
|
140
|
+
this.baseline = this.value;
|
|
141
|
+
this.edited = undefined;
|
|
142
|
+
}
|
|
143
|
+
this.toggleState('modified', this.modified);
|
|
144
|
+
}
|
|
145
|
+
updated(changed) {
|
|
146
|
+
super.updated(changed);
|
|
147
|
+
this.create();
|
|
148
|
+
const view = this.view;
|
|
149
|
+
if (!view) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (changed.has('language')) {
|
|
153
|
+
view.dispatch({ effects: this.language$.reconfigure(this.grammar()) });
|
|
154
|
+
}
|
|
155
|
+
if (changed.has('fieldLabel')) {
|
|
156
|
+
view.dispatch({
|
|
157
|
+
effects: this.name$.reconfigure(EditorView.contentAttributes.of({ 'aria-label': this.fieldLabel })),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
if (changed.has('readOnly')) {
|
|
161
|
+
view.dispatch({
|
|
162
|
+
effects: this.readOnly$.reconfigure(EditorState.readOnly.of(this.readOnly)),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
if (changed.has('value') && this.value !== view.state.doc.toString()) {
|
|
166
|
+
const head = view.state.selection.main.head;
|
|
167
|
+
view.dispatch({
|
|
168
|
+
annotations: given.of(true),
|
|
169
|
+
changes: { from: 0, insert: this.value, to: view.state.doc.length },
|
|
170
|
+
selection: { anchor: Math.min(head, this.value.length) },
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
render() {
|
|
175
|
+
return html `<div part="editor"></div>`;
|
|
176
|
+
}
|
|
177
|
+
static { this.styles = [styles, unsafeCSS(syntaxRules)]; }
|
|
178
|
+
};
|
|
179
|
+
__decorate([
|
|
180
|
+
words,
|
|
181
|
+
property({ attribute: 'field-label' })
|
|
182
|
+
], HelixSandboxEditor.prototype, "fieldLabel", void 0);
|
|
183
|
+
__decorate([
|
|
184
|
+
property()
|
|
185
|
+
], HelixSandboxEditor.prototype, "language", void 0);
|
|
186
|
+
__decorate([
|
|
187
|
+
property()
|
|
188
|
+
], HelixSandboxEditor.prototype, "name", void 0);
|
|
189
|
+
__decorate([
|
|
190
|
+
property({ attribute: 'readonly', reflect: true, type: Boolean })
|
|
191
|
+
], HelixSandboxEditor.prototype, "readOnly", void 0);
|
|
192
|
+
__decorate([
|
|
193
|
+
property()
|
|
194
|
+
], HelixSandboxEditor.prototype, "value", void 0);
|
|
195
|
+
HelixSandboxEditor = __decorate([
|
|
196
|
+
customElement('helix-sandbox-editor')
|
|
197
|
+
], HelixSandboxEditor);
|
|
198
|
+
export { HelixSandboxEditor };
|
|
199
|
+
//# sourceMappingURL=editor-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-root.js","sourceRoot":"","sources":["../../../src/editor/root/editor-root.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Highlighter } from '@lezer/highlight';
|
|
2
|
+
import type { HighlightLanguage } from './language.js';
|
|
3
|
+
/**
|
|
4
|
+
* Highlights a snippet, returning HTML with one span per token.
|
|
5
|
+
*
|
|
6
|
+
* **A parser, and no editor.** Lezer's grammars are parsers, and parsing is a
|
|
7
|
+
* pure function of the text: `highlightCode` walks a tree and hands back
|
|
8
|
+
* tokens. Nothing is mounted, no document is created, and this runs on a server
|
|
9
|
+
* with no DOM at all, which is what lets a static page ship highlighted code
|
|
10
|
+
* with no client JavaScript spent on it.
|
|
11
|
+
*
|
|
12
|
+
* **`CodeBlock` holds no parser.** A `dependencies` entry is paid by every
|
|
13
|
+
* consumer whether or not they import it, so the grammars are in this package,
|
|
14
|
+
* beside the editor that reads them too. `CodeBlock` renders a `<slot>`, so the
|
|
15
|
+
* output of this drops straight into one. A snippet on a reference page and the
|
|
16
|
+
* same snippet open in the sandbox are then colored by one source.
|
|
17
|
+
*
|
|
18
|
+
* `classHighlighter` emits Lezer's own `tok-` class names. Mapping those to
|
|
19
|
+
* colors is yours, because the classes are stable and a palette is not: the
|
|
20
|
+
* Fusion site paints them from `--helix-color-syntax-*`. Pass another
|
|
21
|
+
* `highlighter` for other classes, such as `syntaxHighlighter`, the editor's
|
|
22
|
+
* own, whose rules are `syntaxRules`.
|
|
23
|
+
*/
|
|
24
|
+
export declare const highlight: (code: string, language: HighlightLanguage, highlighter?: Highlighter) => string;
|
|
25
|
+
//# sourceMappingURL=highlight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.d.ts","sourceRoot":"","sources":["../../src/highlight/highlight.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,WAAW,EAAiB,MAAM,kBAAkB,CAAA;AAGpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AA2GtD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,SAAS,SACd,MAAM,YACF,iBAAiB,gBACd,WAAW,KACvB,MAcF,CAAA"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { parser as cssParser } from '@lezer/css';
|
|
2
|
+
import { classHighlighter, highlightCode } from '@lezer/highlight';
|
|
3
|
+
import { configureNesting, parser as htmlParser } from '@lezer/html';
|
|
4
|
+
import { parser as jsParser } from '@lezer/javascript';
|
|
5
|
+
import { shellMode, shellTokens } from './shell.js';
|
|
6
|
+
import { highlightStream } from './stream.js';
|
|
7
|
+
const EVENT_ATTRIBUTES = [
|
|
8
|
+
'beforeunload',
|
|
9
|
+
'blur',
|
|
10
|
+
'change',
|
|
11
|
+
'click',
|
|
12
|
+
'copy',
|
|
13
|
+
'cut',
|
|
14
|
+
'drag',
|
|
15
|
+
'dragend',
|
|
16
|
+
'dragenter',
|
|
17
|
+
'dragleave',
|
|
18
|
+
'dragover',
|
|
19
|
+
'dragstart',
|
|
20
|
+
'focus',
|
|
21
|
+
'keydown',
|
|
22
|
+
'keyup',
|
|
23
|
+
'load',
|
|
24
|
+
'mousedown',
|
|
25
|
+
'mouseenter',
|
|
26
|
+
'mouseleave',
|
|
27
|
+
'mouseup',
|
|
28
|
+
'paste',
|
|
29
|
+
'resize',
|
|
30
|
+
'scroll',
|
|
31
|
+
'unload',
|
|
32
|
+
].map((name) => `on${name}`);
|
|
33
|
+
const typescript = jsParser.configure({ dialect: 'ts' });
|
|
34
|
+
const tsx = jsParser.configure({ dialect: 'jsx ts' });
|
|
35
|
+
const PARSERS = {
|
|
36
|
+
css: cssParser,
|
|
37
|
+
html: htmlParser.configure({
|
|
38
|
+
wrap: configureNesting([
|
|
39
|
+
{
|
|
40
|
+
attrs: (attrs) => attrs.type === 'text/typescript' || attrs.lang === 'ts',
|
|
41
|
+
parser: typescript,
|
|
42
|
+
tag: 'script',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
attrs: (attrs) => attrs.type === 'text/babel' || attrs.type === 'text/jsx',
|
|
46
|
+
parser: jsParser.configure({ dialect: 'jsx' }),
|
|
47
|
+
tag: 'script',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
attrs: (attrs) => attrs.type === 'text/typescript-jsx',
|
|
51
|
+
parser: tsx,
|
|
52
|
+
tag: 'script',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
attrs: (attrs) => /^(importmap|speculationrules|application\/(.+\+)?json)$/i.test(attrs.type ?? ''),
|
|
56
|
+
parser: jsParser.configure({ top: 'SingleExpression' }),
|
|
57
|
+
tag: 'script',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
attrs: (attrs) => !attrs.type ||
|
|
61
|
+
/^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^module$|^$/i.test(attrs.type),
|
|
62
|
+
parser: jsParser,
|
|
63
|
+
tag: 'script',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
attrs: (attrs) => (!attrs.lang || attrs.lang === 'css') &&
|
|
67
|
+
(!attrs.type || /^(text\/)?(x-)?(stylesheet|css)$/i.test(attrs.type)),
|
|
68
|
+
parser: cssParser,
|
|
69
|
+
tag: 'style',
|
|
70
|
+
},
|
|
71
|
+
], [
|
|
72
|
+
{ name: 'style', parser: cssParser.configure({ top: 'Styles' }) },
|
|
73
|
+
...EVENT_ATTRIBUTES.map((name) => ({ name, parser: jsParser })),
|
|
74
|
+
]),
|
|
75
|
+
}),
|
|
76
|
+
js: jsParser,
|
|
77
|
+
ts: typescript,
|
|
78
|
+
tsx,
|
|
79
|
+
};
|
|
80
|
+
const escapeHtml = (text) => text.replace(/[&<>"']/g, (char) => ({ "'": ''', '"': '"', '&': '&', '<': '<', '>': '>' })[char] ?? char);
|
|
81
|
+
export const highlight = (code, language, highlighter = classHighlighter) => {
|
|
82
|
+
let out = '';
|
|
83
|
+
const put = (text, classes) => {
|
|
84
|
+
out += classes ? `<span class="${classes}">${escapeHtml(text)}</span>` : escapeHtml(text);
|
|
85
|
+
};
|
|
86
|
+
const putBreak = () => {
|
|
87
|
+
out += '\n';
|
|
88
|
+
};
|
|
89
|
+
if (language === 'sh') {
|
|
90
|
+
highlightStream(code, shellMode, shellTokens, highlighter, put, putBreak);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
highlightCode(code, PARSERS[language].parse(code), highlighter, put, putBreak);
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=highlight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../src/highlight/highlight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/highlight/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/highlight/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAA0B,UAAU,EAAE,MAAM,eAAe,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The languages a snippet can be written in.
|
|
3
|
+
*
|
|
4
|
+
* **`ts` and `tsx` are here because the documentation is mostly written in
|
|
5
|
+
* them**, and the base JavaScript grammar reads both wrongly, where a partial
|
|
6
|
+
* reading would be harmless. Measured on a `tsx` fence highlighted as `js`:
|
|
7
|
+
* `<helix-input` came out as the variable `helix`, the operator `-` and the
|
|
8
|
+
* variable `input`, which is the parser doing arithmetic on a tag name and
|
|
9
|
+
* coloring the result confidently. A grammar that does not know the dialect
|
|
10
|
+
* does not degrade, it lies.
|
|
11
|
+
*
|
|
12
|
+
* `tsx` covers JSX as well, since the dialect is a superset: there is no `jsx`
|
|
13
|
+
* member because a JSX file that is not TypeScript still parses under it, and
|
|
14
|
+
* a fourth entry would be a distinction with no consequence. `languageOf`
|
|
15
|
+
* reads `jsx` as `tsx`.
|
|
16
|
+
*
|
|
17
|
+
* `sh` is the one grammar here that is not shipped as it comes: see `shell.ts`
|
|
18
|
+
* for why a mode that knows sh perfectly colors nothing in `bun add`.
|
|
19
|
+
*/
|
|
20
|
+
export type HighlightLanguage = 'css' | 'html' | 'js' | 'sh' | 'ts' | 'tsx';
|
|
21
|
+
/**
|
|
22
|
+
* The language a name stands for, in any case: `TypeScript`, `bash` or `mjs`.
|
|
23
|
+
* `undefined` for a name no grammar here reads.
|
|
24
|
+
*/
|
|
25
|
+
export declare const languageOf: (name: string) => HighlightLanguage | undefined;
|
|
26
|
+
//# sourceMappingURL=language.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../src/highlight/language.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,CAAA;AA2B3E;;;GAGG;AACH,eAAO,MAAM,UAAU,SAAU,MAAM,KAAG,iBAAiB,GAAG,SAC5B,CAAA"}
|