jssm 5.148.2 → 5.149.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/README.md +7 -7
- package/custom-elements.json +272 -0
- package/dist/cdn/instance.js +1 -1
- package/dist/cdn/viz.js +1 -1
- 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/deno/README.md +7 -7
- package/dist/deno/jssm.js +1 -1
- 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/docs.define.js +52 -0
- package/dist/wc/docs.js +1131 -0
- package/package.json +15 -3
package/dist/wc/docs.js
ADDED
|
@@ -0,0 +1,1131 @@
|
|
|
1
|
+
import { css, LitElement, html } from 'lit';
|
|
2
|
+
import { property, state } from 'lit/decorators.js';
|
|
3
|
+
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
4
|
+
|
|
5
|
+
const DOCS_PAGES = [
|
|
6
|
+
{
|
|
7
|
+
"id": "mealy-vs-moore",
|
|
8
|
+
"section": "about-state-machines",
|
|
9
|
+
"title": "Mealy vs Moore",
|
|
10
|
+
"order": 20,
|
|
11
|
+
"teaches": [],
|
|
12
|
+
"mentions": [],
|
|
13
|
+
"indexTerms": [
|
|
14
|
+
"mealy",
|
|
15
|
+
"moore",
|
|
16
|
+
"output",
|
|
17
|
+
"action",
|
|
18
|
+
"theory"
|
|
19
|
+
],
|
|
20
|
+
"body": "\n# Mealy vs Moore\n\nTwo classic models differ in *where the output lives*:\n\n- A **Moore machine** produces output based only on the **current state**. The output is a property of *being* in a state.\n- A **Mealy machine** produces output based on the **state and the transition** taken. The output is a property of *moving*.\n\nFSL can express both styles. Actions attached to transitions (`A 'go' -> B;`) read naturally as Mealy outputs; state-level behaviour reads as Moore. You rarely have to choose a camp — you model what the system does, and the distinction becomes a way to *describe* your machine rather than a constraint you fight.\n"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"id": "what-is-an-fsm",
|
|
24
|
+
"section": "about-state-machines",
|
|
25
|
+
"title": "What is a state machine?",
|
|
26
|
+
"order": 10,
|
|
27
|
+
"teaches": [],
|
|
28
|
+
"mentions": [],
|
|
29
|
+
"indexTerms": [
|
|
30
|
+
"fsm",
|
|
31
|
+
"finite",
|
|
32
|
+
"state",
|
|
33
|
+
"transition",
|
|
34
|
+
"theory",
|
|
35
|
+
"automaton"
|
|
36
|
+
],
|
|
37
|
+
"body": "\n# What is a state machine?\n\nA **finite state machine** is a system that is always in exactly one of a finite set of **states**, and moves between them through **transitions**. A transition fires in response to an input — in FSL, an **action**.\n\nThree ideas carry most of the weight:\n\n- **States** are the situations a system can be in: a door is *Open* or *Closed*; a traffic light is *Red*, *Yellow*, or *Green*.\n- **Transitions** are the allowed moves between states. A door can go *Closed → Open*, but a turnstile cannot go *Locked → Locked-and-paid* without paying first.\n- **Determinism** means that, from a given state and input, the next state is fixed. FSL machines are deterministic by construction.\n\nBecause the set of states is finite and the moves are explicit, a state machine is something you can *reason about* — and even *prove things about* — rather than just run.\n"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "ex-toggle",
|
|
41
|
+
"section": "example-machines",
|
|
42
|
+
"title": "Toggle",
|
|
43
|
+
"order": 20,
|
|
44
|
+
"teaches": [],
|
|
45
|
+
"mentions": [
|
|
46
|
+
"transitions"
|
|
47
|
+
],
|
|
48
|
+
"indexTerms": [
|
|
49
|
+
"toggle",
|
|
50
|
+
"switch",
|
|
51
|
+
"on",
|
|
52
|
+
"off",
|
|
53
|
+
"example"
|
|
54
|
+
],
|
|
55
|
+
"body": "\n# Toggle\n\nThe smallest useful machine: two states and one action that flips between them.\n\n```fsl {run: true}\nOff 'flip' -> On 'flip' -> Off;\n```\n\nThis is the shape behind every checkbox, light switch, and feature flag — a single action bouncing the system between two states.\n"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"id": "ex-traffic-light",
|
|
59
|
+
"section": "example-machines",
|
|
60
|
+
"title": "Traffic light",
|
|
61
|
+
"order": 10,
|
|
62
|
+
"teaches": [],
|
|
63
|
+
"mentions": [
|
|
64
|
+
"transitions",
|
|
65
|
+
"timed-transitions"
|
|
66
|
+
],
|
|
67
|
+
"indexTerms": [
|
|
68
|
+
"traffic",
|
|
69
|
+
"light",
|
|
70
|
+
"example",
|
|
71
|
+
"cycle"
|
|
72
|
+
],
|
|
73
|
+
"body": "\n# Traffic light\n\nThe canonical state machine: three states that cycle on a timer. Load it and watch the diagram.\n\n```fsl {run: true}\nGreen after 5 -> Yellow;\nYellow after 2 -> Red;\nRed after 5 -> Green;\n```\n\nSwap the `after` clauses for actions (`Green 'advance' -> Yellow;`) to drive it by hand instead of by timer.\n"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "first-machine",
|
|
77
|
+
"section": "getting-started",
|
|
78
|
+
"title": "Your first machine",
|
|
79
|
+
"order": 30,
|
|
80
|
+
"teaches": [],
|
|
81
|
+
"mentions": [
|
|
82
|
+
"transitions"
|
|
83
|
+
],
|
|
84
|
+
"indexTerms": [
|
|
85
|
+
"first",
|
|
86
|
+
"example",
|
|
87
|
+
"quickstart",
|
|
88
|
+
"machine"
|
|
89
|
+
],
|
|
90
|
+
"body": "\n# Your first machine\n\nAn FSL file is a list of statements. The simplest machine is a chain of transitions. States are inferred from the arrows — you do not have to declare them.\n\nTry loading this into the editor and watch the diagram appear:\n\n```fsl {run: true}\nSolid 'crack' -> Liquid 'boil' -> Gas;\n```\n\nEach transition is a **source state**, an optional **action** in single quotes, an **arrow**, and a **target state**. Add `machine_name : \"…\";` at the top to give your machine a title.\n"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"id": "using-the-editor",
|
|
94
|
+
"section": "getting-started",
|
|
95
|
+
"title": "Using the editor",
|
|
96
|
+
"order": 20,
|
|
97
|
+
"teaches": [],
|
|
98
|
+
"mentions": [],
|
|
99
|
+
"indexTerms": [
|
|
100
|
+
"autocomplete",
|
|
101
|
+
"layout",
|
|
102
|
+
"theme",
|
|
103
|
+
"diagram",
|
|
104
|
+
"resize",
|
|
105
|
+
"highlight"
|
|
106
|
+
],
|
|
107
|
+
"body": "\n# Using the editor\n\n## Editing and autocomplete\n\nWrite FSL in the code pane. Suggestions appear as you type after a `:`, or on Ctrl+Space. At the start of a line you get **keys** — machine attributes, config, and (inside a `{ }` block) per-state style keys. After a key's `:` you get its **values** — shapes, layouts, directions, and the full SVG color list with a swatch preview.\n\n## The live diagram\n\nThe graph re-renders whenever the machine parses and compiles cleanly. While an edit is invalid, the last good diagram stays and the status bar shows the parser error.\n\n## Layouts\n\nThe **View** button chooses how the panes sit: side by side or stacked with the editor on either side, just the editor or just the viewer, or **Tabbed** — one pane at a time. **Auto** follows the window shape.\n\n## Resizing panes\n\nDrag any divider to resize — between the graph and code, or this docs panel and the rest. Double-click a divider to reset it.\n\n## Highlighting\n\nBeyond the base syntax colors, the editor reads the parsed machine to mark what the tokenizer cannot: color values get a swatch chip in their own color, state names are tinted apart from other identifiers, and shape values are marked as enums.\n\n## Theme\n\nThe sun / moon button switches between light and dark, and your choice is remembered.\n"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "welcome",
|
|
111
|
+
"section": "getting-started",
|
|
112
|
+
"title": "Welcome to FSL",
|
|
113
|
+
"order": 10,
|
|
114
|
+
"teaches": [],
|
|
115
|
+
"mentions": [
|
|
116
|
+
"transitions"
|
|
117
|
+
],
|
|
118
|
+
"indexTerms": [
|
|
119
|
+
"intro",
|
|
120
|
+
"start",
|
|
121
|
+
"hello"
|
|
122
|
+
],
|
|
123
|
+
"body": "\n# Welcome to FSL\n\nFSL is a small language for finite state machines. Most machines are one line.\n\n```fsl {teaches: transitions, run: true}\nRed 'go' -> Green 'go' -> Yellow 'go' -> Red;\n```\n"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"id": "tut-states-and-styling",
|
|
127
|
+
"section": "tutorials",
|
|
128
|
+
"title": "States and styling",
|
|
129
|
+
"order": 20,
|
|
130
|
+
"teaches": [
|
|
131
|
+
"states"
|
|
132
|
+
],
|
|
133
|
+
"mentions": [
|
|
134
|
+
"state-styling",
|
|
135
|
+
"colors"
|
|
136
|
+
],
|
|
137
|
+
"indexTerms": [
|
|
138
|
+
"state",
|
|
139
|
+
"declaration",
|
|
140
|
+
"style",
|
|
141
|
+
"color",
|
|
142
|
+
"shape"
|
|
143
|
+
],
|
|
144
|
+
"body": "\n# States and styling\n\nMost states are inferred from transitions, but you can **declare** a state explicitly to give it a style. A declaration is `state Name { … };` with style keys inside.\n\n```fsl {teaches: states, run: true}\nstate On : {\n background-color : green;\n};\n\nOff 'flip' -> On 'flip' -> Off;\n```\n\nInside the block you can set `background-color`, `text-color`, `border-color`, `shape`, `corners`, and more — the same vocabulary the autocomplete offers after a `:`. Declared or not, a state still participates in transitions exactly the same way.\n"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "tut-timed-transitions",
|
|
148
|
+
"section": "tutorials",
|
|
149
|
+
"title": "Timed transitions",
|
|
150
|
+
"order": 30,
|
|
151
|
+
"teaches": [
|
|
152
|
+
"timed-transitions"
|
|
153
|
+
],
|
|
154
|
+
"mentions": [
|
|
155
|
+
"transitions"
|
|
156
|
+
],
|
|
157
|
+
"indexTerms": [
|
|
158
|
+
"after",
|
|
159
|
+
"timeout",
|
|
160
|
+
"delay",
|
|
161
|
+
"timer",
|
|
162
|
+
"seconds"
|
|
163
|
+
],
|
|
164
|
+
"body": "\n# Timed transitions\n\nA transition can fire **on its own after a delay** using `after`. This is how you model timeouts — a traffic light that advances itself, a session that expires.\n\n```fsl {teaches: timed-transitions, run: true}\nGreen after 5 -> Yellow;\nYellow after 2 -> Red;\nRed after 5 -> Green;\n```\n\n**Watch the units.** A bare `after 5` means **five seconds**, not five milliseconds — the implicit scale is 1000. Write `after 500ms` if you really mean milliseconds. This trips people up constantly, so when in doubt, spell the unit out.\n"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"id": "tut-transitions",
|
|
168
|
+
"section": "tutorials",
|
|
169
|
+
"title": "Transitions",
|
|
170
|
+
"order": 10,
|
|
171
|
+
"teaches": [
|
|
172
|
+
"transitions"
|
|
173
|
+
],
|
|
174
|
+
"mentions": [
|
|
175
|
+
"states",
|
|
176
|
+
"labels-quoting"
|
|
177
|
+
],
|
|
178
|
+
"indexTerms": [
|
|
179
|
+
"arrow",
|
|
180
|
+
"edge",
|
|
181
|
+
"transition",
|
|
182
|
+
"action"
|
|
183
|
+
],
|
|
184
|
+
"body": "\n# Transitions\n\nA transition is the core of FSL: a **source state**, an arrow, and a **target state**. States are inferred from the arrows, so you never declare them just to use them.\n\n```fsl {teaches: transitions, run: true}\nOff 'flip' -> On 'flip' -> Off;\n```\n\nThe text in single quotes is an **action** — the named input that fires the transition. You can chain transitions on one line, as above, or write them one per line. The plain `->` arrow means a *legal* transition; later tutorials cover the other arrow kinds.\n"
|
|
185
|
+
}
|
|
186
|
+
];
|
|
187
|
+
const DOCS_FEATURES = [
|
|
188
|
+
{
|
|
189
|
+
"id": "doc-structure",
|
|
190
|
+
"surface": "language",
|
|
191
|
+
"title": "Document structure",
|
|
192
|
+
"tier": "core",
|
|
193
|
+
"referenceAnchor": "1-document-shape",
|
|
194
|
+
"indexTerms": [
|
|
195
|
+
"document",
|
|
196
|
+
"term",
|
|
197
|
+
"statement",
|
|
198
|
+
"top level"
|
|
199
|
+
]
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"id": "comments",
|
|
203
|
+
"surface": "language",
|
|
204
|
+
"title": "Comments",
|
|
205
|
+
"tier": "core",
|
|
206
|
+
"indexTerms": [
|
|
207
|
+
"comment",
|
|
208
|
+
"//",
|
|
209
|
+
"/*",
|
|
210
|
+
"block comment",
|
|
211
|
+
"line comment"
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"id": "transitions",
|
|
216
|
+
"surface": "language",
|
|
217
|
+
"title": "Transitions",
|
|
218
|
+
"tier": "core",
|
|
219
|
+
"referenceAnchor": "3-transitions",
|
|
220
|
+
"indexTerms": [
|
|
221
|
+
"transition",
|
|
222
|
+
"arrow",
|
|
223
|
+
"edge",
|
|
224
|
+
"->",
|
|
225
|
+
"<-",
|
|
226
|
+
"<->"
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"id": "arrow-flavors",
|
|
231
|
+
"surface": "language",
|
|
232
|
+
"title": "Arrow flavors (fat, tilde, light)",
|
|
233
|
+
"tier": "advanced",
|
|
234
|
+
"indexTerms": [
|
|
235
|
+
"fat arrow",
|
|
236
|
+
"tilde arrow",
|
|
237
|
+
"=>",
|
|
238
|
+
"~>",
|
|
239
|
+
"legal",
|
|
240
|
+
"main path",
|
|
241
|
+
"forced"
|
|
242
|
+
]
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "timed-transitions",
|
|
246
|
+
"surface": "language",
|
|
247
|
+
"title": "Timed transitions (after)",
|
|
248
|
+
"tier": "intermediate",
|
|
249
|
+
"indexTerms": [
|
|
250
|
+
"after",
|
|
251
|
+
"timeout",
|
|
252
|
+
"delay",
|
|
253
|
+
"timer",
|
|
254
|
+
"seconds"
|
|
255
|
+
]
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"id": "weighted-arrows",
|
|
259
|
+
"surface": "language",
|
|
260
|
+
"title": "Weighted / probabilistic arrows",
|
|
261
|
+
"tier": "advanced",
|
|
262
|
+
"indexTerms": [
|
|
263
|
+
"probability",
|
|
264
|
+
"weight",
|
|
265
|
+
"percent",
|
|
266
|
+
"random",
|
|
267
|
+
"cycle",
|
|
268
|
+
"Pi",
|
|
269
|
+
"Infinity"
|
|
270
|
+
]
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"id": "arrow-decorations",
|
|
274
|
+
"surface": "language",
|
|
275
|
+
"title": "Per-arrow decorations (labels, colors)",
|
|
276
|
+
"tier": "advanced",
|
|
277
|
+
"indexTerms": [
|
|
278
|
+
"arrow label",
|
|
279
|
+
"edge label",
|
|
280
|
+
"arc_label",
|
|
281
|
+
"head_label",
|
|
282
|
+
"tail_label",
|
|
283
|
+
"per-arrow color"
|
|
284
|
+
]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"id": "labels-quoting",
|
|
288
|
+
"surface": "language",
|
|
289
|
+
"title": "Labels and quoting",
|
|
290
|
+
"tier": "core",
|
|
291
|
+
"referenceAnchor": "5-labels-strings-atoms",
|
|
292
|
+
"indexTerms": [
|
|
293
|
+
"label",
|
|
294
|
+
"string",
|
|
295
|
+
"atom",
|
|
296
|
+
"quote",
|
|
297
|
+
"name",
|
|
298
|
+
"action"
|
|
299
|
+
]
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
"id": "states",
|
|
303
|
+
"surface": "language",
|
|
304
|
+
"title": "State declarations",
|
|
305
|
+
"tier": "core",
|
|
306
|
+
"indexTerms": [
|
|
307
|
+
"state",
|
|
308
|
+
"node",
|
|
309
|
+
"declaration"
|
|
310
|
+
]
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"id": "state-styling",
|
|
314
|
+
"surface": "language",
|
|
315
|
+
"title": "State styling",
|
|
316
|
+
"tier": "intermediate",
|
|
317
|
+
"indexTerms": [
|
|
318
|
+
"style",
|
|
319
|
+
"color",
|
|
320
|
+
"shape",
|
|
321
|
+
"border",
|
|
322
|
+
"background",
|
|
323
|
+
"image",
|
|
324
|
+
"node style"
|
|
325
|
+
]
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"id": "colors",
|
|
329
|
+
"surface": "language",
|
|
330
|
+
"title": "Colors",
|
|
331
|
+
"tier": "intermediate",
|
|
332
|
+
"indexTerms": [
|
|
333
|
+
"color",
|
|
334
|
+
"svg color",
|
|
335
|
+
"hex",
|
|
336
|
+
"rgb",
|
|
337
|
+
"rgba",
|
|
338
|
+
"#"
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
"id": "shapes",
|
|
343
|
+
"surface": "language",
|
|
344
|
+
"title": "State shapes",
|
|
345
|
+
"tier": "advanced",
|
|
346
|
+
"indexTerms": [
|
|
347
|
+
"shape",
|
|
348
|
+
"box",
|
|
349
|
+
"circle",
|
|
350
|
+
"ellipse",
|
|
351
|
+
"graphviz shape"
|
|
352
|
+
]
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
"id": "line-styles",
|
|
356
|
+
"surface": "language",
|
|
357
|
+
"title": "Line styles",
|
|
358
|
+
"tier": "intermediate",
|
|
359
|
+
"indexTerms": [
|
|
360
|
+
"line style",
|
|
361
|
+
"dashed",
|
|
362
|
+
"dotted",
|
|
363
|
+
"solid",
|
|
364
|
+
"bold"
|
|
365
|
+
]
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
"id": "corners",
|
|
369
|
+
"surface": "language",
|
|
370
|
+
"title": "Corner styles",
|
|
371
|
+
"tier": "advanced",
|
|
372
|
+
"indexTerms": [
|
|
373
|
+
"corners",
|
|
374
|
+
"rounded",
|
|
375
|
+
"regular"
|
|
376
|
+
]
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
"id": "directions",
|
|
380
|
+
"surface": "language",
|
|
381
|
+
"title": "Directions",
|
|
382
|
+
"tier": "advanced",
|
|
383
|
+
"indexTerms": [
|
|
384
|
+
"direction",
|
|
385
|
+
"up",
|
|
386
|
+
"down",
|
|
387
|
+
"left",
|
|
388
|
+
"right"
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"id": "literal-values",
|
|
393
|
+
"surface": "language",
|
|
394
|
+
"title": "Literal values (boolean, null, undefined)",
|
|
395
|
+
"tier": "intermediate",
|
|
396
|
+
"indexTerms": [
|
|
397
|
+
"true",
|
|
398
|
+
"false",
|
|
399
|
+
"null",
|
|
400
|
+
"undefined",
|
|
401
|
+
"boolean"
|
|
402
|
+
]
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
"id": "urls",
|
|
406
|
+
"surface": "language",
|
|
407
|
+
"title": "URLs",
|
|
408
|
+
"tier": "advanced",
|
|
409
|
+
"indexTerms": [
|
|
410
|
+
"url",
|
|
411
|
+
"link",
|
|
412
|
+
"http",
|
|
413
|
+
"https"
|
|
414
|
+
]
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
"id": "groups",
|
|
418
|
+
"surface": "language",
|
|
419
|
+
"title": "Groups and named lists",
|
|
420
|
+
"tier": "intermediate",
|
|
421
|
+
"indexTerms": [
|
|
422
|
+
"group",
|
|
423
|
+
"named list",
|
|
424
|
+
"&",
|
|
425
|
+
"reusable",
|
|
426
|
+
"set"
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
"id": "hooks",
|
|
431
|
+
"surface": "language",
|
|
432
|
+
"title": "Boundary hooks",
|
|
433
|
+
"tier": "intermediate",
|
|
434
|
+
"indexTerms": [
|
|
435
|
+
"hook",
|
|
436
|
+
"on enter",
|
|
437
|
+
"on exit",
|
|
438
|
+
"boundary",
|
|
439
|
+
"callback"
|
|
440
|
+
]
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"id": "config-blocks",
|
|
444
|
+
"surface": "language",
|
|
445
|
+
"title": "Configuration blocks",
|
|
446
|
+
"tier": "intermediate",
|
|
447
|
+
"referenceAnchor": "8-configuration-blocks-config",
|
|
448
|
+
"indexTerms": [
|
|
449
|
+
"config",
|
|
450
|
+
"transition config",
|
|
451
|
+
"graph config",
|
|
452
|
+
"state defaults",
|
|
453
|
+
"block"
|
|
454
|
+
]
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
"id": "single-value-configs",
|
|
458
|
+
"surface": "language",
|
|
459
|
+
"title": "Single-value configuration",
|
|
460
|
+
"tier": "intermediate",
|
|
461
|
+
"referenceAnchor": "8-configuration-blocks-config",
|
|
462
|
+
"indexTerms": [
|
|
463
|
+
"graph_layout",
|
|
464
|
+
"start_states",
|
|
465
|
+
"allow_islands",
|
|
466
|
+
"allows_override",
|
|
467
|
+
"failed_outputs"
|
|
468
|
+
]
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"id": "machine-attributes",
|
|
472
|
+
"surface": "language",
|
|
473
|
+
"title": "Machine attributes",
|
|
474
|
+
"tier": "core",
|
|
475
|
+
"referenceAnchor": "9-machine-attributes",
|
|
476
|
+
"indexTerms": [
|
|
477
|
+
"machine_name",
|
|
478
|
+
"fsl_version",
|
|
479
|
+
"author",
|
|
480
|
+
"license",
|
|
481
|
+
"theme",
|
|
482
|
+
"metadata",
|
|
483
|
+
"attribute"
|
|
484
|
+
]
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
"id": "typed-properties",
|
|
488
|
+
"surface": "language",
|
|
489
|
+
"title": "Typed machine properties",
|
|
490
|
+
"tier": "advanced",
|
|
491
|
+
"indexTerms": [
|
|
492
|
+
"property",
|
|
493
|
+
"typed property",
|
|
494
|
+
"required",
|
|
495
|
+
"default",
|
|
496
|
+
"extended state"
|
|
497
|
+
]
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"id": "semver",
|
|
501
|
+
"surface": "language",
|
|
502
|
+
"title": "Version ranges (SemVer)",
|
|
503
|
+
"tier": "intermediate",
|
|
504
|
+
"indexTerms": [
|
|
505
|
+
"semver",
|
|
506
|
+
"version",
|
|
507
|
+
"fsl_version",
|
|
508
|
+
"range"
|
|
509
|
+
]
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
"id": "arrange",
|
|
513
|
+
"surface": "language",
|
|
514
|
+
"title": "Layout hints (arrange)",
|
|
515
|
+
"tier": "advanced",
|
|
516
|
+
"indexTerms": [
|
|
517
|
+
"arrange",
|
|
518
|
+
"layout",
|
|
519
|
+
"rank",
|
|
520
|
+
"position"
|
|
521
|
+
]
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
"id": "api-machine",
|
|
525
|
+
"surface": "api",
|
|
526
|
+
"title": "The Machine and its factories",
|
|
527
|
+
"tier": "core",
|
|
528
|
+
"indexTerms": [
|
|
529
|
+
"state_machine",
|
|
530
|
+
"sm",
|
|
531
|
+
"from",
|
|
532
|
+
"compile",
|
|
533
|
+
"deserialize",
|
|
534
|
+
"instantiate",
|
|
535
|
+
"Machine"
|
|
536
|
+
]
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
"id": "api-version-info",
|
|
540
|
+
"surface": "api",
|
|
541
|
+
"title": "Version and build info (API)",
|
|
542
|
+
"tier": "intermediate",
|
|
543
|
+
"indexTerms": [
|
|
544
|
+
"version",
|
|
545
|
+
"build time",
|
|
546
|
+
"compareVersions"
|
|
547
|
+
]
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
"id": "api-arrow-introspection",
|
|
551
|
+
"surface": "api",
|
|
552
|
+
"title": "Arrow introspection helpers",
|
|
553
|
+
"tier": "advanced",
|
|
554
|
+
"indexTerms": [
|
|
555
|
+
"arrow direction",
|
|
556
|
+
"arrow kind",
|
|
557
|
+
"introspection"
|
|
558
|
+
]
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
"id": "api-constants",
|
|
562
|
+
"surface": "api",
|
|
563
|
+
"title": "Exported constants and vocabularies",
|
|
564
|
+
"tier": "intermediate",
|
|
565
|
+
"indexTerms": [
|
|
566
|
+
"constants",
|
|
567
|
+
"shapes",
|
|
568
|
+
"named_colors",
|
|
569
|
+
"directions"
|
|
570
|
+
]
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
"id": "api-hook-helpers",
|
|
574
|
+
"surface": "api",
|
|
575
|
+
"title": "Hook result helpers (API)",
|
|
576
|
+
"tier": "advanced",
|
|
577
|
+
"indexTerms": [
|
|
578
|
+
"hook",
|
|
579
|
+
"rejection",
|
|
580
|
+
"hook result"
|
|
581
|
+
]
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
"id": "api-utilities",
|
|
585
|
+
"surface": "api",
|
|
586
|
+
"title": "Utility exports",
|
|
587
|
+
"tier": "advanced",
|
|
588
|
+
"indexTerms": [
|
|
589
|
+
"seq",
|
|
590
|
+
"random",
|
|
591
|
+
"weighted",
|
|
592
|
+
"sleep",
|
|
593
|
+
"utility"
|
|
594
|
+
]
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
"id": "viz-render",
|
|
598
|
+
"surface": "viz",
|
|
599
|
+
"title": "Rendering FSL / machines to SVG",
|
|
600
|
+
"tier": "core",
|
|
601
|
+
"indexTerms": [
|
|
602
|
+
"svg",
|
|
603
|
+
"render",
|
|
604
|
+
"visualize",
|
|
605
|
+
"diagram"
|
|
606
|
+
]
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
"id": "viz-dot",
|
|
610
|
+
"surface": "viz",
|
|
611
|
+
"title": "DOT (Graphviz) output",
|
|
612
|
+
"tier": "intermediate",
|
|
613
|
+
"indexTerms": [
|
|
614
|
+
"dot",
|
|
615
|
+
"graphviz"
|
|
616
|
+
]
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
"id": "viz-config",
|
|
620
|
+
"surface": "viz",
|
|
621
|
+
"title": "Render configuration",
|
|
622
|
+
"tier": "intermediate",
|
|
623
|
+
"indexTerms": [
|
|
624
|
+
"configure",
|
|
625
|
+
"render options",
|
|
626
|
+
"groups"
|
|
627
|
+
]
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
"id": "viz-version-info",
|
|
631
|
+
"surface": "viz",
|
|
632
|
+
"title": "Version and build info (viz)",
|
|
633
|
+
"tier": "advanced",
|
|
634
|
+
"indexTerms": [
|
|
635
|
+
"version",
|
|
636
|
+
"build time"
|
|
637
|
+
]
|
|
638
|
+
},
|
|
639
|
+
{
|
|
640
|
+
"id": "editor-language-support",
|
|
641
|
+
"surface": "editor",
|
|
642
|
+
"title": "CodeMirror 6 FSL language support",
|
|
643
|
+
"tier": "core",
|
|
644
|
+
"indexTerms": [
|
|
645
|
+
"codemirror",
|
|
646
|
+
"cm6",
|
|
647
|
+
"language support",
|
|
648
|
+
"editor"
|
|
649
|
+
]
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
"id": "editor-highlighting",
|
|
653
|
+
"surface": "editor",
|
|
654
|
+
"title": "Syntax highlighting",
|
|
655
|
+
"tier": "intermediate",
|
|
656
|
+
"indexTerms": [
|
|
657
|
+
"highlight",
|
|
658
|
+
"syntax color",
|
|
659
|
+
"deprecated marker"
|
|
660
|
+
]
|
|
661
|
+
},
|
|
662
|
+
{
|
|
663
|
+
"id": "editor-keyword-sets",
|
|
664
|
+
"surface": "editor",
|
|
665
|
+
"title": "Keyword classification sets",
|
|
666
|
+
"tier": "advanced",
|
|
667
|
+
"indexTerms": [
|
|
668
|
+
"keywords",
|
|
669
|
+
"structural",
|
|
670
|
+
"property",
|
|
671
|
+
"enum"
|
|
672
|
+
]
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
"id": "wc-viz",
|
|
676
|
+
"surface": "webcomponent",
|
|
677
|
+
"title": "<fsl-viz> diagram element",
|
|
678
|
+
"tier": "core",
|
|
679
|
+
"indexTerms": [
|
|
680
|
+
"fsl-viz",
|
|
681
|
+
"web component",
|
|
682
|
+
"custom element",
|
|
683
|
+
"diagram"
|
|
684
|
+
]
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
"id": "wc-instance",
|
|
688
|
+
"surface": "webcomponent",
|
|
689
|
+
"title": "<fsl-instance> live machine element",
|
|
690
|
+
"tier": "intermediate",
|
|
691
|
+
"indexTerms": [
|
|
692
|
+
"fsl-instance",
|
|
693
|
+
"interactive",
|
|
694
|
+
"live machine"
|
|
695
|
+
]
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
"id": "wc-bind",
|
|
699
|
+
"surface": "webcomponent",
|
|
700
|
+
"title": "<fsl-bind> data binding",
|
|
701
|
+
"tier": "intermediate",
|
|
702
|
+
"indexTerms": [
|
|
703
|
+
"fsl-bind",
|
|
704
|
+
"binding",
|
|
705
|
+
"data"
|
|
706
|
+
]
|
|
707
|
+
},
|
|
708
|
+
{
|
|
709
|
+
"id": "wc-panels",
|
|
710
|
+
"surface": "webcomponent",
|
|
711
|
+
"title": "Inspector panels",
|
|
712
|
+
"tier": "advanced",
|
|
713
|
+
"indexTerms": [
|
|
714
|
+
"panel",
|
|
715
|
+
"inspector",
|
|
716
|
+
"info",
|
|
717
|
+
"effective properties"
|
|
718
|
+
]
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
"id": "cli-dispatcher",
|
|
722
|
+
"surface": "cli",
|
|
723
|
+
"title": "The fsl dispatcher",
|
|
724
|
+
"tier": "core",
|
|
725
|
+
"indexTerms": [
|
|
726
|
+
"cli",
|
|
727
|
+
"fsl",
|
|
728
|
+
"dispatcher",
|
|
729
|
+
"--help",
|
|
730
|
+
"--version"
|
|
731
|
+
]
|
|
732
|
+
},
|
|
733
|
+
{
|
|
734
|
+
"id": "cli-render",
|
|
735
|
+
"surface": "cli",
|
|
736
|
+
"title": "fsl render",
|
|
737
|
+
"tier": "core",
|
|
738
|
+
"indexTerms": [
|
|
739
|
+
"render",
|
|
740
|
+
"cli render",
|
|
741
|
+
"fsl-render"
|
|
742
|
+
]
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
"id": "cli-render-targets",
|
|
746
|
+
"surface": "cli",
|
|
747
|
+
"title": "Render output formats",
|
|
748
|
+
"tier": "intermediate",
|
|
749
|
+
"indexTerms": [
|
|
750
|
+
"svg",
|
|
751
|
+
"png",
|
|
752
|
+
"jpeg",
|
|
753
|
+
"dot",
|
|
754
|
+
"html",
|
|
755
|
+
"format",
|
|
756
|
+
"export"
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
"id": "cli-export-prompt",
|
|
761
|
+
"surface": "cli",
|
|
762
|
+
"title": "fsl export-system-prompt",
|
|
763
|
+
"tier": "advanced",
|
|
764
|
+
"indexTerms": [
|
|
765
|
+
"system prompt",
|
|
766
|
+
"llms.txt",
|
|
767
|
+
"export prompt"
|
|
768
|
+
]
|
|
769
|
+
},
|
|
770
|
+
{
|
|
771
|
+
"id": "prompt-overview",
|
|
772
|
+
"surface": "llm-prompt",
|
|
773
|
+
"title": "System-prompt overview sections",
|
|
774
|
+
"tier": "intermediate",
|
|
775
|
+
"indexTerms": [
|
|
776
|
+
"llms.txt",
|
|
777
|
+
"system prompt",
|
|
778
|
+
"agent",
|
|
779
|
+
"concepts"
|
|
780
|
+
]
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
"id": "prompt-examples",
|
|
784
|
+
"surface": "llm-prompt",
|
|
785
|
+
"title": "System-prompt worked examples",
|
|
786
|
+
"tier": "advanced",
|
|
787
|
+
"indexTerms": [
|
|
788
|
+
"example",
|
|
789
|
+
"basic machine",
|
|
790
|
+
"actions"
|
|
791
|
+
]
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
"id": "api-language-service",
|
|
795
|
+
"surface": "api",
|
|
796
|
+
"title": "Language service helpers",
|
|
797
|
+
"tier": "advanced",
|
|
798
|
+
"indexTerms": [
|
|
799
|
+
"language service",
|
|
800
|
+
"completions",
|
|
801
|
+
"diagnostics",
|
|
802
|
+
"semantic spans"
|
|
803
|
+
]
|
|
804
|
+
},
|
|
805
|
+
{
|
|
806
|
+
"id": "wc-editor-suite",
|
|
807
|
+
"surface": "webcomponent",
|
|
808
|
+
"title": "FSL editor web-component suite",
|
|
809
|
+
"tier": "advanced",
|
|
810
|
+
"indexTerms": [
|
|
811
|
+
"editor",
|
|
812
|
+
"help panel",
|
|
813
|
+
"docs",
|
|
814
|
+
"toolbar",
|
|
815
|
+
"footer",
|
|
816
|
+
"inspector",
|
|
817
|
+
"web component suite"
|
|
818
|
+
]
|
|
819
|
+
}
|
|
820
|
+
];
|
|
821
|
+
|
|
822
|
+
// Minimal, dependency-free markdown renderer for <fsl-docs>. Renders the help
|
|
823
|
+
// subset to an HTML string; fsl code fences are tagged with data attributes so
|
|
824
|
+
// the component can wire a "load into editor" button.
|
|
825
|
+
/** Parse a fenced-code info string like `fsl {teaches: x, run: true}`. */
|
|
826
|
+
function parseFenceInfo(info) {
|
|
827
|
+
var _a, _b;
|
|
828
|
+
const m = /^(\S+)\s*(?:\{([^}]*)\})?/.exec(info.trim());
|
|
829
|
+
const lang = (_a = m === null || m === void 0 ? void 0 : m[1]) !== null && _a !== void 0 ? _a : '';
|
|
830
|
+
const attrs = {};
|
|
831
|
+
for (const pair of ((_b = m === null || m === void 0 ? void 0 : m[2]) !== null && _b !== void 0 ? _b : '').split(',')) {
|
|
832
|
+
const kv = pair.split(':');
|
|
833
|
+
if (kv.length < 2) {
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
const k = kv[0].trim();
|
|
837
|
+
const raw = kv.slice(1).join(':').trim();
|
|
838
|
+
if (k) {
|
|
839
|
+
attrs[k] = raw === 'true' ? true : raw === 'false' ? false : raw;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
return { lang, attrs };
|
|
843
|
+
}
|
|
844
|
+
const esc = (s) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
845
|
+
function inline(s) {
|
|
846
|
+
return esc(s)
|
|
847
|
+
.replace(/`([^`]+)`/g, (_m, c) => `<code>${c}</code>`)
|
|
848
|
+
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
|
849
|
+
.replace(/\*([^*]+)\*/g, '<em>$1</em>')
|
|
850
|
+
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
|
|
851
|
+
}
|
|
852
|
+
/** Render the supported markdown subset to an HTML string. */
|
|
853
|
+
function renderMarkdown(md) {
|
|
854
|
+
const lines = md.replace(/\r\n/g, '\n').split('\n');
|
|
855
|
+
const out = [];
|
|
856
|
+
let i = 0;
|
|
857
|
+
while (i < lines.length) {
|
|
858
|
+
const line = lines[i];
|
|
859
|
+
const fence = /^```(.*)$/.exec(line);
|
|
860
|
+
if (fence) {
|
|
861
|
+
const { lang, attrs } = parseFenceInfo(fence[1]);
|
|
862
|
+
const buf = [];
|
|
863
|
+
i++;
|
|
864
|
+
while (i < lines.length && !/^```/.test(lines[i])) {
|
|
865
|
+
buf.push(lines[i]);
|
|
866
|
+
i++;
|
|
867
|
+
}
|
|
868
|
+
i++;
|
|
869
|
+
const code = esc(buf.join('\n'));
|
|
870
|
+
if (lang === 'fsl') {
|
|
871
|
+
const teaches = attrs.teaches ? ` data-teaches="${esc(String(attrs.teaches))}"` : '';
|
|
872
|
+
const run = attrs.run === true ? ' data-run="true"' : '';
|
|
873
|
+
out.push(`<pre data-fsl-example${teaches}${run}><code>${code}</code></pre>`);
|
|
874
|
+
}
|
|
875
|
+
else {
|
|
876
|
+
out.push(`<pre><code>${code}</code></pre>`);
|
|
877
|
+
}
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
const head = /^(#{1,3})\s+(.*)$/.exec(line);
|
|
881
|
+
if (head) {
|
|
882
|
+
out.push(`<h${head[1].length}>${inline(head[2])}</h${head[1].length}>`);
|
|
883
|
+
i++;
|
|
884
|
+
continue;
|
|
885
|
+
}
|
|
886
|
+
if (/^---+\s*$/.test(line)) {
|
|
887
|
+
out.push('<hr>');
|
|
888
|
+
i++;
|
|
889
|
+
continue;
|
|
890
|
+
}
|
|
891
|
+
if (/^\s*[-*]\s+/.test(line)) {
|
|
892
|
+
out.push('<ul>');
|
|
893
|
+
while (i < lines.length && /^\s*[-*]\s+/.test(lines[i])) {
|
|
894
|
+
out.push(`<li>${inline(lines[i].replace(/^\s*[-*]\s+/, ''))}</li>`);
|
|
895
|
+
i++;
|
|
896
|
+
}
|
|
897
|
+
out.push('</ul>');
|
|
898
|
+
continue;
|
|
899
|
+
}
|
|
900
|
+
if (/^\s*\d+\.\s+/.test(line)) {
|
|
901
|
+
out.push('<ol>');
|
|
902
|
+
while (i < lines.length && /^\s*\d+\.\s+/.test(lines[i])) {
|
|
903
|
+
out.push(`<li>${inline(lines[i].replace(/^\s*\d+\.\s+/, ''))}</li>`);
|
|
904
|
+
i++;
|
|
905
|
+
}
|
|
906
|
+
out.push('</ol>');
|
|
907
|
+
continue;
|
|
908
|
+
}
|
|
909
|
+
if (/^\s*$/.test(line)) {
|
|
910
|
+
i++;
|
|
911
|
+
continue;
|
|
912
|
+
}
|
|
913
|
+
const para = [];
|
|
914
|
+
while (i < lines.length && !/^\s*$/.test(lines[i]) && !/^(#{1,3}\s|```|\s*[-*]\s|\s*\d+\.\s|---+\s*$)/.test(lines[i])) {
|
|
915
|
+
para.push(lines[i]);
|
|
916
|
+
i++;
|
|
917
|
+
}
|
|
918
|
+
out.push(`<p>${inline(para.join(' '))}</p>`);
|
|
919
|
+
}
|
|
920
|
+
return out.join('\n');
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
/**
|
|
924
|
+
* Shared FSL appearance contract — the `--fsl-*` design-token vocabulary.
|
|
925
|
+
*
|
|
926
|
+
* Components include this in `static styles` and consume the **private**
|
|
927
|
+
* `--_fsl-*` vars, which resolve: embedder's public `--fsl-*` token →
|
|
928
|
+
* `[theme="dark"]` default → built-in light fallback. White-label by setting
|
|
929
|
+
* `--fsl-*` on any ancestor (custom properties inherit through shadow DOM);
|
|
930
|
+
* flip the built-in default with the host's `theme="dark"` attribute.
|
|
931
|
+
*
|
|
932
|
+
* Companion conventions (declared per-component): expose structural elements as
|
|
933
|
+
* `::part(...)` (e.g. `part="toolbar"`, `"gutter"`, `"editor"`) and forward
|
|
934
|
+
* child parts with `exportparts`; chrome components carry brand slots
|
|
935
|
+
* (`<slot name="brand">` / `"logo">`).
|
|
936
|
+
*/
|
|
937
|
+
const fslTokens = css `
|
|
938
|
+
:host {
|
|
939
|
+
--_fsl-surface: var(--fsl-color-surface, #ffffff);
|
|
940
|
+
--_fsl-text: var(--fsl-color-text, #222222);
|
|
941
|
+
--_fsl-accent: var(--fsl-color-accent, #5b9dff);
|
|
942
|
+
--_fsl-border: var(--fsl-color-border, #e5e5e5);
|
|
943
|
+
--_fsl-muted: var(--fsl-color-muted, #9aa0a6);
|
|
944
|
+
--_fsl-font: var(--fsl-font, system-ui, -apple-system, "Segoe UI", sans-serif);
|
|
945
|
+
--_fsl-font-mono: var(--fsl-font-mono, ui-monospace, Consolas, monospace);
|
|
946
|
+
--_fsl-radius: var(--fsl-radius, 6px);
|
|
947
|
+
--_fsl-space-1: var(--fsl-space-1, 4px);
|
|
948
|
+
--_fsl-space-2: var(--fsl-space-2, 8px);
|
|
949
|
+
--_fsl-space-3: var(--fsl-space-3, 12px);
|
|
950
|
+
--_fsl-space-4: var(--fsl-space-4, 16px);
|
|
951
|
+
}
|
|
952
|
+
:host([theme="dark"]) {
|
|
953
|
+
--_fsl-surface: var(--fsl-color-surface, #1e1e22);
|
|
954
|
+
--_fsl-text: var(--fsl-color-text, #d6d6d6);
|
|
955
|
+
--_fsl-accent: var(--fsl-color-accent, #82aaff);
|
|
956
|
+
--_fsl-border: var(--fsl-color-border, #2a2a2e);
|
|
957
|
+
--_fsl-muted: var(--fsl-color-muted, #5a5f66);
|
|
958
|
+
}
|
|
959
|
+
`;
|
|
960
|
+
|
|
961
|
+
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
962
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
963
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
964
|
+
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;
|
|
965
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
966
|
+
};
|
|
967
|
+
const SECTIONS = [
|
|
968
|
+
['getting-started', 'Getting Started'], ['about-state-machines', 'About State Machines'],
|
|
969
|
+
['tutorials', 'Tutorials'], ['example-machines', 'Example Machines'],
|
|
970
|
+
['index', 'Index'], ['search', 'Search'],
|
|
971
|
+
];
|
|
972
|
+
/**
|
|
973
|
+
* `<fsl-docs>` — the language-docs content engine: drill-in nav over the bundled
|
|
974
|
+
* curriculum (Getting Started / About State Machines / Tutorials / Example
|
|
975
|
+
* Machines / Index / Search), a markdown page renderer, and "load into editor"
|
|
976
|
+
* for tagged FSL examples. Content-only; slot it into `<fsl-help>`.
|
|
977
|
+
*
|
|
978
|
+
* @element fsl-docs
|
|
979
|
+
* @fires {CustomEvent<FslDocsLoadExampleDetail>} load-example - When a fence's "Load into editor" is clicked.
|
|
980
|
+
*/
|
|
981
|
+
class FslDocs extends LitElement {
|
|
982
|
+
constructor() {
|
|
983
|
+
super(...arguments);
|
|
984
|
+
/** Color theme; reflected so it drives the `--fsl-*` token defaults. */
|
|
985
|
+
this.theme = 'light';
|
|
986
|
+
this._view = 'sections';
|
|
987
|
+
this._section = '';
|
|
988
|
+
this._pageId = '';
|
|
989
|
+
this._query = '';
|
|
990
|
+
this._go = (view, section = '', pageId = '') => {
|
|
991
|
+
this._view = view;
|
|
992
|
+
this._section = section;
|
|
993
|
+
this._pageId = pageId;
|
|
994
|
+
};
|
|
995
|
+
this._loadExample = (e) => {
|
|
996
|
+
var _a, _b;
|
|
997
|
+
const pre = e.target.closest('pre[data-fsl-example]');
|
|
998
|
+
const fsl = (_b = (_a = pre === null || pre === void 0 ? void 0 : pre.querySelector('code')) === null || _a === void 0 ? void 0 : _a.textContent) !== null && _b !== void 0 ? _b : '';
|
|
999
|
+
this.dispatchEvent(new CustomEvent('load-example', {
|
|
1000
|
+
detail: { fsl }, bubbles: true, composed: true,
|
|
1001
|
+
}));
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
_pagesIn(section) {
|
|
1005
|
+
// Page `order` already encodes the intended tier/dependency ordering (the
|
|
1006
|
+
// teaching-surface dependency-order check enforces it), so a plain sort suffices.
|
|
1007
|
+
return DOCS_PAGES.filter(p => p.section === section).sort((a, b) => a.order - b.order);
|
|
1008
|
+
}
|
|
1009
|
+
/** Display label for a section id (falls back to the id for unknown sections). */
|
|
1010
|
+
_sectionLabel(id) {
|
|
1011
|
+
var _a, _b;
|
|
1012
|
+
return (_b = (_a = SECTIONS.find(s => s[0] === id)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : id;
|
|
1013
|
+
}
|
|
1014
|
+
_renderSections() {
|
|
1015
|
+
return html `
|
|
1016
|
+
<nav class="crumb"><span>Docs</span></nav>
|
|
1017
|
+
<ul class="nav">${SECTIONS.map(([id, label]) => html `
|
|
1018
|
+
<li><a data-section=${id} @click=${() => id === 'index' ? this._go('index') : id === 'search' ? this._go('search') : this._go('pages', id)}>${label}</a></li>`)}</ul>`;
|
|
1019
|
+
}
|
|
1020
|
+
_renderPages() {
|
|
1021
|
+
const label = this._sectionLabel(this._section);
|
|
1022
|
+
const list = this._pagesIn(this._section);
|
|
1023
|
+
return html `
|
|
1024
|
+
<nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> / <span>${label}</span></nav>
|
|
1025
|
+
<ul class="nav">${list.length
|
|
1026
|
+
? list.map(p => html `<li><a data-page=${p.id} @click=${() => this._go('page', this._section, p.id)}>${p.title}</a></li>`)
|
|
1027
|
+
: html `<li class="empty">No pages yet.</li>`}</ul>`;
|
|
1028
|
+
}
|
|
1029
|
+
_renderPage() {
|
|
1030
|
+
const p = DOCS_PAGES.find(x => x.id === this._pageId);
|
|
1031
|
+
if (!p) {
|
|
1032
|
+
return html `<p class="empty">Not found.</p>`;
|
|
1033
|
+
}
|
|
1034
|
+
const label = this._sectionLabel(p.section);
|
|
1035
|
+
return html `
|
|
1036
|
+
<nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> /
|
|
1037
|
+
<a @click=${() => this._go('pages', p.section)}>${label}</a> / <span>${p.title}</span></nav>
|
|
1038
|
+
<article class="docs-page" @click=${(e) => {
|
|
1039
|
+
if (e.target.classList.contains('docs-load-example')) {
|
|
1040
|
+
this._loadExample(e);
|
|
1041
|
+
}
|
|
1042
|
+
}}>${unsafeHTML(this._withButtons(renderMarkdown(p.body)))}</article>`;
|
|
1043
|
+
}
|
|
1044
|
+
/** Append a "Load into editor" button to every runnable fsl fence. */
|
|
1045
|
+
_withButtons(htmlStr) {
|
|
1046
|
+
return htmlStr.replace(/(<pre data-fsl-example[^>]*data-run="true"[^>]*>[\s\S]*?<\/pre>)/g, (m) => m.replace('</pre>', '<button class="docs-load-example">Load into editor</button></pre>'));
|
|
1047
|
+
}
|
|
1048
|
+
render() {
|
|
1049
|
+
switch (this._view) {
|
|
1050
|
+
case 'pages': return this._renderPages();
|
|
1051
|
+
case 'page': return this._renderPage();
|
|
1052
|
+
case 'index': return this._renderIndex();
|
|
1053
|
+
case 'search': return this._renderSearch();
|
|
1054
|
+
default: return this._renderSections();
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
_renderIndex() {
|
|
1058
|
+
var _a;
|
|
1059
|
+
const teachesOf = (id) => DOCS_PAGES.find(p => p.teaches.includes(id));
|
|
1060
|
+
const bySurface = {};
|
|
1061
|
+
for (const f of DOCS_FEATURES) {
|
|
1062
|
+
(bySurface[_a = f.surface] || (bySurface[_a] = [])).push(f);
|
|
1063
|
+
}
|
|
1064
|
+
return html `
|
|
1065
|
+
<nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> / <span>Index</span></nav>
|
|
1066
|
+
${Object.keys(bySurface).sort().map(surface => html `
|
|
1067
|
+
<h3>${surface}</h3>
|
|
1068
|
+
<ul class="nav">${[...bySurface[surface]].sort((a, b) => a.title.localeCompare(b.title)).map(f => {
|
|
1069
|
+
const pg = teachesOf(f.id);
|
|
1070
|
+
return html `<li>${pg
|
|
1071
|
+
? html `<a data-page=${pg.id} @click=${() => this._go('page', pg.section, pg.id)}>${f.title}</a>`
|
|
1072
|
+
: html `<span>${f.title}</span>`}</li>`;
|
|
1073
|
+
})}</ul>`)}`;
|
|
1074
|
+
}
|
|
1075
|
+
_renderSearch() {
|
|
1076
|
+
const q = this._query.trim().toLowerCase();
|
|
1077
|
+
const corpus = [
|
|
1078
|
+
...DOCS_FEATURES.map(f => {
|
|
1079
|
+
var _a;
|
|
1080
|
+
return ({ title: f.title, kind: 'feature',
|
|
1081
|
+
terms: [f.title, ...f.indexTerms].join(' ').toLowerCase(),
|
|
1082
|
+
page: (_a = DOCS_PAGES.find(p => p.teaches.includes(f.id))) === null || _a === void 0 ? void 0 : _a.id });
|
|
1083
|
+
}),
|
|
1084
|
+
...DOCS_PAGES.map(p => ({ title: p.title, kind: 'page',
|
|
1085
|
+
terms: [p.title, ...p.indexTerms].join(' ').toLowerCase(), page: p.id })),
|
|
1086
|
+
];
|
|
1087
|
+
const hits = q ? corpus.filter(c => c.terms.includes(q)).slice(0, 40) : [];
|
|
1088
|
+
return html `
|
|
1089
|
+
<nav class="crumb"><a @click=${() => this._go('sections')}>Docs</a> / <span>Search</span></nav>
|
|
1090
|
+
<input class="search-input" type="search" placeholder="Search the docs…"
|
|
1091
|
+
.value=${this._query} @input=${(e) => { this._query = e.target.value; }}>
|
|
1092
|
+
<ul class="nav">${hits.length
|
|
1093
|
+
? hits.map(h => html `<li>${h.page
|
|
1094
|
+
? html `<a data-page=${h.page} @click=${() => { const p = DOCS_PAGES.find(x => x.id === h.page); this._go('page', p.section, p.id); }}>${h.title}</a>`
|
|
1095
|
+
: html `<span>${h.title}</span>`} <em>${h.kind}</em></li>`)
|
|
1096
|
+
: (q ? html `<li class="empty">No matches.</li>` : html ``)}</ul>`;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
FslDocs.styles = css `
|
|
1100
|
+
:host { display: block; color: var(--_fsl-text); }
|
|
1101
|
+
.crumb { font-size: 0.7rem; color: var(--_fsl-muted); margin: 0.3rem 0 0.5rem; }
|
|
1102
|
+
.crumb a, .nav a { color: var(--_fsl-accent, #6a4cd6); text-decoration: none; cursor: pointer; }
|
|
1103
|
+
.nav { list-style: none; margin: 0.3rem 0; padding: 0; }
|
|
1104
|
+
.nav li { margin: 0.1rem 0; }
|
|
1105
|
+
.nav a { display: block; padding: 0.35rem 0.25rem; border-radius: 4px; }
|
|
1106
|
+
.nav a:hover { background: rgba(127,127,127,0.14); }
|
|
1107
|
+
.docs-page { font-size: 0.82rem; line-height: 1.55; }
|
|
1108
|
+
.docs-page pre { background: var(--_fsl-surface-alt, rgba(127,127,127,0.1)); padding: 0.5rem 0.6rem; border-radius: 6px; overflow-x: auto; }
|
|
1109
|
+
.docs-load-example { display: block; margin-top: 0.4rem; font: inherit; font-size: 0.7rem; cursor: pointer; }
|
|
1110
|
+
.search-input { width: 100%; box-sizing: border-box; padding: 0.35rem 0.5rem; margin: 0.25rem 0 0.5rem;
|
|
1111
|
+
background: var(--_fsl-surface); color: var(--_fsl-text); border: 1px solid var(--_fsl-border); border-radius: 4px; }
|
|
1112
|
+
.empty { color: var(--_fsl-muted); }
|
|
1113
|
+
${fslTokens}
|
|
1114
|
+
`;
|
|
1115
|
+
__decorate([
|
|
1116
|
+
property({ type: String, reflect: true })
|
|
1117
|
+
], FslDocs.prototype, "theme", void 0);
|
|
1118
|
+
__decorate([
|
|
1119
|
+
state()
|
|
1120
|
+
], FslDocs.prototype, "_view", void 0);
|
|
1121
|
+
__decorate([
|
|
1122
|
+
state()
|
|
1123
|
+
], FslDocs.prototype, "_section", void 0);
|
|
1124
|
+
__decorate([
|
|
1125
|
+
state()
|
|
1126
|
+
], FslDocs.prototype, "_pageId", void 0);
|
|
1127
|
+
__decorate([
|
|
1128
|
+
state()
|
|
1129
|
+
], FslDocs.prototype, "_query", void 0);
|
|
1130
|
+
|
|
1131
|
+
export { FslDocs };
|