@cascivo/editor 0.0.1 → 0.1.1
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 +31 -1
- package/package.json +20 -20
- package/readme.body.md +31 -1
- package/dist/editor.css +0 -2
- package/dist/index.d.ts +0 -202
- package/dist/index.js +0 -701
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 urbanisierung
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -16,7 +16,11 @@
|
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
|
19
|
-
A lightweight, CSS-native, signal-driven code editor for cascivo. `CodeEditor` overlays a native `<textarea>` on a syntax-highlighted `<pre>`, so the browser owns the caret, selection, IME,
|
|
19
|
+
A lightweight, CSS-native, signal-driven code editor for cascivo. `CodeEditor` overlays a native `<textarea>` on a syntax-highlighted `<pre>`, so the browser owns the caret, selection, IME, and accessibility — JS adds an owned tokenizer, scroll-sync, and a thin layer of editing affordances. `Highlight` is the read-only renderer for snippets and docs. Zero runtime dependencies, themeable through the cascivo token system.
|
|
20
|
+
|
|
21
|
+
Beyond highlighting it provides the essentials for editing real documents: **owned undo/redo** (`Mod-Z` / `Mod-Shift-Z`) that survives programmatic `value` changes, **selection-preserving, echo-safe controlled sync** (external/remote updates don't jump the caret), **find & replace** (`Mod-F`), a **`Mod-S` save** hook, **per-instance theming** that can switch live, **bracket matching**, an **active-line gutter**, and an imperative **`CodeEditorHandle`**.
|
|
22
|
+
|
|
23
|
+
It is deliberately not a full editor engine: no LSP/IntelliSense, multi-cursor, code folding, minimap, or vim mode — reach for a full framework (Monaco/CodeMirror) if you need those.
|
|
20
24
|
|
|
21
25
|
## Install
|
|
22
26
|
|
|
@@ -54,6 +58,32 @@ import { Highlight } from '@cascivo/editor'
|
|
|
54
58
|
Ships small, tree-shakeable grammars: `plaintext`, `json`, `javascript`, `typescript`, `css`,
|
|
55
59
|
`html`, `markdown`, `bash`. Register your own with `registerGrammar(grammar)`.
|
|
56
60
|
|
|
61
|
+
### Extending the editor
|
|
62
|
+
|
|
63
|
+
Three bounded seams — no plugin lifecycle, no transaction filters (use a full editor
|
|
64
|
+
framework if you need those):
|
|
65
|
+
|
|
66
|
+
- **Key bindings** — pass a `keymap` of `chord → command`. Chords use `Mod` for
|
|
67
|
+
Cmd/Ctrl (e.g. `'Mod-s'`, `'Mod-Shift-z'`, `'Shift-Tab'`); a command returns `true`
|
|
68
|
+
when it handled the event. User bindings merge over (and override) the built-ins.
|
|
69
|
+
- **Decorations** — pass `decorations` (an array, or `(value) => Decoration[]`) to tag
|
|
70
|
+
`{ line, start, end, className }` column ranges; they render as extra classes in the
|
|
71
|
+
highlight layer (the same seam find and bracket-matching use).
|
|
72
|
+
- **Grammars** — register a language with `registerGrammar(grammar)`.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
<CodeEditor
|
|
76
|
+
language="markdown"
|
|
77
|
+
onSave={(value) => save(value)} // Mod-S
|
|
78
|
+
keymap={{
|
|
79
|
+
'Mod-/': ({ textarea, setText }) => {
|
|
80
|
+
/* toggle comment */ return true
|
|
81
|
+
},
|
|
82
|
+
}}
|
|
83
|
+
decorations={(value) => findTodos(value)}
|
|
84
|
+
/>
|
|
85
|
+
```
|
|
86
|
+
|
|
57
87
|
### React apps must subscribe to signals
|
|
58
88
|
|
|
59
89
|
`CodeEditor` and `Highlight` are signal-driven. In a plain React app (no Babel signals transform),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cascivo/editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Lightweight CSS-native code editor — native textarea overlay + owned zero-dependency tokenizer",
|
|
6
6
|
"keywords": [
|
|
@@ -42,31 +42,31 @@
|
|
|
42
42
|
"access": "public",
|
|
43
43
|
"provenance": true
|
|
44
44
|
},
|
|
45
|
-
"scripts": {
|
|
46
|
-
"build": "vp build && node scripts/flatten-types.mjs && node scripts/check-types-flat.mjs",
|
|
47
|
-
"check": "tsc --noEmit",
|
|
48
|
-
"test": "vp test"
|
|
49
|
-
},
|
|
50
45
|
"dependencies": {
|
|
51
|
-
"@cascivo/core": "
|
|
52
|
-
"@cascivo/i18n": "
|
|
46
|
+
"@cascivo/core": "^0.1.3",
|
|
47
|
+
"@cascivo/i18n": "^0.1.6"
|
|
53
48
|
},
|
|
54
49
|
"devDependencies": {
|
|
55
|
-
"@testing-library/jest-dom": "
|
|
56
|
-
"@testing-library/react": "
|
|
57
|
-
"@testing-library/user-event": "
|
|
58
|
-
"@types/react": "
|
|
59
|
-
"@types/react-dom": "
|
|
60
|
-
"fast-check": "
|
|
61
|
-
"jsdom": "
|
|
62
|
-
"react": "
|
|
63
|
-
"react-dom": "
|
|
64
|
-
"typescript": "
|
|
65
|
-
"vite-plus": "
|
|
50
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
51
|
+
"@testing-library/react": "^16.3.2",
|
|
52
|
+
"@testing-library/user-event": "^14",
|
|
53
|
+
"@types/react": "^19.2.17",
|
|
54
|
+
"@types/react-dom": "^19.2.3",
|
|
55
|
+
"fast-check": "^4.0.0",
|
|
56
|
+
"jsdom": "^29",
|
|
57
|
+
"react": "^19.2.7",
|
|
58
|
+
"react-dom": "^19.2.7",
|
|
59
|
+
"typescript": "^5",
|
|
60
|
+
"vite-plus": "^0.2.1"
|
|
66
61
|
},
|
|
67
62
|
"peerDependencies": {
|
|
68
63
|
"@preact/signals-react": ">=2.0.0",
|
|
69
64
|
"react": ">=18.0.0",
|
|
70
65
|
"react-dom": ">=18.0.0"
|
|
66
|
+
},
|
|
67
|
+
"scripts": {
|
|
68
|
+
"build": "vp build && node scripts/flatten-types.mjs && node scripts/check-types-flat.mjs",
|
|
69
|
+
"check": "tsc --noEmit",
|
|
70
|
+
"test": "vp test"
|
|
71
71
|
}
|
|
72
|
-
}
|
|
72
|
+
}
|
package/readme.body.md
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
A lightweight, CSS-native, signal-driven code editor for cascivo. `CodeEditor` overlays a native `<textarea>` on a syntax-highlighted `<pre>`, so the browser owns the caret, selection, IME,
|
|
1
|
+
A lightweight, CSS-native, signal-driven code editor for cascivo. `CodeEditor` overlays a native `<textarea>` on a syntax-highlighted `<pre>`, so the browser owns the caret, selection, IME, and accessibility — JS adds an owned tokenizer, scroll-sync, and a thin layer of editing affordances. `Highlight` is the read-only renderer for snippets and docs. Zero runtime dependencies, themeable through the cascivo token system.
|
|
2
|
+
|
|
3
|
+
Beyond highlighting it provides the essentials for editing real documents: **owned undo/redo** (`Mod-Z` / `Mod-Shift-Z`) that survives programmatic `value` changes, **selection-preserving, echo-safe controlled sync** (external/remote updates don't jump the caret), **find & replace** (`Mod-F`), a **`Mod-S` save** hook, **per-instance theming** that can switch live, **bracket matching**, an **active-line gutter**, and an imperative **`CodeEditorHandle`**.
|
|
4
|
+
|
|
5
|
+
It is deliberately not a full editor engine: no LSP/IntelliSense, multi-cursor, code folding, minimap, or vim mode — reach for a full framework (Monaco/CodeMirror) if you need those.
|
|
2
6
|
|
|
3
7
|
## Install
|
|
4
8
|
|
|
@@ -36,6 +40,32 @@ import { Highlight } from '@cascivo/editor'
|
|
|
36
40
|
Ships small, tree-shakeable grammars: `plaintext`, `json`, `javascript`, `typescript`, `css`,
|
|
37
41
|
`html`, `markdown`, `bash`. Register your own with `registerGrammar(grammar)`.
|
|
38
42
|
|
|
43
|
+
### Extending the editor
|
|
44
|
+
|
|
45
|
+
Three bounded seams — no plugin lifecycle, no transaction filters (use a full editor
|
|
46
|
+
framework if you need those):
|
|
47
|
+
|
|
48
|
+
- **Key bindings** — pass a `keymap` of `chord → command`. Chords use `Mod` for
|
|
49
|
+
Cmd/Ctrl (e.g. `'Mod-s'`, `'Mod-Shift-z'`, `'Shift-Tab'`); a command returns `true`
|
|
50
|
+
when it handled the event. User bindings merge over (and override) the built-ins.
|
|
51
|
+
- **Decorations** — pass `decorations` (an array, or `(value) => Decoration[]`) to tag
|
|
52
|
+
`{ line, start, end, className }` column ranges; they render as extra classes in the
|
|
53
|
+
highlight layer (the same seam find and bracket-matching use).
|
|
54
|
+
- **Grammars** — register a language with `registerGrammar(grammar)`.
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<CodeEditor
|
|
58
|
+
language="markdown"
|
|
59
|
+
onSave={(value) => save(value)} // Mod-S
|
|
60
|
+
keymap={{
|
|
61
|
+
'Mod-/': ({ textarea, setText }) => {
|
|
62
|
+
/* toggle comment */ return true
|
|
63
|
+
},
|
|
64
|
+
}}
|
|
65
|
+
decorations={(value) => findTodos(value)}
|
|
66
|
+
/>
|
|
67
|
+
```
|
|
68
|
+
|
|
39
69
|
### React apps must subscribe to signals
|
|
40
70
|
|
|
41
71
|
`CodeEditor` and `Highlight` are signal-driven. In a plain React app (no Babel signals transform),
|
package/dist/editor.css
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
@layer cascivo.component{._root_4k2k5_2{background:var(--cascivo-editor-bg);max-block-size:100%;color:var(--cascivo-editor-fg);border:1px solid var(--cascivo-editor-border);border-radius:var(--cascivo-radius-field);font-family:var(--cascivo-font-mono);font-size:var(--cascivo-text-sm);line-height:var(--cascivo-leading-normal);tab-size:var(--cascivo-editor-tab-size,2);display:flex;overflow:auto}._gutter_4k2k5_17{padding-block:var(--cascivo-space-3);background:var(--cascivo-editor-gutter-bg);color:var(--cascivo-editor-gutter-fg);text-align:end;-webkit-user-select:none;user-select:none;flex:none;padding-inline-start:var(--cascivo-space-3);padding-inline-end:var(--cascivo-space-2)}._gutterLine_4k2k5_28{min-block-size:1lh;display:block}._pre_4k2k5_33{min-inline-size:0;padding-block:var(--cascivo-space-3);padding-inline:var(--cascivo-space-3);white-space:pre;font:inherit;tab-size:inherit;flex:auto;margin-block:0;margin-inline:0}._code_4k2k5_45{font:inherit}._line_4k2k5_50{min-block-size:1lh;display:block}._root_4k2k5_2[data-wrap=true] ._pre_4k2k5_33{white-space:pre-wrap;word-break:break-word}._root_4k2k5_2[data-line-numbers=false] ._gutter_4k2k5_17{display:none}._plain_4k2k5_65{color:var(--cascivo-editor-fg)}._keyword_4k2k5_68{color:var(--cascivo-editor-syntax-keyword)}._string_4k2k5_71{color:var(--cascivo-editor-syntax-string)}._number_4k2k5_74{color:var(--cascivo-editor-syntax-number)}._comment_4k2k5_77{color:var(--cascivo-editor-syntax-comment);font-style:italic}._function_4k2k5_81{color:var(--cascivo-editor-syntax-function)}._type_4k2k5_84{color:var(--cascivo-editor-syntax-type)}._operator_4k2k5_87{color:var(--cascivo-editor-syntax-operator)}._punctuation_4k2k5_90{color:var(--cascivo-editor-syntax-punctuation)}._variable_4k2k5_93{color:var(--cascivo-editor-syntax-variable)}._tag_4k2k5_96{color:var(--cascivo-editor-syntax-tag)}._attr_4k2k5_99{color:var(--cascivo-editor-syntax-attr)}._regexp_4k2k5_102{color:var(--cascivo-editor-syntax-regexp)}._boolean_4k2k5_105{color:var(--cascivo-editor-syntax-boolean)}._property_4k2k5_108{color:var(--cascivo-editor-syntax-property)}._root_q71hw_2{background:var(--cascivo-editor-bg);color:var(--cascivo-editor-fg);border:1px solid var(--cascivo-editor-border);border-radius:var(--cascivo-radius-field);font-family:var(--cascivo-font-mono);font-size:var(--cascivo-text-sm);line-height:var(--cascivo-leading-normal);tab-size:var(--cascivo-editor-tab-size,2);transition:box-shadow var(--cascivo-duration-150) var(--cascivo-ease-out);display:flex;position:relative;overflow:hidden}._root_q71hw_2:has(._textarea_q71hw_18:focus-visible){box-shadow:var(--cascivo-focus-ring);border-color:var(--cascivo-color-accent)}._gutter_q71hw_23{padding-block:var(--cascivo-space-3);background:var(--cascivo-editor-gutter-bg);color:var(--cascivo-editor-gutter-fg);text-align:end;-webkit-user-select:none;user-select:none;flex:none;padding-inline-start:var(--cascivo-space-3);padding-inline-end:var(--cascivo-space-2);overflow:hidden}._codeArea_q71hw_35{flex:auto;min-inline-size:0;position:relative}._pre_q71hw_42{padding-block:var(--cascivo-space-3);padding-inline:var(--cascivo-space-3);white-space:pre;pointer-events:none;font:inherit;tab-size:inherit;margin-block:0;margin-inline:0;position:absolute;inset:0;overflow:hidden}._currentLine_q71hw_57{inset-inline:0;top:var(--cascivo-space-3);block-size:1lh;transform:translateY(calc(var(--cascivo-editor-caret-line,0) * 1lh));background:var(--cascivo-editor-current-line);pointer-events:none;position:absolute}._textarea_q71hw_18{block-size:100%;inline-size:100%;padding-block:var(--cascivo-space-3);padding-inline:var(--cascivo-space-3);resize:none;color:#0000;caret-color:var(--cascivo-editor-fg);white-space:pre;font:inherit;tab-size:inherit;background:0 0;border:0;outline:none;margin-block:0;margin-inline:0;position:absolute;inset:0;overflow:auto}._textarea_q71hw_18::placeholder{color:var(--cascivo-editor-gutter-fg)}._textarea_q71hw_18::selection{background:var(--cascivo-editor-selection)}._textarea_q71hw_18:disabled{cursor:not-allowed;opacity:var(--cascivo-disabled-opacity)}._root_q71hw_2[data-wrap=true] ._pre_q71hw_42,._root_q71hw_2[data-wrap=true] ._textarea_q71hw_18{white-space:pre-wrap;word-break:break-word}._root_q71hw_2[data-line-numbers=false] ._gutter_q71hw_23{display:none}@media (pointer:coarse){._root_q71hw_2{min-block-size:var(--cascivo-target-min-coarse,2.75rem)}}@media (prefers-reduced-motion:reduce){._root_q71hw_2{transition:none}}}@media (forced-colors:active){._root_q71hw_2{border:1px solid fieldtext}._pre_q71hw_42{display:none}._textarea_q71hw_18{color:canvastext;caret-color:canvastext}}
|
|
2
|
-
/*$vite$:1*/
|
package/dist/index.d.ts
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { HTMLAttributes, Ref, TextareaHTMLAttributes } from "react";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Token classes the syntax palette colors. Every kind maps to a
|
|
5
|
-
* `--cascivo-editor-syntax-<kind>` custom property (see @cascivo/tokens). `plain`
|
|
6
|
-
* is uncolored text (whitespace, identifiers a grammar chose not to classify).
|
|
7
|
-
*/
|
|
8
|
-
type TokenKind = 'keyword' | 'string' | 'number' | 'comment' | 'function' | 'type' | 'operator' | 'punctuation' | 'variable' | 'tag' | 'attr' | 'regexp' | 'boolean' | 'property' | 'plain';
|
|
9
|
-
/** A single highlighted span. The concatenation of a line's token values is the line. */
|
|
10
|
-
interface Token {
|
|
11
|
-
kind: TokenKind;
|
|
12
|
-
value: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Opaque per-grammar continuation carried from one line to the next so multi-line
|
|
16
|
-
* constructs (block comments, template literals, fenced code) continue correctly.
|
|
17
|
-
* Each grammar owns the meaning of its own state strings; `'default'` is the start.
|
|
18
|
-
*/
|
|
19
|
-
type GrammarState = string;
|
|
20
|
-
/** Result of tokenizing one line: its spans plus the state to feed the next line. */
|
|
21
|
-
interface LineTokens {
|
|
22
|
-
tokens: Token[];
|
|
23
|
-
state: GrammarState;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* A language grammar. Pure and deterministic: `tokenizeLine` must depend only on
|
|
27
|
-
* `(line, state)` and must be lossless (the token values concatenate back to `line`).
|
|
28
|
-
*/
|
|
29
|
-
interface Grammar {
|
|
30
|
-
name: string;
|
|
31
|
-
initialState: GrammarState;
|
|
32
|
-
tokenizeLine(line: string, state: GrammarState): LineTokens;
|
|
33
|
-
}
|
|
34
|
-
/** Result of tokenizing one line: spans plus the continuation state. */
|
|
35
|
-
interface TokenizeResult {
|
|
36
|
-
tokens: Token[];
|
|
37
|
-
endState: GrammarState;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Tokenize a single line, restartable from `startState`, memoized. Pure from the
|
|
41
|
-
* caller's perspective: identical `(grammar, line, startState)` yield identical
|
|
42
|
-
* results (a cache hit returns the previously-computed value).
|
|
43
|
-
*/
|
|
44
|
-
declare function tokenize(grammar: Grammar, line: string, startState: GrammarState): TokenizeResult;
|
|
45
|
-
/**
|
|
46
|
-
* Tokenize a whole document, threading each line's `endState` into the next so
|
|
47
|
-
* block comments / template literals / fenced code continue across lines.
|
|
48
|
-
* Returns one token array per line. The per-line memo makes a single-line edit
|
|
49
|
-
* re-tokenize only the changed line(s) until the start-state reconverges.
|
|
50
|
-
*/
|
|
51
|
-
declare function tokenizeDocument(grammar: Grammar, text: string): Token[][];
|
|
52
|
-
/** Register (or replace) a grammar under its `name`. */
|
|
53
|
-
declare function registerGrammar(grammar: Grammar): void;
|
|
54
|
-
/** Resolve a grammar by name, falling back to `plaintext` for unknown languages. */
|
|
55
|
-
declare function getGrammar(name?: string): Grammar;
|
|
56
|
-
/** List the names of all currently-registered grammars. */
|
|
57
|
-
declare function listGrammars(): string[];
|
|
58
|
-
/**
|
|
59
|
-
* One tokenizer rule. `match` is anchored at the current scan position (compiled
|
|
60
|
-
* sticky internally). On a non-empty match the matched text becomes a token of
|
|
61
|
-
* `kind`, the position advances, and the state transitions via `push`/`pop`.
|
|
62
|
-
*/
|
|
63
|
-
interface Rule {
|
|
64
|
-
match: RegExp;
|
|
65
|
-
kind: TokenKind;
|
|
66
|
-
/** Switch to this state after matching (for entering multi-line constructs). */
|
|
67
|
-
push?: string;
|
|
68
|
-
/** Return to the `default` state after matching (for leaving them). */
|
|
69
|
-
pop?: boolean;
|
|
70
|
-
}
|
|
71
|
-
interface RuleSpec {
|
|
72
|
-
name: string;
|
|
73
|
-
/** Per-state ordered rule lists. Must include a `default` state. */
|
|
74
|
-
states: Record<string, Rule[]>;
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Build a {@link Grammar} from ordered, state-keyed regex rules — a tiny
|
|
78
|
-
* Monarch/Prism-style engine. At each position, the first rule in the current
|
|
79
|
-
* state whose sticky regex matches wins; unmatched characters accumulate into
|
|
80
|
-
* `plain` tokens, so the tokenizer is always lossless. State carries across
|
|
81
|
-
* lines for block comments, template literals, and fenced code.
|
|
82
|
-
*/
|
|
83
|
-
declare function createRuleGrammar(spec: RuleSpec): Grammar;
|
|
84
|
-
/** The trivial fallback grammar: one uncolored `plain` token per line. */
|
|
85
|
-
declare const plaintext: Grammar;
|
|
86
|
-
/**
|
|
87
|
-
* JSON: property keys vs string values, numbers, booleans/null, punctuation.
|
|
88
|
-
* A string immediately followed by a colon is a property key; other strings are
|
|
89
|
-
* values.
|
|
90
|
-
*/
|
|
91
|
-
declare const json: Grammar;
|
|
92
|
-
/** JavaScript: keywords, strings (incl. multi-line template literals), numbers,
|
|
93
|
-
* line + block comments (state carry), function calls, identifiers, operators. */
|
|
94
|
-
declare const javascript: Grammar;
|
|
95
|
-
declare const typescript: Grammar;
|
|
96
|
-
/**
|
|
97
|
-
* CSS: at-rules, selectors, property names, values, numbers/units, strings, and
|
|
98
|
-
* `/* *\/` block comments (state carried across lines).
|
|
99
|
-
*/
|
|
100
|
-
declare const css: Grammar;
|
|
101
|
-
/**
|
|
102
|
-
* HTML: tags, attribute names/values, `<!-- -->` comments (state carried across
|
|
103
|
-
* lines), and text. Inside a tag, attributes and strings are colored until `>`.
|
|
104
|
-
*/
|
|
105
|
-
declare const html: Grammar;
|
|
106
|
-
/**
|
|
107
|
-
* Markdown: headings, strong/emphasis, inline code, fenced code blocks (state
|
|
108
|
-
* carried across lines), links, and list markers.
|
|
109
|
-
*/
|
|
110
|
-
declare const markdown: Grammar;
|
|
111
|
-
/** Bash: comments, strings, keywords, variables (`$VAR` / `${...}`), operators. */
|
|
112
|
-
declare const bash: Grammar;
|
|
113
|
-
interface CodeEditorProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'defaultValue' | 'onChange' | 'wrap'> {
|
|
114
|
-
/** Controlled value. */
|
|
115
|
-
value?: string;
|
|
116
|
-
/** Initial value for uncontrolled use. */
|
|
117
|
-
defaultValue?: string;
|
|
118
|
-
/** Called with the new text on every edit. */
|
|
119
|
-
onValueChange?: (value: string) => void;
|
|
120
|
-
/** Grammar name (defaults to `plaintext`; unknown names fall back to it). */
|
|
121
|
-
language?: string;
|
|
122
|
-
/** Show the line-number gutter (default true). */
|
|
123
|
-
lineNumbers?: boolean;
|
|
124
|
-
/** Spaces per tab stop (default 2). */
|
|
125
|
-
tabSize?: number;
|
|
126
|
-
/** Insert spaces (default) vs a literal tab on Tab. */
|
|
127
|
-
insertSpaces?: boolean;
|
|
128
|
-
/** Soft-wrap long lines instead of scrolling horizontally (default false). */
|
|
129
|
-
wrap?: boolean;
|
|
130
|
-
/**
|
|
131
|
-
* Render only the visible lines for large documents. Defaults to auto
|
|
132
|
-
* (on above ~1000 lines); disabled when `wrap` makes row heights variable.
|
|
133
|
-
*/
|
|
134
|
-
virtualize?: boolean;
|
|
135
|
-
/** Accessible label for the editor (defaults to the i18n "Code editor"). */
|
|
136
|
-
label?: string;
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* A lightweight code editor: a native `<textarea>` overlaid on a syntax-highlighted
|
|
140
|
-
* `Highlight` layer. The browser owns editing/caret/IME/undo/a11y; JS handles only
|
|
141
|
-
* tokenizing, scroll-sync, and Tab/Shift-Tab indent. Signal-driven, no banned hooks.
|
|
142
|
-
*
|
|
143
|
-
* Performance: tokenization is per-line memoized, the highlight layer is
|
|
144
|
-
* rAF-debounced (typing never blocks), and large documents window to the visible
|
|
145
|
-
* range while the textarea always holds the full text.
|
|
146
|
-
*/
|
|
147
|
-
declare function CodeEditor({
|
|
148
|
-
value,
|
|
149
|
-
defaultValue,
|
|
150
|
-
onValueChange,
|
|
151
|
-
language,
|
|
152
|
-
lineNumbers,
|
|
153
|
-
tabSize,
|
|
154
|
-
insertSpaces,
|
|
155
|
-
wrap,
|
|
156
|
-
virtualize,
|
|
157
|
-
readOnly,
|
|
158
|
-
disabled,
|
|
159
|
-
spellCheck,
|
|
160
|
-
label,
|
|
161
|
-
className,
|
|
162
|
-
style,
|
|
163
|
-
onKeyDown,
|
|
164
|
-
...rest
|
|
165
|
-
}: CodeEditorProps): import("react").JSX.Element;
|
|
166
|
-
interface HighlightProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
167
|
-
/** Code to render. */
|
|
168
|
-
value: string;
|
|
169
|
-
/** Grammar name (defaults to `plaintext`; unknown names fall back to it). */
|
|
170
|
-
language?: string;
|
|
171
|
-
/** Show the line-number gutter. */
|
|
172
|
-
lineNumbers?: boolean;
|
|
173
|
-
/** Soft-wrap long lines instead of scrolling horizontally. */
|
|
174
|
-
wrap?: boolean;
|
|
175
|
-
/** Spaces per tab stop (default 2). */
|
|
176
|
-
tabSize?: number;
|
|
177
|
-
/** Accessible label for the read-only code block. */
|
|
178
|
-
label?: string;
|
|
179
|
-
/** Ref to the scrollable `<pre>` (used by `CodeEditor` for scroll-sync). */
|
|
180
|
-
preRef?: Ref<HTMLPreElement>;
|
|
181
|
-
/** Ref to the gutter column (used by `CodeEditor` for scroll-sync). */
|
|
182
|
-
gutterRef?: Ref<HTMLDivElement>;
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Read-only, syntax-highlighted `<pre><code>` rendered from the owned tokenizer.
|
|
186
|
-
* The same render layer `CodeEditor` overlays its `<textarea>` on. Signal-safe,
|
|
187
|
-
* themeable, and accessible — no banned hooks.
|
|
188
|
-
*/
|
|
189
|
-
declare function Highlight({
|
|
190
|
-
value,
|
|
191
|
-
language,
|
|
192
|
-
lineNumbers,
|
|
193
|
-
wrap,
|
|
194
|
-
tabSize,
|
|
195
|
-
label,
|
|
196
|
-
className,
|
|
197
|
-
preRef,
|
|
198
|
-
gutterRef,
|
|
199
|
-
style,
|
|
200
|
-
...rest
|
|
201
|
-
}: HighlightProps): import("react").JSX.Element;
|
|
202
|
-
export { CodeEditor, type CodeEditorProps, type Grammar, type GrammarState, Highlight, type HighlightProps, type LineTokens, type Rule, type RuleSpec, type Token, type TokenKind, type TokenizeResult, bash, createRuleGrammar, css, getGrammar, html, javascript, json, listGrammars, markdown, plaintext, registerGrammar, tokenize, tokenizeDocument, typescript };
|
package/dist/index.js
DELETED
|
@@ -1,701 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { cn as e, useControllableSignal as t, useSignal as n, useSignalEffect as r, useSignals as i } from "@cascivo/core";
|
|
3
|
-
import { builtin as a, t as o } from "@cascivo/i18n";
|
|
4
|
-
import { useRef as s } from "react";
|
|
5
|
-
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
|
-
//#region src/engine/tokenize.ts
|
|
7
|
-
var u = 5e3, d = /* @__PURE__ */ new Map(), f = "\0";
|
|
8
|
-
function p(e, t, n) {
|
|
9
|
-
let r = `${e.name}${f}${n}${f}${t}`, i = d.get(r);
|
|
10
|
-
if (i) return d.delete(r), d.set(r, i), i;
|
|
11
|
-
let { tokens: a, state: o } = e.tokenizeLine(t, n), s = {
|
|
12
|
-
tokens: a,
|
|
13
|
-
endState: o
|
|
14
|
-
};
|
|
15
|
-
if (d.set(r, s), d.size > u) {
|
|
16
|
-
let e = d.keys().next().value;
|
|
17
|
-
e !== void 0 && d.delete(e);
|
|
18
|
-
}
|
|
19
|
-
return s;
|
|
20
|
-
}
|
|
21
|
-
function m(e, t) {
|
|
22
|
-
let n = t.split("\n"), r = [], i = e.initialState;
|
|
23
|
-
for (let t of n) {
|
|
24
|
-
let n = p(e, t, i);
|
|
25
|
-
r.push(n.tokens), i = n.endState;
|
|
26
|
-
}
|
|
27
|
-
return r;
|
|
28
|
-
}
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/engine/registry.ts
|
|
31
|
-
var h = /* @__PURE__ */ new Map(), g = {
|
|
32
|
-
name: "plaintext",
|
|
33
|
-
initialState: "default",
|
|
34
|
-
tokenizeLine: (e) => ({
|
|
35
|
-
tokens: e.length > 0 ? [{
|
|
36
|
-
kind: "plain",
|
|
37
|
-
value: e
|
|
38
|
-
}] : [],
|
|
39
|
-
state: "default"
|
|
40
|
-
})
|
|
41
|
-
};
|
|
42
|
-
h.set(g.name, g);
|
|
43
|
-
function _(e) {
|
|
44
|
-
h.set(e.name, e);
|
|
45
|
-
}
|
|
46
|
-
function v(e) {
|
|
47
|
-
if (e !== void 0) {
|
|
48
|
-
let t = h.get(e);
|
|
49
|
-
if (t) return t;
|
|
50
|
-
}
|
|
51
|
-
return h.get("plaintext");
|
|
52
|
-
}
|
|
53
|
-
function y() {
|
|
54
|
-
return [...h.keys()];
|
|
55
|
-
}
|
|
56
|
-
//#endregion
|
|
57
|
-
//#region src/grammars/rules.ts
|
|
58
|
-
function b(e) {
|
|
59
|
-
let t = {};
|
|
60
|
-
for (let [n, r] of Object.entries(e.states)) t[n] = r.map((e) => {
|
|
61
|
-
let t = `${e.match.flags.replace(/[gy]/g, "")}y`, n = {
|
|
62
|
-
re: new RegExp(e.match.source, t),
|
|
63
|
-
kind: e.kind
|
|
64
|
-
};
|
|
65
|
-
return e.push !== void 0 && (n.push = e.push), e.pop !== void 0 && (n.pop = e.pop), n;
|
|
66
|
-
});
|
|
67
|
-
return {
|
|
68
|
-
name: e.name,
|
|
69
|
-
initialState: "default",
|
|
70
|
-
tokenizeLine(e, n) {
|
|
71
|
-
let r = t[n] ? n : "default", i = [], a = -1, o = 0, s = (t) => {
|
|
72
|
-
a >= 0 && (i.push({
|
|
73
|
-
kind: "plain",
|
|
74
|
-
value: e.slice(a, t)
|
|
75
|
-
}), a = -1);
|
|
76
|
-
};
|
|
77
|
-
for (; o < e.length;) {
|
|
78
|
-
let n = t[r], c = !1;
|
|
79
|
-
for (let a of n) {
|
|
80
|
-
a.re.lastIndex = o;
|
|
81
|
-
let n = a.re.exec(e);
|
|
82
|
-
if (n !== null && n.index === o && n[0].length > 0) {
|
|
83
|
-
s(o), i.push({
|
|
84
|
-
kind: a.kind,
|
|
85
|
-
value: n[0]
|
|
86
|
-
}), o += n[0].length, a.pop ? r = "default" : a.push && t[a.push] && (r = a.push), c = !0;
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
c || (a < 0 && (a = o), o++);
|
|
91
|
-
}
|
|
92
|
-
return s(e.length), {
|
|
93
|
-
tokens: i,
|
|
94
|
-
state: r
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
//#endregion
|
|
100
|
-
//#region src/grammars/plaintext.ts
|
|
101
|
-
var x = {
|
|
102
|
-
name: "plaintext",
|
|
103
|
-
initialState: "default",
|
|
104
|
-
tokenizeLine: (e) => ({
|
|
105
|
-
tokens: e.length > 0 ? [{
|
|
106
|
-
kind: "plain",
|
|
107
|
-
value: e
|
|
108
|
-
}] : [],
|
|
109
|
-
state: "default"
|
|
110
|
-
})
|
|
111
|
-
};
|
|
112
|
-
_(x);
|
|
113
|
-
//#endregion
|
|
114
|
-
//#region src/grammars/json.ts
|
|
115
|
-
var S = b({
|
|
116
|
-
name: "json",
|
|
117
|
-
states: { default: [
|
|
118
|
-
{
|
|
119
|
-
match: /"(?:[^"\\]|\\.)*"(?=\s*:)/,
|
|
120
|
-
kind: "property"
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
match: /"(?:[^"\\]|\\.)*"/,
|
|
124
|
-
kind: "string"
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
match: /\b(?:true|false|null)\b/,
|
|
128
|
-
kind: "boolean"
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
match: /-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/,
|
|
132
|
-
kind: "number"
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
match: /[{}[\],]/,
|
|
136
|
-
kind: "punctuation"
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
match: /:/,
|
|
140
|
-
kind: "operator"
|
|
141
|
-
}
|
|
142
|
-
] }
|
|
143
|
-
});
|
|
144
|
-
_(S);
|
|
145
|
-
//#endregion
|
|
146
|
-
//#region src/grammars/clike.ts
|
|
147
|
-
var C = /* @__PURE__ */ "async.await.break.case.catch.class.const.continue.debugger.default.delete.do.else.export.extends.finally.for.function.if.import.in.instanceof.let.new.of.return.static.super.switch.this.throw.try.typeof.var.void.while.with.yield.as.from.get.set".split(".");
|
|
148
|
-
function w(e) {
|
|
149
|
-
return RegExp(`(?:${e.join("|")})\\b`);
|
|
150
|
-
}
|
|
151
|
-
function T(e, t, n = []) {
|
|
152
|
-
let r = [
|
|
153
|
-
{
|
|
154
|
-
match: /\/\/.*/,
|
|
155
|
-
kind: "comment"
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
match: /\/\*/,
|
|
159
|
-
kind: "comment",
|
|
160
|
-
push: "block"
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
match: /`/,
|
|
164
|
-
kind: "string",
|
|
165
|
-
push: "template"
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
match: /'(?:[^'\\]|\\.)*'/,
|
|
169
|
-
kind: "string"
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
match: /"(?:[^"\\]|\\.)*"/,
|
|
173
|
-
kind: "string"
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
match: /0[xX][0-9a-fA-F]+|0[bB][01]+|0[oO][0-7]+|(?:\d[\d_]*\.?\d*|\.\d+)(?:[eE][+-]?\d+)?n?/,
|
|
177
|
-
kind: "number"
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
match: /\b(?:true|false|null|undefined|NaN|Infinity)\b/,
|
|
181
|
-
kind: "boolean"
|
|
182
|
-
}
|
|
183
|
-
];
|
|
184
|
-
return n.length > 0 && r.push({
|
|
185
|
-
match: w(n),
|
|
186
|
-
kind: "type"
|
|
187
|
-
}), r.push({
|
|
188
|
-
match: w(t),
|
|
189
|
-
kind: "keyword"
|
|
190
|
-
}, {
|
|
191
|
-
match: /[A-Za-z_$][\w$]*(?=\s*\()/,
|
|
192
|
-
kind: "function"
|
|
193
|
-
}, {
|
|
194
|
-
match: /[A-Z][\w$]*/,
|
|
195
|
-
kind: "type"
|
|
196
|
-
}, {
|
|
197
|
-
match: /[A-Za-z_$][\w$]*/,
|
|
198
|
-
kind: "variable"
|
|
199
|
-
}, {
|
|
200
|
-
match: /[+\-*/%=<>!&|^~?]+/,
|
|
201
|
-
kind: "operator"
|
|
202
|
-
}, {
|
|
203
|
-
match: /[{}()[\];,.:]/,
|
|
204
|
-
kind: "punctuation"
|
|
205
|
-
}), b({
|
|
206
|
-
name: e,
|
|
207
|
-
states: {
|
|
208
|
-
default: r,
|
|
209
|
-
block: [
|
|
210
|
-
{
|
|
211
|
-
match: /\*\//,
|
|
212
|
-
kind: "comment",
|
|
213
|
-
pop: !0
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
match: /[^*]+/,
|
|
217
|
-
kind: "comment"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
match: /\*/,
|
|
221
|
-
kind: "comment"
|
|
222
|
-
}
|
|
223
|
-
],
|
|
224
|
-
template: [
|
|
225
|
-
{
|
|
226
|
-
match: /\\./,
|
|
227
|
-
kind: "string"
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
match: /`/,
|
|
231
|
-
kind: "string",
|
|
232
|
-
pop: !0
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
match: /\$\{/,
|
|
236
|
-
kind: "punctuation"
|
|
237
|
-
},
|
|
238
|
-
{
|
|
239
|
-
match: /[^`\\$]+/,
|
|
240
|
-
kind: "string"
|
|
241
|
-
},
|
|
242
|
-
{
|
|
243
|
-
match: /\$/,
|
|
244
|
-
kind: "string"
|
|
245
|
-
}
|
|
246
|
-
]
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
//#endregion
|
|
251
|
-
//#region src/grammars/javascript.ts
|
|
252
|
-
var E = T("javascript", C);
|
|
253
|
-
_(E);
|
|
254
|
-
var D = T("typescript", C, [
|
|
255
|
-
"interface",
|
|
256
|
-
"type",
|
|
257
|
-
"enum",
|
|
258
|
-
"implements",
|
|
259
|
-
"namespace",
|
|
260
|
-
"declare",
|
|
261
|
-
"abstract",
|
|
262
|
-
"readonly",
|
|
263
|
-
"public",
|
|
264
|
-
"private",
|
|
265
|
-
"protected",
|
|
266
|
-
"keyof",
|
|
267
|
-
"infer",
|
|
268
|
-
"satisfies",
|
|
269
|
-
"is",
|
|
270
|
-
"asserts",
|
|
271
|
-
"override",
|
|
272
|
-
"string",
|
|
273
|
-
"number",
|
|
274
|
-
"boolean",
|
|
275
|
-
"any",
|
|
276
|
-
"unknown",
|
|
277
|
-
"never",
|
|
278
|
-
"object"
|
|
279
|
-
]);
|
|
280
|
-
_(D);
|
|
281
|
-
//#endregion
|
|
282
|
-
//#region src/grammars/css.ts
|
|
283
|
-
var O = b({
|
|
284
|
-
name: "css",
|
|
285
|
-
states: {
|
|
286
|
-
default: [
|
|
287
|
-
{
|
|
288
|
-
match: /\/\*/,
|
|
289
|
-
kind: "comment",
|
|
290
|
-
push: "block"
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
match: /@[\w-]+/,
|
|
294
|
-
kind: "keyword"
|
|
295
|
-
},
|
|
296
|
-
{
|
|
297
|
-
match: /"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/,
|
|
298
|
-
kind: "string"
|
|
299
|
-
},
|
|
300
|
-
{
|
|
301
|
-
match: /#[0-9a-fA-F]{3,8}\b/,
|
|
302
|
-
kind: "number"
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
match: /-?\d+(?:\.\d+)?(?:px|rem|em|%|vh|vw|s|ms|deg|fr|ch|ex)?/,
|
|
306
|
-
kind: "number"
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
match: /--[\w-]+/,
|
|
310
|
-
kind: "variable"
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
match: /[.#][\w-]+/,
|
|
314
|
-
kind: "tag"
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
match: /&|::?[\w-]+/,
|
|
318
|
-
kind: "tag"
|
|
319
|
-
},
|
|
320
|
-
{
|
|
321
|
-
match: /[\w-]+(?=\s*:)/,
|
|
322
|
-
kind: "property"
|
|
323
|
-
},
|
|
324
|
-
{
|
|
325
|
-
match: /[\w-]+(?=\s*\()/,
|
|
326
|
-
kind: "function"
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
match: /[{}();,:]/,
|
|
330
|
-
kind: "punctuation"
|
|
331
|
-
}
|
|
332
|
-
],
|
|
333
|
-
block: [
|
|
334
|
-
{
|
|
335
|
-
match: /\*\//,
|
|
336
|
-
kind: "comment",
|
|
337
|
-
pop: !0
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
match: /[^*]+/,
|
|
341
|
-
kind: "comment"
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
match: /\*/,
|
|
345
|
-
kind: "comment"
|
|
346
|
-
}
|
|
347
|
-
]
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
_(O);
|
|
351
|
-
//#endregion
|
|
352
|
-
//#region src/grammars/html.ts
|
|
353
|
-
var k = b({
|
|
354
|
-
name: "html",
|
|
355
|
-
states: {
|
|
356
|
-
default: [
|
|
357
|
-
{
|
|
358
|
-
match: /<!--/,
|
|
359
|
-
kind: "comment",
|
|
360
|
-
push: "comment"
|
|
361
|
-
},
|
|
362
|
-
{
|
|
363
|
-
match: /<!?\/?[A-Za-z][\w-]*/,
|
|
364
|
-
kind: "tag",
|
|
365
|
-
push: "tag"
|
|
366
|
-
},
|
|
367
|
-
{
|
|
368
|
-
match: /&[a-zA-Z#0-9]+;/,
|
|
369
|
-
kind: "boolean"
|
|
370
|
-
}
|
|
371
|
-
],
|
|
372
|
-
comment: [
|
|
373
|
-
{
|
|
374
|
-
match: /-->/,
|
|
375
|
-
kind: "comment",
|
|
376
|
-
pop: !0
|
|
377
|
-
},
|
|
378
|
-
{
|
|
379
|
-
match: /[^-]+/,
|
|
380
|
-
kind: "comment"
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
match: /-/,
|
|
384
|
-
kind: "comment"
|
|
385
|
-
}
|
|
386
|
-
],
|
|
387
|
-
tag: [
|
|
388
|
-
{
|
|
389
|
-
match: /\/?>/,
|
|
390
|
-
kind: "tag",
|
|
391
|
-
pop: !0
|
|
392
|
-
},
|
|
393
|
-
{
|
|
394
|
-
match: /"(?:[^"\\]|\\.)*"|'[^']*'/,
|
|
395
|
-
kind: "string"
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
match: /[\w-]+(?=\s*=)/,
|
|
399
|
-
kind: "attr"
|
|
400
|
-
},
|
|
401
|
-
{
|
|
402
|
-
match: /=/,
|
|
403
|
-
kind: "operator"
|
|
404
|
-
},
|
|
405
|
-
{
|
|
406
|
-
match: /[\w-]+/,
|
|
407
|
-
kind: "attr"
|
|
408
|
-
}
|
|
409
|
-
]
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
_(k);
|
|
413
|
-
//#endregion
|
|
414
|
-
//#region src/grammars/markdown.ts
|
|
415
|
-
var A = b({
|
|
416
|
-
name: "markdown",
|
|
417
|
-
states: {
|
|
418
|
-
default: [
|
|
419
|
-
{
|
|
420
|
-
match: /^```.*/,
|
|
421
|
-
kind: "keyword",
|
|
422
|
-
push: "fence"
|
|
423
|
-
},
|
|
424
|
-
{
|
|
425
|
-
match: /^#{1,6}\s.*/,
|
|
426
|
-
kind: "keyword"
|
|
427
|
-
},
|
|
428
|
-
{
|
|
429
|
-
match: /^\s*(?:[-*+]|\d+\.)\s/,
|
|
430
|
-
kind: "operator"
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
match: /^\s*>\s.*/,
|
|
434
|
-
kind: "comment"
|
|
435
|
-
},
|
|
436
|
-
{
|
|
437
|
-
match: /`[^`]+`/,
|
|
438
|
-
kind: "string"
|
|
439
|
-
},
|
|
440
|
-
{
|
|
441
|
-
match: /\*\*[^*]+\*\*|__[^_]+__/,
|
|
442
|
-
kind: "keyword"
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
match: /\*[^*\s][^*]*\*|_[^_\s][^_]*_/,
|
|
446
|
-
kind: "type"
|
|
447
|
-
},
|
|
448
|
-
{
|
|
449
|
-
match: /!?\[[^\]]*\]\([^)]*\)/,
|
|
450
|
-
kind: "function"
|
|
451
|
-
}
|
|
452
|
-
],
|
|
453
|
-
fence: [{
|
|
454
|
-
match: /^```.*/,
|
|
455
|
-
kind: "keyword",
|
|
456
|
-
pop: !0
|
|
457
|
-
}, {
|
|
458
|
-
match: /.+/,
|
|
459
|
-
kind: "string"
|
|
460
|
-
}]
|
|
461
|
-
}
|
|
462
|
-
});
|
|
463
|
-
_(A);
|
|
464
|
-
//#endregion
|
|
465
|
-
//#region src/grammars/bash.ts
|
|
466
|
-
var j = b({
|
|
467
|
-
name: "bash",
|
|
468
|
-
states: { default: [
|
|
469
|
-
{
|
|
470
|
-
match: /#.*/,
|
|
471
|
-
kind: "comment"
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
match: /"(?:[^"\\]|\\.)*"/,
|
|
475
|
-
kind: "string"
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
match: /'[^']*'/,
|
|
479
|
-
kind: "string"
|
|
480
|
-
},
|
|
481
|
-
{
|
|
482
|
-
match: /\b(?:if|then|else|elif|fi|for|while|until|do|done|case|esac|in|function|select|return|exit|break|continue|local|export|readonly|declare|echo|cd|source|set|unset)\b/,
|
|
483
|
-
kind: "keyword"
|
|
484
|
-
},
|
|
485
|
-
{
|
|
486
|
-
match: /\$\{[^}]*\}|\$[A-Za-z_]\w*|\$[0-9@*#?$!]/,
|
|
487
|
-
kind: "variable"
|
|
488
|
-
},
|
|
489
|
-
{
|
|
490
|
-
match: /-?\b\d+\b/,
|
|
491
|
-
kind: "number"
|
|
492
|
-
},
|
|
493
|
-
{
|
|
494
|
-
match: /[A-Za-z_][\w-]*(?=\s*\(\s*\))/,
|
|
495
|
-
kind: "function"
|
|
496
|
-
},
|
|
497
|
-
{
|
|
498
|
-
match: /[|&;<>()]+|&&|\|\||=/,
|
|
499
|
-
kind: "operator"
|
|
500
|
-
}
|
|
501
|
-
] }
|
|
502
|
-
});
|
|
503
|
-
_(j);
|
|
504
|
-
var M = {
|
|
505
|
-
root: "_root_4k2k5_2",
|
|
506
|
-
gutter: "_gutter_4k2k5_17",
|
|
507
|
-
gutterLine: "_gutterLine_4k2k5_28",
|
|
508
|
-
pre: "_pre_4k2k5_33",
|
|
509
|
-
code: "_code_4k2k5_45",
|
|
510
|
-
line: "_line_4k2k5_50",
|
|
511
|
-
plain: "_plain_4k2k5_65",
|
|
512
|
-
keyword: "_keyword_4k2k5_68",
|
|
513
|
-
string: "_string_4k2k5_71",
|
|
514
|
-
number: "_number_4k2k5_74",
|
|
515
|
-
comment: "_comment_4k2k5_77",
|
|
516
|
-
function: "_function_4k2k5_81",
|
|
517
|
-
type: "_type_4k2k5_84",
|
|
518
|
-
operator: "_operator_4k2k5_87",
|
|
519
|
-
punctuation: "_punctuation_4k2k5_90",
|
|
520
|
-
variable: "_variable_4k2k5_93",
|
|
521
|
-
tag: "_tag_4k2k5_96",
|
|
522
|
-
attr: "_attr_4k2k5_99",
|
|
523
|
-
regexp: "_regexp_4k2k5_102",
|
|
524
|
-
boolean: "_boolean_4k2k5_105",
|
|
525
|
-
property: "_property_4k2k5_108"
|
|
526
|
-
};
|
|
527
|
-
//#endregion
|
|
528
|
-
//#region src/editor/view.tsx
|
|
529
|
-
function N(e, t = 0, n = e.length) {
|
|
530
|
-
let r = [];
|
|
531
|
-
for (let i = t; i < n; i++) {
|
|
532
|
-
let t = e[i];
|
|
533
|
-
r.push(/* @__PURE__ */ c("span", {
|
|
534
|
-
className: M.line,
|
|
535
|
-
children: t.length === 0 ? "" : t.map((e, t) => /* @__PURE__ */ c("span", {
|
|
536
|
-
className: M[e.kind],
|
|
537
|
-
children: e.value
|
|
538
|
-
}, t))
|
|
539
|
-
}, i));
|
|
540
|
-
}
|
|
541
|
-
return r;
|
|
542
|
-
}
|
|
543
|
-
function P({ count: e, className: t, gutterRef: n, start: r = 0, end: i = e, topPad: a = 0, bottomPad: o = 0 }) {
|
|
544
|
-
let s = [];
|
|
545
|
-
for (let e = r + 1; e <= i; e++) s.push(/* @__PURE__ */ c("span", {
|
|
546
|
-
className: M.gutterLine,
|
|
547
|
-
children: e
|
|
548
|
-
}, e));
|
|
549
|
-
return /* @__PURE__ */ l("div", {
|
|
550
|
-
ref: n,
|
|
551
|
-
className: t,
|
|
552
|
-
"aria-hidden": "true",
|
|
553
|
-
children: [
|
|
554
|
-
a > 0 && /* @__PURE__ */ c("div", { style: { blockSize: a } }),
|
|
555
|
-
s,
|
|
556
|
-
o > 0 && /* @__PURE__ */ c("div", { style: { blockSize: o } })
|
|
557
|
-
]
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
var F = {
|
|
561
|
-
root: "_root_q71hw_2",
|
|
562
|
-
textarea: "_textarea_q71hw_18",
|
|
563
|
-
gutter: "_gutter_q71hw_23",
|
|
564
|
-
codeArea: "_codeArea_q71hw_35",
|
|
565
|
-
pre: "_pre_q71hw_42",
|
|
566
|
-
currentLine: "_currentLine_q71hw_57"
|
|
567
|
-
}, I = 1e3, L = 12;
|
|
568
|
-
function R({ value: u, defaultValue: d, onValueChange: f, language: p = "plaintext", lineNumbers: h = !0, tabSize: g = 2, insertSpaces: _ = !0, wrap: y = !1, virtualize: b, readOnly: x = !1, disabled: S = !1, spellCheck: C = !1, label: w, className: T, style: E, onKeyDown: D, ...O }) {
|
|
569
|
-
i();
|
|
570
|
-
let [k, A] = t({
|
|
571
|
-
value: u,
|
|
572
|
-
defaultValue: d ?? "",
|
|
573
|
-
onChange: f
|
|
574
|
-
}), j = s(null), M = s(null), R = s(null), z = s(null), B = n(k.value), V = n(0), H = n(0), U = n(0);
|
|
575
|
-
r(() => {
|
|
576
|
-
let e = k.value;
|
|
577
|
-
if (typeof requestAnimationFrame != "function") {
|
|
578
|
-
B.value = e;
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
let t = requestAnimationFrame(() => {
|
|
582
|
-
B.value = e;
|
|
583
|
-
});
|
|
584
|
-
return () => cancelAnimationFrame(t);
|
|
585
|
-
}), r(() => {
|
|
586
|
-
let e = z.current;
|
|
587
|
-
if (!e) return;
|
|
588
|
-
let t = () => {
|
|
589
|
-
let t = Number.parseFloat(getComputedStyle(e).lineHeight);
|
|
590
|
-
U.value = Number.isFinite(t) && t > 0 ? t : 0, H.value = e.clientHeight;
|
|
591
|
-
}, n = () => {
|
|
592
|
-
V.value = e.scrollTop, H.value = e.clientHeight, M.current && (M.current.scrollTop = e.scrollTop, M.current.scrollLeft = e.scrollLeft), R.current && (R.current.scrollTop = e.scrollTop);
|
|
593
|
-
}, r = () => {
|
|
594
|
-
let t = e.value.slice(0, e.selectionStart).split("\n").length - 1;
|
|
595
|
-
j.current?.style.setProperty("--cascivo-editor-caret-line", String(t));
|
|
596
|
-
};
|
|
597
|
-
return t(), r(), e.addEventListener("scroll", n), e.addEventListener("keyup", r), e.addEventListener("click", r), e.addEventListener("input", r), () => {
|
|
598
|
-
e.removeEventListener("scroll", n), e.removeEventListener("keyup", r), e.removeEventListener("click", r), e.removeEventListener("input", r);
|
|
599
|
-
};
|
|
600
|
-
});
|
|
601
|
-
let W = m(v(p), B.value), G = W.length, K = U.value, q = (b ?? G > I) && !y && K > 0, J = 0, Y = G;
|
|
602
|
-
if (q) {
|
|
603
|
-
J = Math.max(0, Math.floor(V.value / K) - L);
|
|
604
|
-
let e = Math.ceil(H.value / K);
|
|
605
|
-
Y = Math.min(G, J + e + L * 2);
|
|
606
|
-
}
|
|
607
|
-
let X = J * K, Z = (G - Y) * K, Q = (e) => {
|
|
608
|
-
if (e.key === "Tab" && !x && !S) {
|
|
609
|
-
e.preventDefault();
|
|
610
|
-
let t = e.currentTarget, { selectionStart: n, selectionEnd: r, value: i } = t, a = _ ? " ".repeat(g) : " ", o = i.lastIndexOf("\n", n - 1) + 1;
|
|
611
|
-
if (e.shiftKey) {
|
|
612
|
-
let e = i.slice(o, r).replace(RegExp(`^(?:\\t| {1,${g}})`, "gm"), "");
|
|
613
|
-
t.setRangeText(e, o, r, "select");
|
|
614
|
-
} else if (n === r) t.setRangeText(a, n, r, "end");
|
|
615
|
-
else {
|
|
616
|
-
let e = i.slice(o, r).replace(/^/gm, a);
|
|
617
|
-
t.setRangeText(e, o, r, "select");
|
|
618
|
-
}
|
|
619
|
-
A(t.value);
|
|
620
|
-
}
|
|
621
|
-
D?.(e);
|
|
622
|
-
}, $ = {
|
|
623
|
-
"--cascivo-editor-tab-size": g,
|
|
624
|
-
...E
|
|
625
|
-
};
|
|
626
|
-
return /* @__PURE__ */ l("div", {
|
|
627
|
-
ref: j,
|
|
628
|
-
className: e(F.root, T),
|
|
629
|
-
"data-wrap": y,
|
|
630
|
-
"data-line-numbers": h,
|
|
631
|
-
style: $,
|
|
632
|
-
children: [h && /* @__PURE__ */ c(P, {
|
|
633
|
-
count: G,
|
|
634
|
-
className: F.gutter,
|
|
635
|
-
gutterRef: R,
|
|
636
|
-
start: J,
|
|
637
|
-
end: Y,
|
|
638
|
-
topPad: X,
|
|
639
|
-
bottomPad: Z
|
|
640
|
-
}), /* @__PURE__ */ l("div", {
|
|
641
|
-
className: F.codeArea,
|
|
642
|
-
children: [/* @__PURE__ */ l("pre", {
|
|
643
|
-
ref: M,
|
|
644
|
-
className: F.pre,
|
|
645
|
-
"aria-hidden": "true",
|
|
646
|
-
children: [
|
|
647
|
-
/* @__PURE__ */ c("div", { className: F.currentLine }),
|
|
648
|
-
X > 0 && /* @__PURE__ */ c("div", { style: { blockSize: X } }),
|
|
649
|
-
/* @__PURE__ */ c("code", { children: N(W, J, Y) }),
|
|
650
|
-
Z > 0 && /* @__PURE__ */ c("div", { style: { blockSize: Z } })
|
|
651
|
-
]
|
|
652
|
-
}), /* @__PURE__ */ c("textarea", {
|
|
653
|
-
ref: z,
|
|
654
|
-
className: F.textarea,
|
|
655
|
-
value: k.value,
|
|
656
|
-
onChange: (e) => A(e.currentTarget.value),
|
|
657
|
-
onKeyDown: Q,
|
|
658
|
-
readOnly: x,
|
|
659
|
-
disabled: S,
|
|
660
|
-
spellCheck: C,
|
|
661
|
-
"aria-label": w ?? o(a.editor.label),
|
|
662
|
-
autoCapitalize: "off",
|
|
663
|
-
autoCorrect: "off",
|
|
664
|
-
autoComplete: "off",
|
|
665
|
-
wrap: y ? "soft" : "off",
|
|
666
|
-
...O
|
|
667
|
-
})]
|
|
668
|
-
})]
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
|
-
//#endregion
|
|
672
|
-
//#region src/editor/highlight/highlight.tsx
|
|
673
|
-
function z({ value: t, language: n = "plaintext", lineNumbers: r = !1, wrap: a = !1, tabSize: o = 2, label: s, className: u, preRef: d, gutterRef: f, style: p, ...h }) {
|
|
674
|
-
i();
|
|
675
|
-
let g = m(v(n), t), _ = {
|
|
676
|
-
"--cascivo-editor-tab-size": o,
|
|
677
|
-
...p
|
|
678
|
-
};
|
|
679
|
-
return /* @__PURE__ */ l("div", {
|
|
680
|
-
className: e(M.root, u),
|
|
681
|
-
"data-wrap": a,
|
|
682
|
-
"data-line-numbers": r,
|
|
683
|
-
style: _,
|
|
684
|
-
"aria-label": s,
|
|
685
|
-
...h,
|
|
686
|
-
children: [r && /* @__PURE__ */ c(P, {
|
|
687
|
-
count: g.length,
|
|
688
|
-
className: M.gutter,
|
|
689
|
-
gutterRef: f
|
|
690
|
-
}), /* @__PURE__ */ c("pre", {
|
|
691
|
-
ref: d,
|
|
692
|
-
className: M.pre,
|
|
693
|
-
children: /* @__PURE__ */ c("code", {
|
|
694
|
-
className: M.code,
|
|
695
|
-
children: N(g)
|
|
696
|
-
})
|
|
697
|
-
})]
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
//#endregion
|
|
701
|
-
export { R as CodeEditor, z as Highlight, j as bash, b as createRuleGrammar, O as css, v as getGrammar, k as html, E as javascript, S as json, y as listGrammars, A as markdown, x as plaintext, _ as registerGrammar, p as tokenize, m as tokenizeDocument, D as typescript };
|