@rohal12/spindle 0.22.0 → 0.23.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rohal12/spindle",
3
- "version": "0.22.0",
3
+ "version": "0.23.1",
4
4
  "type": "module",
5
5
  "description": "A Preact-based story format for Twine 2.",
6
6
  "license": "Unlicense",
@@ -1,7 +1,7 @@
1
1
  import { useMemo, useEffect, useState } from 'preact/hooks';
2
2
  import { tokenize } from '../markup/tokenizer';
3
3
  import { buildAST } from '../markup/ast';
4
- import { renderNodes } from '../markup/render';
4
+ import { renderNodes, NobrContext } from '../markup/render';
5
5
  import { useStoryStore } from '../store';
6
6
  import type { Passage as PassageData } from '../parser';
7
7
  import { sourceLocationOf } from '../utils/source-location';
@@ -89,7 +89,9 @@ export function Passage({ passage, dataTransition }: PassageProps) {
89
89
  }
90
90
  }, [doneReady, donePassage?.content]);
91
91
 
92
- return (
92
+ const nobr = passage.tags.includes('nobr');
93
+
94
+ const inner = (
93
95
  <div
94
96
  class="passage"
95
97
  data-passage={passage.name}
@@ -102,4 +104,10 @@ export function Passage({ passage, dataTransition }: PassageProps) {
102
104
  {doneContent && <div hidden>{doneContent}</div>}
103
105
  </div>
104
106
  );
107
+
108
+ return nobr ? (
109
+ <NobrContext.Provider value={true}>{inner}</NobrContext.Provider>
110
+ ) : (
111
+ inner
112
+ );
105
113
  }
@@ -1,7 +1,7 @@
1
1
  import { useStoryStore } from '../store';
2
2
  import { tokenize } from '../markup/tokenizer';
3
3
  import { buildAST } from '../markup/ast';
4
- import { renderInlineNodes } from '../markup/render';
4
+ import { renderInlineNodes, NobrContext } from '../markup/render';
5
5
 
6
6
  const DEFAULT_MARKUP =
7
7
  '<header class="story-menubar">{story-title}{back}{forward}{restart}{quicksave}{quickload}{saves}{settings}</header>\n{passage}';
@@ -12,11 +12,17 @@ export function StoryInterface() {
12
12
  const overridePassage = storyData?.passages.get('StoryInterface');
13
13
  const markup =
14
14
  overridePassage !== undefined ? overridePassage.content : DEFAULT_MARKUP;
15
+ const nobr = overridePassage?.tags.includes('nobr') ?? false;
15
16
 
16
17
  try {
17
18
  const tokens = tokenize(markup);
18
19
  const ast = buildAST(tokens);
19
- return <>{renderInlineNodes(ast)}</>;
20
+ const rendered = <>{renderInlineNodes(ast)}</>;
21
+ return nobr ? (
22
+ <NobrContext.Provider value={true}>{rendered}</NobrContext.Provider>
23
+ ) : (
24
+ rendered
25
+ );
20
26
  } catch (err) {
21
27
  return (
22
28
  <span class="error">
@@ -8,6 +8,7 @@ import {
8
8
  import {
9
9
  LocalsValuesContext,
10
10
  LocalsUpdateContext,
11
+ NobrContext,
11
12
  renderNodes,
12
13
  } from '../../markup/render';
13
14
  import { defineMacro } from '../../define-macro';
@@ -76,10 +77,12 @@ function ForIteration({
76
77
  }, []);
77
78
  const updater = useMemo(() => ({ update, getValues }), [update, getValues]);
78
79
 
80
+ const nobr = useContext(NobrContext);
81
+
79
82
  return (
80
83
  <LocalsUpdateContext.Provider value={updater}>
81
84
  <LocalsValuesContext.Provider value={localState}>
82
- {renderNodes(children)}
85
+ {renderNodes(children, nobr ? { nobr: true } : undefined)}
83
86
  </LocalsValuesContext.Provider>
84
87
  </LocalsUpdateContext.Provider>
85
88
  );
@@ -1,6 +1,7 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { tokenize } from '../../markup/tokenizer';
3
3
  import { buildAST } from '../../markup/ast';
4
+ import { NobrContext } from '../../markup/render';
4
5
  import { defineMacro } from '../../define-macro';
5
6
 
6
7
  defineMacro({
@@ -33,10 +34,16 @@ defineMacro({
33
34
  );
34
35
  }
35
36
 
37
+ const nobr = passage.tags.includes('nobr');
36
38
  const tokens = tokenize(passage.content);
37
39
  const ast = buildAST(tokens);
38
- const content = inline ? ctx.renderInlineNodes(ast) : ctx.renderNodes(ast);
40
+ const content = inline
41
+ ? ctx.renderInlineNodes(ast)
42
+ : ctx.renderNodes(ast, nobr ? { nobr: true } : undefined);
39
43
 
44
+ if (nobr) {
45
+ return ctx.wrap(ctx.h(NobrContext.Provider, { value: true }, content));
46
+ }
40
47
  return ctx.wrap(content);
41
48
  },
42
49
  });
@@ -1,8 +1,15 @@
1
1
  import { defineMacro } from '../../define-macro';
2
+ import { NobrContext } from '../../markup/render';
2
3
 
3
4
  defineMacro({
4
5
  name: 'nobr',
5
6
  render({ children = [] }, ctx) {
6
- return ctx.wrap(ctx.renderNodes(children, { nobr: true }));
7
+ return ctx.wrap(
8
+ ctx.h(
9
+ NobrContext.Provider,
10
+ { value: true },
11
+ ctx.renderNodes(children, { nobr: true }),
12
+ ),
13
+ );
7
14
  },
8
15
  });
@@ -8,6 +8,7 @@ import {
8
8
  import {
9
9
  LocalsValuesContext,
10
10
  LocalsUpdateContext,
11
+ NobrContext,
11
12
  renderNodes,
12
13
  } from '../../markup/render';
13
14
  import { useMergedLocals } from '../../hooks/use-merged-locals';
@@ -79,6 +80,7 @@ function WidgetBody({
79
80
  parentValues: Record<string, unknown>;
80
81
  ownKeys: Record<string, unknown>;
81
82
  }) {
83
+ const nobr = useContext(NobrContext);
82
84
  const [localState, setLocalState] = useState<Record<string, unknown>>(() => ({
83
85
  ...parentValues,
84
86
  ...ownKeys,
@@ -96,7 +98,7 @@ function WidgetBody({
96
98
  return (
97
99
  <LocalsUpdateContext.Provider value={updater}>
98
100
  <LocalsValuesContext.Provider value={localState}>
99
- {renderNodes(body)}
101
+ {renderNodes(body, nobr ? { nobr: true } : undefined)}
100
102
  </LocalsValuesContext.Provider>
101
103
  </LocalsUpdateContext.Provider>
102
104
  );
@@ -108,10 +110,11 @@ export function WidgetInvocation({
108
110
  rawArgs,
109
111
  }: WidgetInvocationProps) {
110
112
  const parentValues = useContext(LocalsValuesContext);
113
+ const nobr = useContext(NobrContext);
111
114
  const [mergedVars, mergedTemps, mergedLocals] = useMergedLocals();
112
115
 
113
116
  if (params.length === 0 || !rawArgs) {
114
- return <>{renderNodes(body)}</>;
117
+ return <>{renderNodes(body, nobr ? { nobr: true } : undefined)}</>;
115
118
  }
116
119
 
117
120
  const argExprs = splitArgs(rawArgs);
@@ -13,9 +13,11 @@ import { useInterpolate } from './hooks/use-interpolate';
13
13
  import { useMergedLocals } from './hooks/use-merged-locals';
14
14
  import {
15
15
  LocalsUpdateContext,
16
- renderNodes,
16
+ NobrContext,
17
+ renderNodes as _renderNodes,
17
18
  renderInlineNodes,
18
19
  } from './markup/render';
20
+ import type { ASTNode } from './markup/ast';
19
21
  import { executeMutation } from './execute-mutation';
20
22
  import { evaluate } from './expression';
21
23
  import { useStoryStore } from './store';
@@ -56,7 +58,7 @@ export interface MacroContext {
56
58
  wrap: (content: ComponentChildren) => VNode<any>;
57
59
  useAction: (opts: UseActionOptions) => string;
58
60
  h: typeof h;
59
- renderNodes: typeof renderNodes;
61
+ renderNodes: typeof _renderNodes;
60
62
  renderInlineNodes: typeof renderInlineNodes;
61
63
  hooks: {
62
64
  useState: typeof useState;
@@ -102,6 +104,11 @@ export function defineMacro(config: MacroDefinition): void {
102
104
 
103
105
  // Always-on: cssClass + mutation
104
106
  const { update, getValues } = useContext(LocalsUpdateContext);
107
+ const nobr = useContext(NobrContext);
108
+ const renderNodes = nobr
109
+ ? (nodes: ASTNode[], options?: { nobr?: boolean }) =>
110
+ _renderNodes(nodes, { nobr: true, ...options })
111
+ : _renderNodes;
105
112
  const ctx: MacroContext = {
106
113
  collectText,
107
114
  sourceLocation: currentSourceLocation,
@@ -1,4 +1,5 @@
1
1
  import { createContext } from 'preact';
2
+ import { useContext } from 'preact/hooks';
2
3
  import { VarDisplay } from '../components/macros/VarDisplay';
3
4
  import { WidgetInvocation } from '../components/macros/WidgetInvocation';
4
5
  import { getWidget } from '../widgets/widget-registry';
@@ -21,6 +22,7 @@ const defaultUpdater: LocalsUpdater = {
21
22
 
22
23
  export const LocalsValuesContext = createContext<Record<string, unknown>>({});
23
24
  export const LocalsUpdateContext = createContext<LocalsUpdater>(defaultUpdater);
25
+ export const NobrContext = createContext(false);
24
26
 
25
27
  /**
26
28
  * Convert an HTML string (from micromark) to Preact VNodes,
@@ -80,6 +82,7 @@ function convertDomNode(
80
82
 
81
83
  function HtmlNodeRenderer({ node }: { node: HtmlNode }) {
82
84
  const resolve = useInterpolate();
85
+ const nobr = useContext(NobrContext);
83
86
  const attrs: Record<string, unknown> = {};
84
87
  for (const [k, v] of Object.entries(node.attributes)) {
85
88
  attrs[k] = resolve(v) ?? v;
@@ -87,7 +90,9 @@ function HtmlNodeRenderer({ node }: { node: HtmlNode }) {
87
90
  return h(
88
91
  node.tag,
89
92
  attrs,
90
- node.children.length > 0 ? renderNodes(node.children) : undefined,
93
+ node.children.length > 0
94
+ ? renderNodes(node.children, nobr ? { nobr: true } : undefined)
95
+ : undefined,
91
96
  );
92
97
  }
93
98