@rohal12/spindle 0.58.0 → 0.59.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/dist/pkg/format.js +1 -1
- package/dist/pkg/headless.js +318 -196
- package/dist/pkg/macro-registry.json +29 -11
- package/dist/pkg/story-variables.js +329 -206
- package/package.json +1 -1
- package/src/code-check.ts +156 -82
- package/src/components/macros/Button.tsx +3 -1
- package/src/components/macros/Checkbox.tsx +4 -1
- package/src/components/macros/Dialog.tsx +1 -1
- package/src/components/macros/MacroLink.tsx +1 -1
- package/src/components/macros/Meter.tsx +1 -1
- package/src/components/macros/Radiobutton.tsx +2 -2
- package/src/components/macros/Watch.tsx +11 -6
- package/src/components/macros/arg-utils.ts +0 -37
- package/src/components/macros/input-macro.ts +4 -1
- package/src/components/macros/macro-args.ts +93 -52
- package/src/components/macros/option-utils.ts +1 -1
- package/src/index.tsx +2 -4
- package/src/js-lexer.ts +19 -0
- package/src/markup/parse.ts +22 -4
- package/src/markup/spindle.peggy +21 -9
- package/src/markup/tokens.ts +3 -0
- package/src/markup/validate.ts +13 -10
- package/src/registry.ts +63 -6
- package/src/story-variables.ts +12 -8
- package/src/tooling.ts +15 -16
- package/src/widgets/widget-def.ts +2 -2
- package/types/index.d.ts +23 -0
- package/types/tooling.d.ts +28 -2
package/src/tooling.ts
CHANGED
|
@@ -11,8 +11,11 @@ import {
|
|
|
11
11
|
} from './markup/validate';
|
|
12
12
|
import { isBlockMacro } from './markup/ast';
|
|
13
13
|
import { tokenizeMarkupTolerant } from './markup/parse';
|
|
14
|
-
import {
|
|
15
|
-
|
|
14
|
+
import {
|
|
15
|
+
collectPassageReferences,
|
|
16
|
+
parameterLookup,
|
|
17
|
+
type PassageReference,
|
|
18
|
+
} from './code-check';
|
|
16
19
|
import { blockWidgetNames } from './widgets/widget-def';
|
|
17
20
|
import type { ParameterDef } from './registry';
|
|
18
21
|
|
|
@@ -71,8 +74,13 @@ export interface ToolingMacro {
|
|
|
71
74
|
name: string;
|
|
72
75
|
block: boolean;
|
|
73
76
|
subMacros: string[];
|
|
74
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Its declared parameters: their types tell which arguments are code, and
|
|
79
|
+
* what a `string` or `text` argument holds (see ParameterDef.holds).
|
|
80
|
+
*/
|
|
75
81
|
parameters?: readonly ParameterDef[];
|
|
82
|
+
/** Whether it resolves markup: its strings hold markup by default. */
|
|
83
|
+
interpolate?: boolean;
|
|
76
84
|
}
|
|
77
85
|
|
|
78
86
|
/**
|
|
@@ -87,20 +95,19 @@ export function validateStoryMarkup(
|
|
|
87
95
|
options: ValidateMarkupOptions = {},
|
|
88
96
|
): MarkupDiagnostic[] {
|
|
89
97
|
const list = [...passages];
|
|
98
|
+
const all = [...macros];
|
|
90
99
|
const known = new Set<string>();
|
|
91
|
-
const parameters = new Map<string, readonly ParameterDef[] | undefined>();
|
|
92
100
|
const blocks = new Set(blockWidgetNames(list).map((n) => n.toLowerCase()));
|
|
93
|
-
for (const macro of
|
|
101
|
+
for (const macro of all) {
|
|
94
102
|
const name = macro.name.toLowerCase();
|
|
95
103
|
known.add(name);
|
|
96
|
-
parameters.set(name, macro.parameters);
|
|
97
104
|
for (const sub of macro.subMacros) known.add(sub.toLowerCase());
|
|
98
105
|
if (macro.block) blocks.add(name);
|
|
99
106
|
}
|
|
100
107
|
return validateMarkup(list, {
|
|
101
108
|
isKnownMacro: (name) => known.has(name),
|
|
102
109
|
macroNames: known,
|
|
103
|
-
parametersOf: (
|
|
110
|
+
parametersOf: parameterLookup(all),
|
|
104
111
|
isBlockMacro: (name) =>
|
|
105
112
|
blocks.has(name.toLowerCase()) || isBlockMacro(name),
|
|
106
113
|
checkPassageNames: options.checkPassageNames,
|
|
@@ -116,14 +123,6 @@ export function collectStoryPassageReferences(
|
|
|
116
123
|
source: string,
|
|
117
124
|
macros: Iterable<ToolingMacro>,
|
|
118
125
|
): PassageReference[] {
|
|
119
|
-
const parameters = new Map<string, readonly ParameterDef[] | undefined>();
|
|
120
|
-
for (const macro of macros) {
|
|
121
|
-
parameters.set(macro.name.toLowerCase(), macro.parameters);
|
|
122
|
-
}
|
|
123
126
|
const { tokens } = tokenizeMarkupTolerant(source);
|
|
124
|
-
return collectPassageReferences(
|
|
125
|
-
source,
|
|
126
|
-
tokens,
|
|
127
|
-
(name) => parameters.get(name.toLowerCase()) ?? subMacroParameters(name),
|
|
128
|
-
);
|
|
127
|
+
return collectPassageReferences(source, tokens, parameterLookup(macros));
|
|
129
128
|
}
|
|
@@ -7,8 +7,8 @@ import type { MacroArgs } from '../registry';
|
|
|
7
7
|
|
|
8
8
|
/** A {widget} definition's name, then its `@` parameters. */
|
|
9
9
|
export const WIDGET_PARAMETERS = [
|
|
10
|
-
{ name: 'name', type: 'text', required: true },
|
|
11
|
-
{ name: 'parameters', type: 'text' },
|
|
10
|
+
{ name: 'name', type: 'text', holds: 'text', required: true },
|
|
11
|
+
{ name: 'parameters', type: 'text', holds: 'text' },
|
|
12
12
|
] as const;
|
|
13
13
|
|
|
14
14
|
export interface WidgetDef {
|
package/types/index.d.ts
CHANGED
|
@@ -272,6 +272,27 @@ export type ParameterType =
|
|
|
272
272
|
| 'separator'
|
|
273
273
|
| 'options';
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* What the value of a `string` or `text` argument holds, for the check at
|
|
277
|
+
* story start and for tooling:
|
|
278
|
+
* - `markup`: markup the macro renders (`{button}`'s label): its markup
|
|
279
|
+
* is checked.
|
|
280
|
+
* - `text`: plain text the macro uses as written (`{checkbox}`'s label).
|
|
281
|
+
* - `passage`: a passage name (`{watch}`'s `goto`): the passage must exist.
|
|
282
|
+
* - `expression`, `statements`: code (`{watch}`'s condition and `run`): it
|
|
283
|
+
* is checked as code, and its variable references against the schema.
|
|
284
|
+
*
|
|
285
|
+
* Without it, the argument of a macro with `interpolate` holds `markup`,
|
|
286
|
+
* any other `text`.
|
|
287
|
+
* @see {@link ../../src/registry.ts} for the implementation.
|
|
288
|
+
*/
|
|
289
|
+
export type StringHolds =
|
|
290
|
+
| 'markup'
|
|
291
|
+
| 'text'
|
|
292
|
+
| 'passage'
|
|
293
|
+
| 'expression'
|
|
294
|
+
| 'statements';
|
|
295
|
+
|
|
275
296
|
/**
|
|
276
297
|
* Parameter metadata for a macro definition.
|
|
277
298
|
* @see {@link ../../src/registry.ts} for the implementation.
|
|
@@ -282,6 +303,8 @@ export interface ParameterDef {
|
|
|
282
303
|
description?: string;
|
|
283
304
|
/** How the argument is read: required, there is no default. */
|
|
284
305
|
type: ParameterType;
|
|
306
|
+
/** What a `string` or `text` argument holds (see StringHolds). */
|
|
307
|
+
holds?: StringHolds;
|
|
285
308
|
/** The options of an `options` parameter. */
|
|
286
309
|
parameters?: readonly ParameterDef[];
|
|
287
310
|
}
|
package/types/tooling.d.ts
CHANGED
|
@@ -30,12 +30,34 @@ export type ParameterType =
|
|
|
30
30
|
| 'separator'
|
|
31
31
|
| 'options';
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* What the value of a `string` or `text` argument holds, for the check at
|
|
35
|
+
* story start and for tooling:
|
|
36
|
+
* - `markup`: markup the macro renders (`{button}`'s label): its markup
|
|
37
|
+
* is checked.
|
|
38
|
+
* - `text`: plain text the macro uses as written (`{checkbox}`'s label).
|
|
39
|
+
* - `passage`: a passage name (`{watch}`'s `goto`): the passage must exist.
|
|
40
|
+
* - `expression`, `statements`: code (`{watch}`'s condition and `run`): it
|
|
41
|
+
* is checked as code, and its variable references against the schema.
|
|
42
|
+
*
|
|
43
|
+
* Without it, the argument of a macro with `interpolate` holds `markup`,
|
|
44
|
+
* any other `text`.
|
|
45
|
+
*/
|
|
46
|
+
export type StringHolds =
|
|
47
|
+
| 'markup'
|
|
48
|
+
| 'text'
|
|
49
|
+
| 'passage'
|
|
50
|
+
| 'expression'
|
|
51
|
+
| 'statements';
|
|
52
|
+
|
|
33
53
|
export interface ParameterDef {
|
|
34
54
|
name: string;
|
|
35
55
|
required?: boolean;
|
|
36
56
|
description?: string;
|
|
37
57
|
/** How the argument is read: required, there is no default. */
|
|
38
58
|
type: ParameterType;
|
|
59
|
+
/** What a `string` or `text` argument holds (see StringHolds). */
|
|
60
|
+
holds?: StringHolds;
|
|
39
61
|
/** The options of an `options` parameter. */
|
|
40
62
|
parameters?: readonly ParameterDef[];
|
|
41
63
|
}
|
|
@@ -285,6 +307,9 @@ export interface LinkToken extends TokenSpan, Selectors {
|
|
|
285
307
|
type: 'link';
|
|
286
308
|
display: string;
|
|
287
309
|
target: string;
|
|
310
|
+
/** Where the target is written, from `targetStart` to `targetEnd`. */
|
|
311
|
+
targetStart: number;
|
|
312
|
+
targetEnd: number;
|
|
288
313
|
}
|
|
289
314
|
|
|
290
315
|
export interface MacroToken extends TokenSpan, Selectors {
|
|
@@ -465,8 +490,9 @@ export interface PassageReference {
|
|
|
465
490
|
* The passages the markup of `source` names, in source order: `[[…]]` links,
|
|
466
491
|
* the passage of `{goto}`, `{include}` and `{link}` (and of macros that
|
|
467
492
|
* declare a `passage` argument), the `goto` and `dialog` actions of
|
|
468
|
-
* `{watch}` and the
|
|
469
|
-
*
|
|
493
|
+
* `{watch}` (and the `string` and `text` arguments of macros that declare
|
|
494
|
+
* they hold a passage name) and the body of `{dialog}`. Malformed tags are
|
|
495
|
+
* skipped, so half-typed markup reads.
|
|
470
496
|
*/
|
|
471
497
|
export declare function collectPassageReferences(
|
|
472
498
|
source: string,
|