@rohal12/spindle 0.59.10 → 0.59.12

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/src/triggers.ts CHANGED
@@ -251,7 +251,7 @@ export function checkTriggersOnNavigation(): void {
251
251
 
252
252
  /**
253
253
  * Re-evaluate watchers whenever a namespace their conditions can read
254
- * ($variables, _temporary, %transient) changes. Navigation is left to the
254
+ * ($variables, _temporary, %transient) or the render counts change. Navigation is left to the
255
255
  * store: navigate() checks watchers once the new moment is complete
256
256
  * (checkTriggersOnNavigation), while history traversal and loads
257
257
  * reinitialize watcher state instead of firing.
@@ -269,7 +269,9 @@ export function connectTriggersToStore(): () => void {
269
269
  if (
270
270
  state.variables === before.variables &&
271
271
  state.temporary === before.temporary &&
272
- state.transient === before.transient
272
+ state.transient === before.transient &&
273
+ // hasRendered() / rendered() read the counts an {include} bumps
274
+ state.renderCounts === before.renderCounts
273
275
  ) {
274
276
  return;
275
277
  }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Counts the edits a reader made through a control bound to a story
3
+ * variable (`{textbox}`, `{checkbox}`, ...). {for} tells these apart from a
4
+ * list that is replaced: typing into a control inside an iteration changes
5
+ * its item, but must not remount the iteration and drop the control's focus.
6
+ */
7
+ let version = 0;
8
+
9
+ export function noteControlEdit(): void {
10
+ version++;
11
+ }
12
+
13
+ export function controlEditVersion(): number {
14
+ return version;
15
+ }
@@ -0,0 +1,44 @@
1
+ import { registerWidget } from './widget-registry';
2
+ import { astContainsChildren } from './ast-scanner';
3
+ import { registerBlockMacro, type ASTNode } from '../markup/ast';
4
+ import { errorMessage } from '../utils/error-message';
5
+ import { parseWidgetDef, type WidgetDef } from './widget-def';
6
+
7
+ /**
8
+ * Register the widget a definition declares, with its body. Widgets whose
9
+ * body renders {@children} take a closing tag, so they are registered as
10
+ * block macros too: passages parsed later nest their content. A parameter
11
+ * that no namespace can hold throws (see registerWidget), registering
12
+ * nothing.
13
+ */
14
+ export function registerWidgetDef(
15
+ { name, params }: WidgetDef,
16
+ body: ASTNode[],
17
+ ): void {
18
+ const isBlock = astContainsChildren(body);
19
+ registerWidget(name, body, params, isBlock);
20
+ if (isBlock) registerBlockMacro(name);
21
+ }
22
+
23
+ /**
24
+ * Register the widgets `nodes` (a passage's markup) define at its top level,
25
+ * as the {widget} macro does when it renders. A widget that fails to register
26
+ * is reported; the others still register.
27
+ */
28
+ export function registerWidgetDefinitions(
29
+ nodes: ASTNode[],
30
+ passageName: string,
31
+ ): void {
32
+ for (const node of nodes) {
33
+ if (node.type === 'macro' && node.name === 'widget' && node.rawArgs) {
34
+ const def = parseWidgetDef(node.rawArgs);
35
+ try {
36
+ registerWidgetDef(def, node.children as ASTNode[]);
37
+ } catch (err) {
38
+ console.error(
39
+ `spindle: widget "${def.name}" in passage "${passageName}" was not registered: ${errorMessage(err)}`,
40
+ );
41
+ }
42
+ }
43
+ }
44
+ }