squiffy-runtime 6.0.0-alpha.4 → 6.0.0-alpha.5
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
|
@@ -2,53 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
exports[`"Hello world" script should run 1`] = `
|
|
4
4
|
"
|
|
5
|
-
<div id="squiffy-section-1"><div><p>Hello world</p></div></div>"
|
|
5
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Hello world</p></div></div></div>"
|
|
6
6
|
`;
|
|
7
7
|
|
|
8
8
|
exports[`Click a passage link 1`] = `
|
|
9
9
|
"
|
|
10
|
-
<div id="squiffy-section-1"><div><h1>Squiffy Test</h1>
|
|
10
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="Introduction"><div class="squiffy-output-block"><div data-source="[[Introduction]]"><h1>Squiffy Test</h1>
|
|
11
11
|
<p>This is <a href="http://textadventures.co.uk">a website link</a>.</p>
|
|
12
12
|
<p>This should be <a class="squiffy-link link-passage" data-passage="passage" role="link" tabindex="0">a link to a passage</a>. Here's <a class="squiffy-link link-passage" data-passage="passage2" role="link" tabindex="0">another one</a>.</p>
|
|
13
13
|
<p>You don't need to specify a name - for example, this <a class="squiffy-link link-passage" data-passage="link" role="link" tabindex="0">link</a> and this <a class="squiffy-link link-section" data-section="section" role="link" tabindex="0">section</a>.</p>
|
|
14
14
|
<p>And this goes to the <a class="squiffy-link link-section" data-section="section2" role="link" tabindex="0">next section</a>.</p>
|
|
15
15
|
<p>This line has links to <a class="squiffy-link link-section" data-section="section 3" role="link" tabindex="0">section 3</a> and <a class="squiffy-link link-section" data-section="section four" role="link" tabindex="0">section 4</a>.</p>
|
|
16
16
|
<p>This line has links to <a class="squiffy-link link-passage" data-passage="passage 3" role="link" tabindex="0">passage 3</a> and <a class="squiffy-link link-passage" data-passage="passage four" role="link" tabindex="0">passage 4</a>.</p>
|
|
17
|
-
<p>Oh look - <a class="squiffy-link link-passage" data-passage="it's a passage with an apostrophe" role="link" tabindex="0">it's a passage with an apostrophe</a>.</p></div></div>"
|
|
17
|
+
<p>Oh look - <a class="squiffy-link link-passage" data-passage="it's a passage with an apostrophe" role="link" tabindex="0">it's a passage with an apostrophe</a>.</p></div></div></div>"
|
|
18
18
|
`;
|
|
19
19
|
|
|
20
20
|
exports[`Click a passage link 2`] = `
|
|
21
21
|
"
|
|
22
|
-
<div id="squiffy-section-1"><div><h1>Squiffy Test</h1>
|
|
22
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="Introduction"><div class="squiffy-output-block"><div data-source="[[Introduction]]"><h1>Squiffy Test</h1>
|
|
23
23
|
<p>This is <a href="http://textadventures.co.uk">a website link</a>.</p>
|
|
24
24
|
<p>This should be <a class="squiffy-link link-passage disabled" data-passage="passage" role="link" tabindex="-1">a link to a passage</a>. Here's <a class="squiffy-link link-passage" data-passage="passage2" role="link" tabindex="0">another one</a>.</p>
|
|
25
25
|
<p>You don't need to specify a name - for example, this <a class="squiffy-link link-passage" data-passage="link" role="link" tabindex="0">link</a> and this <a class="squiffy-link link-section" data-section="section" role="link" tabindex="0">section</a>.</p>
|
|
26
26
|
<p>And this goes to the <a class="squiffy-link link-section" data-section="section2" role="link" tabindex="0">next section</a>.</p>
|
|
27
27
|
<p>This line has links to <a class="squiffy-link link-section" data-section="section 3" role="link" tabindex="0">section 3</a> and <a class="squiffy-link link-section" data-section="section four" role="link" tabindex="0">section 4</a>.</p>
|
|
28
28
|
<p>This line has links to <a class="squiffy-link link-passage" data-passage="passage 3" role="link" tabindex="0">passage 3</a> and <a class="squiffy-link link-passage" data-passage="passage four" role="link" tabindex="0">passage 4</a>.</p>
|
|
29
|
-
<p>Oh look - <a class="squiffy-link link-passage" data-passage="it's a passage with an apostrophe" role="link" tabindex="0">it's a passage with an apostrophe</a>.</p></div><
|
|
29
|
+
<p>Oh look - <a class="squiffy-link link-passage" data-passage="it's a passage with an apostrophe" role="link" tabindex="0">it's a passage with an apostrophe</a>.</p></div></div><div class="squiffy-output-block"><div data-source="[[Introduction]][passage]"><p>Here's some text for the passage.</p></div></div></div>"
|
|
30
30
|
`;
|
|
31
31
|
|
|
32
32
|
exports[`Click a section link 1`] = `
|
|
33
33
|
"
|
|
34
|
-
<div id="squiffy-section-1"><div><h1>Squiffy Test</h1>
|
|
34
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="Introduction"><div class="squiffy-output-block"><div data-source="[[Introduction]]"><h1>Squiffy Test</h1>
|
|
35
35
|
<p>This is <a href="http://textadventures.co.uk">a website link</a>.</p>
|
|
36
36
|
<p>This should be <a class="squiffy-link link-passage" data-passage="passage" role="link" tabindex="0">a link to a passage</a>. Here's <a class="squiffy-link link-passage" data-passage="passage2" role="link" tabindex="0">another one</a>.</p>
|
|
37
37
|
<p>You don't need to specify a name - for example, this <a class="squiffy-link link-passage" data-passage="link" role="link" tabindex="0">link</a> and this <a class="squiffy-link link-section" data-section="section" role="link" tabindex="0">section</a>.</p>
|
|
38
38
|
<p>And this goes to the <a class="squiffy-link link-section" data-section="section2" role="link" tabindex="0">next section</a>.</p>
|
|
39
39
|
<p>This line has links to <a class="squiffy-link link-section" data-section="section 3" role="link" tabindex="0">section 3</a> and <a class="squiffy-link link-section" data-section="section four" role="link" tabindex="0">section 4</a>.</p>
|
|
40
40
|
<p>This line has links to <a class="squiffy-link link-passage" data-passage="passage 3" role="link" tabindex="0">passage 3</a> and <a class="squiffy-link link-passage" data-passage="passage four" role="link" tabindex="0">passage 4</a>.</p>
|
|
41
|
-
<p>Oh look - <a class="squiffy-link link-passage" data-passage="it's a passage with an apostrophe" role="link" tabindex="0">it's a passage with an apostrophe</a>.</p></div></div>"
|
|
41
|
+
<p>Oh look - <a class="squiffy-link link-passage" data-passage="it's a passage with an apostrophe" role="link" tabindex="0">it's a passage with an apostrophe</a>.</p></div></div></div>"
|
|
42
42
|
`;
|
|
43
43
|
|
|
44
44
|
exports[`Click a section link 2`] = `
|
|
45
45
|
"
|
|
46
|
-
<div id="squiffy-section-1"><div><h1>Squiffy Test</h1>
|
|
46
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="Introduction"><div class="squiffy-output-block"><div data-source="[[Introduction]]"><h1>Squiffy Test</h1>
|
|
47
47
|
<p>This is <a href="http://textadventures.co.uk">a website link</a>.</p>
|
|
48
48
|
<p>This should be <a class="squiffy-link link-passage disabled" data-passage="passage" role="link" tabindex="-1">a link to a passage</a>. Here's <a class="squiffy-link link-passage disabled" data-passage="passage2" role="link" tabindex="-1">another one</a>.</p>
|
|
49
49
|
<p>You don't need to specify a name - for example, this <a class="squiffy-link link-passage disabled" data-passage="link" role="link" tabindex="-1">link</a> and this <a class="squiffy-link link-section disabled" data-section="section" role="link" tabindex="-1">section</a>.</p>
|
|
50
50
|
<p>And this goes to the <a class="squiffy-link link-section disabled" data-section="section2" role="link" tabindex="-1">next section</a>.</p>
|
|
51
51
|
<p>This line has links to <a class="squiffy-link link-section disabled" data-section="section 3" role="link" tabindex="-1">section 3</a> and <a class="squiffy-link link-section disabled" data-section="section four" role="link" tabindex="-1">section 4</a>.</p>
|
|
52
52
|
<p>This line has links to <a class="squiffy-link link-passage disabled" data-passage="passage 3" role="link" tabindex="-1">passage 3</a> and <a class="squiffy-link link-passage disabled" data-passage="passage four" role="link" tabindex="-1">passage 4</a>.</p>
|
|
53
|
-
<p>Oh look - <a class="squiffy-link link-passage disabled" data-passage="it's a passage with an apostrophe" role="link" tabindex="-1">it's a passage with an apostrophe</a>.</p></div
|
|
53
|
+
<p>Oh look - <a class="squiffy-link link-passage disabled" data-passage="it's a passage with an apostrophe" role="link" tabindex="-1">it's a passage with an apostrophe</a>.</p></div></div></div><div class="squiffy-output-section" id="squiffy-section-2" data-section="section 3"><div class="squiffy-output-block"><div data-source="[[section 3]]"><p>Another section is here.</p></div></div></div>"
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
exports[`Delete passage 1`] = `
|
|
57
|
+
"
|
|
58
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Click this: <a class="squiffy-link link-passage disabled" data-passage="a" role="link" tabindex="-1">a</a></p></div></div><div class="squiffy-output-block"><div data-source="[[_default]][a]"><p>New passage</p></div></div></div>"
|
|
59
|
+
`;
|
|
60
|
+
|
|
61
|
+
exports[`Delete passage 2`] = `
|
|
62
|
+
"
|
|
63
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Click this: <a class="squiffy-link link-passage disabled" data-passage="a" role="link" tabindex="-1">a</a></p></div></div><div class="squiffy-output-block"></div></div>"
|
|
64
|
+
`;
|
|
65
|
+
|
|
66
|
+
exports[`Delete section 1`] = `
|
|
67
|
+
"
|
|
68
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Click this: <a class="squiffy-link link-section disabled" data-section="a" role="link" tabindex="-1">a</a></p></div></div></div><div class="squiffy-output-section" id="squiffy-section-2" data-section="a"><div class="squiffy-output-block"><div data-source="[[a]]"><p>New section</p></div></div></div>"
|
|
69
|
+
`;
|
|
70
|
+
|
|
71
|
+
exports[`Delete section 2`] = `
|
|
72
|
+
"
|
|
73
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Click this: <a class="squiffy-link link-section disabled" data-section="a" role="link" tabindex="-1">a</a></p></div></div></div><div class="squiffy-output-section" id="squiffy-section-2" data-section="a"><div class="squiffy-output-block"></div></div>"
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
exports[`Update default section output 1`] = `
|
|
77
|
+
"
|
|
78
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Hello world</p></div></div></div>"
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
exports[`Update default section output 2`] = `
|
|
82
|
+
"
|
|
83
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Updated content</p></div></div></div>"
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
exports[`Update passage output 1`] = `
|
|
87
|
+
"
|
|
88
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Click this: <a class="squiffy-link link-passage disabled" data-passage="a" role="link" tabindex="-1">a</a></p></div></div><div class="squiffy-output-block"><div data-source="[[_default]][a]"><p>Passage a content</p></div></div></div>"
|
|
89
|
+
`;
|
|
90
|
+
|
|
91
|
+
exports[`Update passage output 2`] = `
|
|
92
|
+
"
|
|
93
|
+
<div class="squiffy-output-section" id="squiffy-section-1" data-section="_default"><div class="squiffy-output-block"><div data-source="[[_default]]"><p>Click this: <a class="squiffy-link link-passage disabled" data-passage="a" role="link" tabindex="-1">a</a></p></div></div><div class="squiffy-output-block"><div data-source="[[_default]][a]"><p>Updated passage content</p></div></div></div>"
|
|
54
94
|
`;
|
|
@@ -2,7 +2,7 @@ import { expect, test, beforeEach, afterEach } from 'vitest';
|
|
|
2
2
|
import fs from 'fs/promises';
|
|
3
3
|
import globalJsdom from 'global-jsdom';
|
|
4
4
|
import { init } from './squiffy.runtime.js';
|
|
5
|
-
import { compile } from 'squiffy-compiler';
|
|
5
|
+
import { compile as squiffyCompile } from 'squiffy-compiler';
|
|
6
6
|
|
|
7
7
|
const html = `
|
|
8
8
|
<!DOCTYPE html>
|
|
@@ -18,15 +18,8 @@ const html = `
|
|
|
18
18
|
</html>
|
|
19
19
|
`;
|
|
20
20
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const element = document.getElementById('squiffy');
|
|
24
|
-
|
|
25
|
-
if (!element) {
|
|
26
|
-
throw new Error('Element not found');
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const compileResult = await compile({
|
|
21
|
+
const compile = async (script: string) => {
|
|
22
|
+
const compileResult = await squiffyCompile({
|
|
30
23
|
scriptBaseFilename: "filename.squiffy", // TODO: This shouldn't be required
|
|
31
24
|
script: script,
|
|
32
25
|
});
|
|
@@ -38,12 +31,27 @@ const initScript = async (script: string) => {
|
|
|
38
31
|
const story = compileResult.output.story;
|
|
39
32
|
const js = compileResult.output.js.map(jsLines => new Function('squiffy', 'get', 'set', jsLines.join('\n')));
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
element: element,
|
|
34
|
+
return {
|
|
43
35
|
story: {
|
|
44
36
|
js: js as any,
|
|
45
37
|
...story,
|
|
46
38
|
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const initScript = async (script: string) => {
|
|
43
|
+
globalJsdom(html);
|
|
44
|
+
const element = document.getElementById('squiffy');
|
|
45
|
+
|
|
46
|
+
if (!element) {
|
|
47
|
+
throw new Error('Element not found');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const compileResult = await compile(script);
|
|
51
|
+
|
|
52
|
+
const squiffyApi = init({
|
|
53
|
+
element: element,
|
|
54
|
+
story: compileResult.story,
|
|
47
55
|
});
|
|
48
56
|
|
|
49
57
|
return {
|
|
@@ -89,8 +97,8 @@ test('Click a section link', async () => {
|
|
|
89
97
|
const linkToPassage = findLink(element, 'passage', 'a link to a passage');
|
|
90
98
|
const section3Link = findLink(element, 'section', 'section 3');
|
|
91
99
|
|
|
92
|
-
expect(linkToPassage).
|
|
93
|
-
expect(section3Link).
|
|
100
|
+
expect(linkToPassage).not.toBeNull();
|
|
101
|
+
expect(section3Link).not.toBeNull();
|
|
94
102
|
expect(linkToPassage.classList).not.toContain('disabled');
|
|
95
103
|
expect(section3Link.classList).not.toContain('disabled');
|
|
96
104
|
|
|
@@ -110,8 +118,8 @@ test('Click a passage link', async () => {
|
|
|
110
118
|
const linkToPassage = findLink(element, 'passage', 'a link to a passage');
|
|
111
119
|
const section3Link = findLink(element, 'section', 'section 3');
|
|
112
120
|
|
|
113
|
-
expect(linkToPassage).
|
|
114
|
-
expect(section3Link).
|
|
121
|
+
expect(linkToPassage).not.toBeNull();
|
|
122
|
+
expect(section3Link).not.toBeNull();
|
|
115
123
|
expect(linkToPassage.classList).not.toContain('disabled');
|
|
116
124
|
expect(section3Link.classList).not.toContain('disabled');
|
|
117
125
|
|
|
@@ -147,7 +155,7 @@ test('Run JavaScript functions', async () => {
|
|
|
147
155
|
|
|
148
156
|
const clickContinue = () => {
|
|
149
157
|
const continueLink = findLink(element, 'section', 'Continue...', true);
|
|
150
|
-
expect(continueLink).
|
|
158
|
+
expect(continueLink).not.toBeNull();
|
|
151
159
|
squiffyApi.clickLink(continueLink);
|
|
152
160
|
};
|
|
153
161
|
|
|
@@ -170,4 +178,109 @@ test('Run JavaScript functions', async () => {
|
|
|
170
178
|
|
|
171
179
|
clickContinue();
|
|
172
180
|
expect(getTestOutput()).toBe('In other section');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
function getSectionContent(element: HTMLElement, section: string) {
|
|
184
|
+
return element.querySelector(`[data-source='[[${section}]]'] p`)?.textContent || null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getPassageContent(element: HTMLElement, section: string, passage: string) {
|
|
188
|
+
return element.querySelector(`[data-source='[[${section}]][${passage}]'] p`)?.textContent || null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
test('Update default section output', async () => {
|
|
192
|
+
const { squiffyApi, element } = await initScript("Hello world");
|
|
193
|
+
let defaultOutput = getSectionContent(element, '_default');
|
|
194
|
+
expect(defaultOutput).toBe('Hello world');
|
|
195
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
196
|
+
|
|
197
|
+
const updated = await compile("Updated content");
|
|
198
|
+
squiffyApi.update(updated.story);
|
|
199
|
+
defaultOutput = getSectionContent(element, '_default');
|
|
200
|
+
expect(defaultOutput).toBe('Updated content');
|
|
201
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('Update passage output', async () => {
|
|
205
|
+
const { squiffyApi, element } = await initScript(`Click this: [a]
|
|
206
|
+
|
|
207
|
+
[a]:
|
|
208
|
+
Passage a content`);
|
|
209
|
+
|
|
210
|
+
const link = findLink(element, 'passage', 'a');
|
|
211
|
+
squiffyApi.clickLink(link);
|
|
212
|
+
|
|
213
|
+
let defaultOutput = getSectionContent(element, '_default');
|
|
214
|
+
expect(defaultOutput).toBe('Click this: a');
|
|
215
|
+
let passageOutput = getPassageContent(element, '_default', 'a');
|
|
216
|
+
expect(passageOutput).toBe('Passage a content');
|
|
217
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
218
|
+
|
|
219
|
+
const updated = await compile(`Click this: [a]
|
|
220
|
+
|
|
221
|
+
[a]:
|
|
222
|
+
Updated passage content`);
|
|
223
|
+
|
|
224
|
+
squiffyApi.update(updated.story);
|
|
225
|
+
|
|
226
|
+
defaultOutput = getSectionContent(element, '_default');
|
|
227
|
+
expect(defaultOutput).toBe('Click this: a');
|
|
228
|
+
|
|
229
|
+
passageOutput = getPassageContent(element, '_default', 'a');
|
|
230
|
+
expect(passageOutput).toBe('Updated passage content');
|
|
231
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test('Delete section', async () => {
|
|
235
|
+
const { squiffyApi, element } = await initScript(`Click this: [[a]]
|
|
236
|
+
|
|
237
|
+
[[a]]:
|
|
238
|
+
New section`);
|
|
239
|
+
|
|
240
|
+
const link = findLink(element, 'section', 'a');
|
|
241
|
+
squiffyApi.clickLink(link);
|
|
242
|
+
|
|
243
|
+
let defaultOutput = getSectionContent(element, '_default');
|
|
244
|
+
expect(defaultOutput).toBe('Click this: a');
|
|
245
|
+
let sectionOutput = getSectionContent(element, 'a');
|
|
246
|
+
expect(sectionOutput).toBe('New section');
|
|
247
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
248
|
+
|
|
249
|
+
const updated = await compile(`Click this: [[a]]`);
|
|
250
|
+
|
|
251
|
+
squiffyApi.update(updated.story);
|
|
252
|
+
|
|
253
|
+
defaultOutput = getSectionContent(element, '_default');
|
|
254
|
+
expect(defaultOutput).toBe('Click this: a');
|
|
255
|
+
sectionOutput = getSectionContent(element, 'a');
|
|
256
|
+
expect(sectionOutput).toBeNull();
|
|
257
|
+
|
|
258
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test('Delete passage', async () => {
|
|
262
|
+
const { squiffyApi, element } = await initScript(`Click this: [a]
|
|
263
|
+
|
|
264
|
+
[a]:
|
|
265
|
+
New passage`);
|
|
266
|
+
|
|
267
|
+
const link = findLink(element, 'passage', 'a');
|
|
268
|
+
squiffyApi.clickLink(link);
|
|
269
|
+
|
|
270
|
+
let defaultOutput = getSectionContent(element, '_default');
|
|
271
|
+
expect(defaultOutput).toBe('Click this: a');
|
|
272
|
+
let passageOutput = getPassageContent(element, '_default', 'a');
|
|
273
|
+
expect(passageOutput).toBe('New passage');
|
|
274
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
275
|
+
|
|
276
|
+
const updated = await compile(`Click this: [a]`);
|
|
277
|
+
|
|
278
|
+
squiffyApi.update(updated.story);
|
|
279
|
+
|
|
280
|
+
defaultOutput = getSectionContent(element, '_default');
|
|
281
|
+
expect(defaultOutput).toBe('Click this: a');
|
|
282
|
+
passageOutput = getPassageContent(element, '_default', 'a');
|
|
283
|
+
expect(passageOutput).toBeNull();
|
|
284
|
+
|
|
285
|
+
expect(element.innerHTML).toMatchSnapshot();
|
|
173
286
|
});
|
package/src/squiffy.runtime.ts
CHANGED
|
@@ -17,6 +17,7 @@ interface SquiffyApi {
|
|
|
17
17
|
get: (attribute: string) => any;
|
|
18
18
|
set: (attribute: string, value: any) => void;
|
|
19
19
|
clickLink: (link: HTMLElement) => void;
|
|
20
|
+
update: (story: Story) => void;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
// Previous versions of Squiffy had "squiffy", "get" and "set" as globals - we now pass these directly into JS functions.
|
|
@@ -63,6 +64,7 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
63
64
|
let story: Story;
|
|
64
65
|
let currentSection: Section;
|
|
65
66
|
let currentSectionElement: HTMLElement;
|
|
67
|
+
let currentBlockOutputElement: HTMLElement;
|
|
66
68
|
let scrollPosition = 0;
|
|
67
69
|
let outputElement: HTMLElement;
|
|
68
70
|
let settings: SquiffySettings;
|
|
@@ -103,7 +105,7 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
103
105
|
set('_turncount', get('_turncount') + 1);
|
|
104
106
|
passage = processLink(passage);
|
|
105
107
|
if (passage) {
|
|
106
|
-
|
|
108
|
+
newBlockOutputElement();
|
|
107
109
|
showPassage(passage);
|
|
108
110
|
}
|
|
109
111
|
const turnPassage = '@' + get('_turncount');
|
|
@@ -117,7 +119,6 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
else if (section) {
|
|
120
|
-
currentSectionElement?.appendChild(document.createElement('hr'));
|
|
121
122
|
disableLink(link);
|
|
122
123
|
section = processLink(section);
|
|
123
124
|
if (section) {
|
|
@@ -270,23 +271,23 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
270
271
|
labelElement.classList.add('fade-out');
|
|
271
272
|
}
|
|
272
273
|
|
|
273
|
-
function go(
|
|
274
|
+
function go(sectionName: string) {
|
|
274
275
|
set('_transition', null);
|
|
275
|
-
newSection();
|
|
276
|
-
currentSection = story.sections[
|
|
276
|
+
newSection(sectionName);
|
|
277
|
+
currentSection = story.sections[sectionName];
|
|
277
278
|
if (!currentSection) return;
|
|
278
|
-
set('_section',
|
|
279
|
-
setSeen(
|
|
279
|
+
set('_section', sectionName);
|
|
280
|
+
setSeen(sectionName);
|
|
280
281
|
const master = story.sections[''];
|
|
281
282
|
if (master) {
|
|
282
283
|
run(master);
|
|
283
|
-
ui.write(master.text || '');
|
|
284
|
+
ui.write(master.text || '', "[[]]");
|
|
284
285
|
}
|
|
285
286
|
run(currentSection);
|
|
286
287
|
// The JS might have changed which section we're in
|
|
287
|
-
if (get('_section') ==
|
|
288
|
+
if (get('_section') == sectionName) {
|
|
288
289
|
set('_turncount', 0);
|
|
289
|
-
ui.write(currentSection.text || '');
|
|
290
|
+
ui.write(currentSection.text || '', `[[${sectionName}]]`);
|
|
290
291
|
save();
|
|
291
292
|
}
|
|
292
293
|
}
|
|
@@ -323,16 +324,16 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
323
324
|
const masterPassage = masterSection.passages[''];
|
|
324
325
|
if (masterPassage) {
|
|
325
326
|
run(masterPassage);
|
|
326
|
-
ui.write(masterPassage.text || '');
|
|
327
|
+
ui.write(masterPassage.text || '', `[[]][]`);
|
|
327
328
|
}
|
|
328
329
|
}
|
|
329
330
|
const master = currentSection.passages && currentSection.passages[''];
|
|
330
331
|
if (master) {
|
|
331
332
|
run(master);
|
|
332
|
-
ui.write(master.text || '');
|
|
333
|
+
ui.write(master.text || '', `[[${get("_section")}]][]`);
|
|
333
334
|
}
|
|
334
335
|
run(passage);
|
|
335
|
-
ui.write(passage.text || '');
|
|
336
|
+
ui.write(passage.text || '', `[[${get("_section")}]][${passageName}]`);
|
|
336
337
|
save();
|
|
337
338
|
}
|
|
338
339
|
|
|
@@ -376,9 +377,10 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
376
377
|
const output = get('_output');
|
|
377
378
|
if (!output) return false;
|
|
378
379
|
outputElement.innerHTML = output;
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
380
|
+
|
|
381
|
+
currentSectionElement = outputElement.querySelector('.squiffy-output-section:last-child');
|
|
382
|
+
currentBlockOutputElement = outputElement.querySelector('.squiffy-output-block:last-child');
|
|
383
|
+
|
|
382
384
|
currentSection = story.sections[get('_section')];
|
|
383
385
|
const transition = get('_transition');
|
|
384
386
|
if (transition) {
|
|
@@ -401,8 +403,14 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
401
403
|
if (!seenSections) return false;
|
|
402
404
|
return (seenSections.indexOf(sectionName) > -1);
|
|
403
405
|
}
|
|
406
|
+
|
|
407
|
+
function newBlockOutputElement() {
|
|
408
|
+
currentBlockOutputElement = document.createElement('div');
|
|
409
|
+
currentBlockOutputElement.classList.add('squiffy-output-block');
|
|
410
|
+
currentSectionElement?.appendChild(currentBlockOutputElement);
|
|
411
|
+
}
|
|
404
412
|
|
|
405
|
-
function newSection() {
|
|
413
|
+
function newSection(sectionName: string | null) {
|
|
406
414
|
if (currentSectionElement) {
|
|
407
415
|
disableLinks(currentSectionElement.querySelectorAll('.squiffy-link'));
|
|
408
416
|
currentSectionElement.querySelectorAll('input').forEach(el => {
|
|
@@ -429,26 +437,32 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
429
437
|
const id = 'squiffy-section-' + sectionCount;
|
|
430
438
|
|
|
431
439
|
currentSectionElement = document.createElement('div');
|
|
440
|
+
currentSectionElement.classList.add('squiffy-output-section');
|
|
432
441
|
currentSectionElement.id = id;
|
|
442
|
+
if (sectionName) {
|
|
443
|
+
currentSectionElement.setAttribute('data-section', `${sectionName}`);
|
|
444
|
+
}
|
|
433
445
|
outputElement.appendChild(currentSectionElement);
|
|
434
|
-
|
|
435
|
-
set('_output-section', id);
|
|
446
|
+
newBlockOutputElement();
|
|
436
447
|
}
|
|
437
448
|
|
|
438
449
|
const ui = {
|
|
439
|
-
write: (text: string) => {
|
|
440
|
-
if (!
|
|
450
|
+
write: (text: string, source: string) => {
|
|
451
|
+
if (!currentBlockOutputElement) return;
|
|
441
452
|
scrollPosition = outputElement.scrollHeight;
|
|
442
453
|
|
|
443
454
|
const div = document.createElement('div');
|
|
444
|
-
|
|
455
|
+
if (source) {
|
|
456
|
+
div.setAttribute('data-source', source);
|
|
457
|
+
}
|
|
458
|
+
currentBlockOutputElement.appendChild(div);
|
|
445
459
|
div.innerHTML = ui.processText(text);
|
|
446
460
|
|
|
447
461
|
ui.scrollToEnd();
|
|
448
462
|
},
|
|
449
463
|
clearScreen: () => {
|
|
450
464
|
outputElement.innerHTML = '';
|
|
451
|
-
newSection();
|
|
465
|
+
newSection(null);
|
|
452
466
|
},
|
|
453
467
|
scrollToEnd: () => {
|
|
454
468
|
if (settings.scroll === 'element') {
|
|
@@ -661,6 +675,60 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
661
675
|
return [next, remaining];
|
|
662
676
|
}
|
|
663
677
|
|
|
678
|
+
function getSectionContent(section: string) {
|
|
679
|
+
return outputElement.querySelectorAll(`[data-source='[[${section}]]']`);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function getPassageContent(section: string, passage: string) {
|
|
683
|
+
return outputElement.querySelectorAll(`[data-source='[[${section}]][${passage}]']`);
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function update(newStory: Story) {
|
|
687
|
+
// TODO: Re-disable clicked links after update
|
|
688
|
+
|
|
689
|
+
for (const existingSection of Object.keys(story.sections)) {
|
|
690
|
+
const elements = getSectionContent(existingSection);
|
|
691
|
+
if (elements.length) {
|
|
692
|
+
const newSection = newStory.sections[existingSection];
|
|
693
|
+
if (!newSection) {
|
|
694
|
+
// section has been deleted
|
|
695
|
+
for (const element of elements) {
|
|
696
|
+
element.remove();
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
else if (newSection.text && newSection.text != story.sections[existingSection].text) {
|
|
700
|
+
// section has been updated
|
|
701
|
+
for (const element of elements) {
|
|
702
|
+
element.innerHTML = ui.processText(newSection.text);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
if (!story.sections[existingSection].passages) continue;
|
|
708
|
+
|
|
709
|
+
for (const existingPassage of Object.keys(story.sections[existingSection].passages)) {
|
|
710
|
+
const elements = getPassageContent(existingSection, existingPassage);
|
|
711
|
+
if (!elements.length) continue;
|
|
712
|
+
|
|
713
|
+
const newPassage = newStory.sections[existingSection]?.passages && newStory.sections[existingSection]?.passages[existingPassage];
|
|
714
|
+
if (!newPassage) {
|
|
715
|
+
// passage has been deleted
|
|
716
|
+
for (const element of elements) {
|
|
717
|
+
element.remove();
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
else if (newPassage.text && newPassage.text != story.sections[existingSection].passages[existingPassage].text) {
|
|
721
|
+
// passage has been updated
|
|
722
|
+
for (const element of elements) {
|
|
723
|
+
element.innerHTML = ui.processText(newPassage.text);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
story = newStory;
|
|
730
|
+
}
|
|
731
|
+
|
|
664
732
|
outputElement = options.element;
|
|
665
733
|
story = options.story;
|
|
666
734
|
|
|
@@ -691,6 +759,7 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
691
759
|
restart: restart,
|
|
692
760
|
get: get,
|
|
693
761
|
set: set,
|
|
694
|
-
clickLink: handleLink
|
|
762
|
+
clickLink: handleLink,
|
|
763
|
+
update: update,
|
|
695
764
|
};
|
|
696
765
|
};
|