jssm 5.145.6 → 5.147.0
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/README.md +7 -7
- package/custom-elements.json +342 -3
- package/dist/cdn/instance.js +144 -9
- package/dist/cdn/viz.js +10 -2
- package/dist/cli/fsl-export-system-prompt.cjs +1 -1
- package/dist/cli/fsl-render.cjs +1 -1
- package/dist/cli/fsl.cjs +1 -1
- package/dist/cli/lib.cjs +1 -1
- package/dist/cli/lib.mjs +1 -1
- package/dist/cm6/fsl_language.js +199 -0
- package/dist/deno/README.md +7 -7
- package/dist/deno/jssm.js +1 -1
- package/dist/es6/cm6/fsl_language.d.ts +81 -0
- package/dist/jssm.es5.cjs +1 -1
- package/dist/jssm.es5.iife.js +1 -1
- package/dist/jssm.es6.mjs +1 -1
- package/dist/jssm_viz.cjs +1 -1
- package/dist/jssm_viz.iife.cjs +1 -1
- package/dist/jssm_viz.mjs +1 -1
- package/dist/wc/instance.define.js +9 -1
- package/dist/wc/instance.js +134 -7
- package/dist/wc/viz.define.js +9 -1
- package/package.json +27 -4
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { StreamLanguage, HighlightStyle, LanguageSupport } from '@codemirror/language';
|
|
2
|
+
import { Tag, tags } from '@lezer/highlight';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* CodeMirror 6 language support for FSL (the source language of jssm
|
|
6
|
+
* finite-state machines), exposed at the `jssm/cm6` subpath.
|
|
7
|
+
*
|
|
8
|
+
* Built on `StreamLanguage` (token-stream based, not a Lezer tree grammar) —
|
|
9
|
+
* a deliberate v1 choice (see `notes/superpowers/specs/2026-05-12-editor-widget-packaging-design.md`):
|
|
10
|
+
* the tokenizer never blocks on the parser, so a failing parse never kills
|
|
11
|
+
* highlighting. The companion linter (driven by `fsl_parser.parse()`) supplies
|
|
12
|
+
* error squiggles separately.
|
|
13
|
+
*
|
|
14
|
+
* The keyword vocabulary is reconciled against the live grammar
|
|
15
|
+
* (`src/ts/fsl_parser.peg`) and guarded by `fsl_language.spec.ts`, which
|
|
16
|
+
* extracts the grammar's config keys and fails if any is not recognized here —
|
|
17
|
+
* so the highlighter cannot silently drift out of date the way the original
|
|
18
|
+
* `sketch/cm6-lang-fsl` did.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Tag modifier marking FSL syntax that still parses but is deprecated (e.g.
|
|
22
|
+
* the flat `graph_bg_color` key, superseded by the `graph: {}` block). Applied
|
|
23
|
+
* to a base tag — `fslDeprecated(tags.propertyName)` — and rendered distinctly
|
|
24
|
+
* by {@link fslHighlightStyle} (struck through) so editors can flag stale
|
|
25
|
+
* syntax. StreamLanguage expresses this through its `tokenTable`; see
|
|
26
|
+
* {@link fslStreamParser}.
|
|
27
|
+
*/
|
|
28
|
+
const fslDeprecated = Tag.defineModifier('fslDeprecated');
|
|
29
|
+
/**
|
|
30
|
+
* Structural / declaration keywords — block openers and the `property`
|
|
31
|
+
* declaration keyword. Highlighted as `keyword`.
|
|
32
|
+
*/
|
|
33
|
+
const STRUCTURAL_KEYWORDS = new Set([
|
|
34
|
+
'state', 'start_state', 'end_state', 'active_state', 'terminal_state', 'hooked_state',
|
|
35
|
+
'action', 'transition', 'validation', 'configuration', 'graph', 'hooks',
|
|
36
|
+
'property', 'required', 'default',
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Configuration / property / style keys (the left side of a `key: value;`
|
|
40
|
+
* config line). Highlighted as `propertyName`. Reconciled against the
|
|
41
|
+
* `"<key>" WS? ":"` rules in `fsl_parser.peg` and guarded by the drift test.
|
|
42
|
+
*/
|
|
43
|
+
const PROPERTY_KEYWORDS = new Set([
|
|
44
|
+
// machine metadata
|
|
45
|
+
'machine_name', 'machine_version', 'machine_author', 'machine_license',
|
|
46
|
+
'machine_comment', 'machine_contributor', 'machine_definition',
|
|
47
|
+
'machine_language', 'machine_reference', 'npm_name', 'fsl_version',
|
|
48
|
+
// graph / layout
|
|
49
|
+
'graph_layout', 'start_states', 'end_states', 'failed_outputs',
|
|
50
|
+
'allows_override', 'allow_islands', 'edge_color', 'theme', 'flow',
|
|
51
|
+
'dot_preamble', 'default_size',
|
|
52
|
+
// per-element style keys
|
|
53
|
+
'label', 'color', 'shape', 'corners', 'linestyle', 'image', 'url',
|
|
54
|
+
]);
|
|
55
|
+
/**
|
|
56
|
+
* Keys that still parse but are deprecated. Highlighted with the
|
|
57
|
+
* {@link fslDeprecated} modifier so editors can visibly flag them.
|
|
58
|
+
*/
|
|
59
|
+
const DEPRECATED_KEYWORDS = new Set([
|
|
60
|
+
'graph_bg_color', // superseded by the `graph: {}` block
|
|
61
|
+
]);
|
|
62
|
+
/**
|
|
63
|
+
* Enumerated literal values (layout engines, corner/line styles, directions,
|
|
64
|
+
* booleans, theme names). Highlighted as `atom`.
|
|
65
|
+
*/
|
|
66
|
+
const ENUM_KEYWORDS = new Set([
|
|
67
|
+
'true', 'false', 'none', 'default', 'modern', 'ocean', 'bold',
|
|
68
|
+
'dot', 'circo', 'fdp', 'neato', 'twopi',
|
|
69
|
+
'up', 'right', 'down', 'left',
|
|
70
|
+
'solid', 'dotted', 'dashed',
|
|
71
|
+
'regular', 'rounded', 'lined',
|
|
72
|
+
'MIT',
|
|
73
|
+
]);
|
|
74
|
+
/** Custom token-type string emitted for deprecated keywords; mapped in `tokenTable`. */
|
|
75
|
+
const DEPRECATED_TOKEN = 'fslDeprecatedKeyword';
|
|
76
|
+
const ARROWS = /^(?:<-=>|<-~>|<=->|<=~>|<~->|<~=>|<->|<=>|<~>|->|<-|=>|<=|~>|<~|↔|←|→|⇔|⇐|⇒|↮|↚|↛)/;
|
|
77
|
+
const COMPARATORS = /^(?:>=|<=|>|<)/;
|
|
78
|
+
// Mirrors the grammar's AtomFirstLetter / AtomLetter rules (fsl_parser.peg:263-267).
|
|
79
|
+
// The high-unicode tail is the range U+0080..U+FFFF (escaped below). The
|
|
80
|
+
// original sketch anchored the range at the comma, wrongly swallowing { } ; : |.
|
|
81
|
+
const ATOM_START = /[0-9a-zA-Z._!$^*?,\u0080-\uFFFF]/;
|
|
82
|
+
const ATOM_BODY = /[0-9a-zA-Z.+_^()*&$#@!?,\u0080-\uFFFF]/;
|
|
83
|
+
/**
|
|
84
|
+
* The StreamLanguage tokenizer for FSL. Classifies each token into a standard
|
|
85
|
+
* CodeMirror highlight name, or {@link DEPRECATED_TOKEN} (mapped through
|
|
86
|
+
* `tokenTable` to `fslDeprecated(tags.propertyName)`).
|
|
87
|
+
*/
|
|
88
|
+
const fslStreamParser = {
|
|
89
|
+
name: 'fsl',
|
|
90
|
+
startState: () => ({ inBlockComment: false }),
|
|
91
|
+
token(stream, state) {
|
|
92
|
+
if (state.inBlockComment) {
|
|
93
|
+
while (!stream.eol()) {
|
|
94
|
+
if (stream.match('*/')) {
|
|
95
|
+
state.inBlockComment = false;
|
|
96
|
+
return 'comment';
|
|
97
|
+
}
|
|
98
|
+
stream.next();
|
|
99
|
+
}
|
|
100
|
+
return 'comment';
|
|
101
|
+
}
|
|
102
|
+
if (stream.eatSpace()) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
if (stream.match('//')) {
|
|
106
|
+
stream.skipToEnd();
|
|
107
|
+
return 'comment';
|
|
108
|
+
}
|
|
109
|
+
if (stream.match('/*')) {
|
|
110
|
+
state.inBlockComment = true;
|
|
111
|
+
return 'comment';
|
|
112
|
+
}
|
|
113
|
+
if (stream.match(/^"(?:\\.|[^"\\])*"?/)) {
|
|
114
|
+
return 'string';
|
|
115
|
+
}
|
|
116
|
+
if (stream.match(/^'(?:\\.|[^'\\])*'?/)) {
|
|
117
|
+
return 'labelName';
|
|
118
|
+
}
|
|
119
|
+
if (stream.match(ARROWS)) {
|
|
120
|
+
return 'operator';
|
|
121
|
+
}
|
|
122
|
+
if (stream.match(COMPARATORS)) {
|
|
123
|
+
return 'operator';
|
|
124
|
+
}
|
|
125
|
+
if (stream.match(/^\d+(?:\.\d+)*/)) {
|
|
126
|
+
return 'number';
|
|
127
|
+
}
|
|
128
|
+
if (stream.match(/^&[A-Za-z_]\w*/)) {
|
|
129
|
+
return 'variableName.special';
|
|
130
|
+
}
|
|
131
|
+
// Invariant: the loop guards `!eol` and `eatSpace()` returned false above,
|
|
132
|
+
// so a non-space character is present and `peek()` is defined here.
|
|
133
|
+
const ch = stream.peek();
|
|
134
|
+
if (ATOM_START.test(ch)) {
|
|
135
|
+
let tok = '';
|
|
136
|
+
let next = stream.peek();
|
|
137
|
+
while (next !== undefined && ATOM_BODY.test(next)) {
|
|
138
|
+
tok += stream.next();
|
|
139
|
+
next = stream.peek();
|
|
140
|
+
}
|
|
141
|
+
if (DEPRECATED_KEYWORDS.has(tok)) {
|
|
142
|
+
return DEPRECATED_TOKEN;
|
|
143
|
+
}
|
|
144
|
+
if (STRUCTURAL_KEYWORDS.has(tok)) {
|
|
145
|
+
return 'keyword';
|
|
146
|
+
}
|
|
147
|
+
if (PROPERTY_KEYWORDS.has(tok)) {
|
|
148
|
+
return 'propertyName';
|
|
149
|
+
}
|
|
150
|
+
if (ENUM_KEYWORDS.has(tok)) {
|
|
151
|
+
return 'atom';
|
|
152
|
+
}
|
|
153
|
+
return 'variableName';
|
|
154
|
+
}
|
|
155
|
+
if (stream.match(/^[\[\]{}()]/)) {
|
|
156
|
+
return 'bracket';
|
|
157
|
+
}
|
|
158
|
+
if (stream.match(/^[;:,|]/)) {
|
|
159
|
+
return 'punctuation';
|
|
160
|
+
}
|
|
161
|
+
stream.next();
|
|
162
|
+
return null;
|
|
163
|
+
},
|
|
164
|
+
tokenTable: {
|
|
165
|
+
[DEPRECATED_TOKEN]: fslDeprecated(tags.propertyName),
|
|
166
|
+
},
|
|
167
|
+
languageData: {
|
|
168
|
+
commentTokens: { line: '//', block: { open: '/*', close: '*/' } },
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* CodeMirror 6 `Language` for FSL. Most consumers use {@link fsl} instead.
|
|
173
|
+
*/
|
|
174
|
+
const fslLanguage = StreamLanguage.define(fslStreamParser);
|
|
175
|
+
/**
|
|
176
|
+
* Recommended highlight style. Beyond the editor theme's own keyword/string/etc.
|
|
177
|
+
* rules, this renders {@link fslDeprecated} tokens struck-through and dimmed, so
|
|
178
|
+
* deprecated FSL syntax is visible at a glance. Include it alongside your theme;
|
|
179
|
+
* a bare theme without it simply won't distinguish deprecated keywords.
|
|
180
|
+
*/
|
|
181
|
+
const fslHighlightStyle = HighlightStyle.define([
|
|
182
|
+
{ tag: fslDeprecated(tags.propertyName), textDecoration: 'line-through', opacity: '0.6' },
|
|
183
|
+
]);
|
|
184
|
+
/**
|
|
185
|
+
* CodeMirror 6 `LanguageSupport` for FSL. Drop into an editor's `extensions`.
|
|
186
|
+
*
|
|
187
|
+
* @returns A `LanguageSupport` extension for FSL highlighting.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* import { EditorView, basicSetup } from 'codemirror';
|
|
191
|
+
* import { fsl } from 'jssm/cm6';
|
|
192
|
+
* new EditorView({ doc: "a 'go' -> b;", parent: document.body,
|
|
193
|
+
* extensions: [ basicSetup, fsl() ] });
|
|
194
|
+
*/
|
|
195
|
+
function fsl() {
|
|
196
|
+
return new LanguageSupport(fslLanguage);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export { DEPRECATED_KEYWORDS, ENUM_KEYWORDS, PROPERTY_KEYWORDS, STRUCTURAL_KEYWORDS, fsl, fslDeprecated, fslHighlightStyle, fslLanguage, fslStreamParser };
|
package/dist/deno/README.md
CHANGED
|
@@ -18,10 +18,10 @@ Please edit the file it's derived from, instead: `./src/md/readme_base.md`
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
* Generated for version 5.
|
|
21
|
+
* Generated for version 5.147.0 at 6/23/2026, 6:50:50 AM
|
|
22
22
|
|
|
23
23
|
-->
|
|
24
|
-
# jssm 5.
|
|
24
|
+
# jssm 5.147.0
|
|
25
25
|
|
|
26
26
|
[**Try the live editor**](https://stonecypher.github.io/jssm-viz-demo/graph_explorer.html) ·
|
|
27
27
|
[Documentation](https://stonecypher.github.io/jssm/docs/) ·
|
|
@@ -312,7 +312,7 @@ That decision shows up everywhere downstream:
|
|
|
312
312
|
or run `npm run benny` against your own machine.
|
|
313
313
|
|
|
314
314
|
- **More thoroughly tested than any other JavaScript state-machine
|
|
315
|
-
library.** 7,
|
|
315
|
+
library.** 7,443 tests at 100.0% line coverage
|
|
316
316
|
([report](https://coveralls.io/github/StoneCypher/jssm)), plus
|
|
317
317
|
fuzz testing via `fast-check`, with parser test data across ten natural
|
|
318
318
|
languages and Emoji.
|
|
@@ -445,11 +445,11 @@ If your contribution is missing here, please open an issue.
|
|
|
445
445
|
|
|
446
446
|
<br/>
|
|
447
447
|
|
|
448
|
-
***7,
|
|
448
|
+
***7,443 tests***, run 82,485 times.
|
|
449
449
|
|
|
450
|
-
- 6,
|
|
451
|
-
- 758 fuzz tests with
|
|
452
|
-
-
|
|
450
|
+
- 6,685 specs with 100.0% coverage
|
|
451
|
+
- 758 fuzz tests with 69.6% coverage
|
|
452
|
+
- 7,276 TypeScript lines - 1.0 tests per line, 11.3 generated tests per line
|
|
453
453
|
|
|
454
454
|
[](https://github.com/StoneCypher/jssm/actions)
|
|
455
455
|
[](https://www.npmjs.com/package/jssm)
|