squiffy-runtime 6.0.0-alpha.7 → 6.0.0-alpha.9
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.
|
@@ -14,7 +14,7 @@ export interface SquiffyApi {
|
|
|
14
14
|
restart: () => void;
|
|
15
15
|
get: (attribute: string) => any;
|
|
16
16
|
set: (attribute: string, value: any) => void;
|
|
17
|
-
clickLink: (link: HTMLElement) =>
|
|
17
|
+
clickLink: (link: HTMLElement) => boolean;
|
|
18
18
|
update: (story: Story) => void;
|
|
19
19
|
}
|
|
20
20
|
interface SquiffyJsFunctionApi {
|
package/dist/squiffy.runtime.js
CHANGED
|
@@ -31,8 +31,11 @@ export const init = (options) => {
|
|
|
31
31
|
return JSON.parse(result);
|
|
32
32
|
}
|
|
33
33
|
function handleLink(link) {
|
|
34
|
+
const outputSection = link.closest('.squiffy-output-section');
|
|
35
|
+
if (outputSection !== currentSectionElement)
|
|
36
|
+
return false;
|
|
34
37
|
if (link.classList.contains('disabled'))
|
|
35
|
-
return;
|
|
38
|
+
return false;
|
|
36
39
|
let passage = link.getAttribute('data-passage');
|
|
37
40
|
let section = link.getAttribute('data-section');
|
|
38
41
|
const rotateAttr = link.getAttribute('data-rotate');
|
|
@@ -55,15 +58,16 @@ export const init = (options) => {
|
|
|
55
58
|
showPassage('@last');
|
|
56
59
|
}
|
|
57
60
|
}
|
|
61
|
+
return true;
|
|
58
62
|
}
|
|
59
|
-
|
|
60
|
-
disableLink(link);
|
|
63
|
+
if (section) {
|
|
61
64
|
section = processLink(section);
|
|
62
65
|
if (section) {
|
|
63
66
|
go(section);
|
|
64
67
|
}
|
|
68
|
+
return true;
|
|
65
69
|
}
|
|
66
|
-
|
|
70
|
+
if (rotateOrSequenceAttr) {
|
|
67
71
|
const result = rotate(rotateOrSequenceAttr, rotateAttr ? link.innerText : '');
|
|
68
72
|
link.innerHTML = result[0].replace(/"/g, '"').replace(/'/g, '\'');
|
|
69
73
|
const dataAttribute = rotateAttr ? 'data-rotate' : 'data-sequence';
|
|
@@ -76,7 +80,9 @@ export const init = (options) => {
|
|
|
76
80
|
set(attribute, result[0]);
|
|
77
81
|
}
|
|
78
82
|
save();
|
|
83
|
+
return true;
|
|
79
84
|
}
|
|
85
|
+
return false;
|
|
80
86
|
}
|
|
81
87
|
function handleClick(event) {
|
|
82
88
|
const target = event.target;
|
|
@@ -88,9 +94,6 @@ export const init = (options) => {
|
|
|
88
94
|
link.classList.add('disabled');
|
|
89
95
|
link.setAttribute('tabindex', '-1');
|
|
90
96
|
}
|
|
91
|
-
function disableLinks(links) {
|
|
92
|
-
links.forEach(disableLink);
|
|
93
|
-
}
|
|
94
97
|
function begin() {
|
|
95
98
|
if (!load()) {
|
|
96
99
|
go(story.start);
|
|
@@ -336,7 +339,6 @@ export const init = (options) => {
|
|
|
336
339
|
}
|
|
337
340
|
function newSection(sectionName) {
|
|
338
341
|
if (currentSectionElement) {
|
|
339
|
-
disableLinks(currentSectionElement.querySelectorAll('.squiffy-link'));
|
|
340
342
|
currentSectionElement.querySelectorAll('input').forEach(el => {
|
|
341
343
|
const attribute = el.getAttribute('data-attribute') || el.id;
|
|
342
344
|
if (attribute)
|
|
@@ -589,8 +591,20 @@ export const init = (options) => {
|
|
|
589
591
|
function getPassageContent(section, passage) {
|
|
590
592
|
return outputElement.querySelectorAll(`[data-source='[[${section}]][${passage}]']`);
|
|
591
593
|
}
|
|
594
|
+
function updateElementTextPreservingDisabledPassageLinks(element, text) {
|
|
595
|
+
// Record which passage links are disabled
|
|
596
|
+
const disabledPassages = Array.from(element
|
|
597
|
+
.querySelectorAll("a.link-passage.disabled"))
|
|
598
|
+
.map((el) => el.getAttribute("data-passage"));
|
|
599
|
+
element.innerHTML = text;
|
|
600
|
+
// Re-disable links that were disabled before the update
|
|
601
|
+
for (const passage of disabledPassages) {
|
|
602
|
+
const link = element.querySelector(`a.link-passage[data-passage="${passage}"]`);
|
|
603
|
+
if (link)
|
|
604
|
+
disableLink(link);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
592
607
|
function update(newStory) {
|
|
593
|
-
// TODO: Re-disable clicked links after update
|
|
594
608
|
for (const existingSection of Object.keys(story.sections)) {
|
|
595
609
|
const elements = getSectionContent(existingSection);
|
|
596
610
|
if (elements.length) {
|
|
@@ -598,13 +612,14 @@ export const init = (options) => {
|
|
|
598
612
|
if (!newSection) {
|
|
599
613
|
// section has been deleted
|
|
600
614
|
for (const element of elements) {
|
|
601
|
-
element.
|
|
615
|
+
const parentOutputSection = element.closest('.squiffy-output-section');
|
|
616
|
+
parentOutputSection.remove();
|
|
602
617
|
}
|
|
603
618
|
}
|
|
604
619
|
else if (newSection.text && newSection.text != story.sections[existingSection].text) {
|
|
605
620
|
// section has been updated
|
|
606
621
|
for (const element of elements) {
|
|
607
|
-
element
|
|
622
|
+
updateElementTextPreservingDisabledPassageLinks(element, newSection.text);
|
|
608
623
|
}
|
|
609
624
|
}
|
|
610
625
|
}
|
|
@@ -618,13 +633,14 @@ export const init = (options) => {
|
|
|
618
633
|
if (!newPassage) {
|
|
619
634
|
// passage has been deleted
|
|
620
635
|
for (const element of elements) {
|
|
621
|
-
element.
|
|
636
|
+
const parentOutputBlock = element.closest('.squiffy-output-block');
|
|
637
|
+
parentOutputBlock.remove();
|
|
622
638
|
}
|
|
623
639
|
}
|
|
624
640
|
else if (newPassage.text && newPassage.text != story.sections[existingSection].passages[existingPassage].text) {
|
|
625
641
|
// passage has been updated
|
|
626
642
|
for (const element of elements) {
|
|
627
|
-
element
|
|
643
|
+
updateElementTextPreservingDisabledPassageLinks(element, newPassage.text);
|
|
628
644
|
}
|
|
629
645
|
}
|
|
630
646
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "squiffy-runtime",
|
|
3
|
-
"version": "6.0.0-alpha.
|
|
3
|
+
"version": "6.0.0-alpha.9",
|
|
4
4
|
"main": "dist/squiffy.runtime.js",
|
|
5
5
|
"types": "dist/squiffy.runtime.d.ts",
|
|
6
6
|
"scripts": {
|
|
7
|
+
"dev": "vitest",
|
|
7
8
|
"test": "vitest --run",
|
|
8
9
|
"build": "tsc",
|
|
9
10
|
"prepublishOnly": "npm run build && npm run test"
|
|
@@ -45,12 +45,12 @@ exports[`Click a section link 2`] = `
|
|
|
45
45
|
"
|
|
46
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
|
-
<p>This should be <a class="squiffy-link link-passage
|
|
49
|
-
<p>You don't need to specify a name - for example, this <a class="squiffy-link link-passage
|
|
50
|
-
<p>And this goes to the <a class="squiffy-link link-section
|
|
51
|
-
<p>This line has links to <a class="squiffy-link link-section
|
|
52
|
-
<p>This line has links to <a class="squiffy-link link-passage
|
|
53
|
-
<p>Oh look - <a class="squiffy-link link-passage
|
|
48
|
+
<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>
|
|
49
|
+
<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>
|
|
50
|
+
<p>And this goes to the <a class="squiffy-link link-section" data-section="section2" role="link" tabindex="0">next section</a>.</p>
|
|
51
|
+
<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>
|
|
52
|
+
<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>
|
|
53
|
+
<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><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, with passages <a class="squiffy-link link-passage" data-passage="a" role="link" tabindex="0">a</a> and <a class="squiffy-link link-passage" data-passage="b" role="link" tabindex="0">b</a>.</p></div></div></div>"
|
|
54
54
|
`;
|
|
55
55
|
|
|
56
56
|
exports[`Delete passage 1`] = `
|
|
@@ -60,17 +60,17 @@ exports[`Delete passage 1`] = `
|
|
|
60
60
|
|
|
61
61
|
exports[`Delete passage 2`] = `
|
|
62
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
|
|
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>"
|
|
64
64
|
`;
|
|
65
65
|
|
|
66
66
|
exports[`Delete section 1`] = `
|
|
67
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
|
|
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" data-section="a" role="link" tabindex="0">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
69
|
`;
|
|
70
70
|
|
|
71
71
|
exports[`Delete section 2`] = `
|
|
72
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
|
|
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" data-section="a" role="link" tabindex="0">a</a></p></div></div></div>"
|
|
74
74
|
`;
|
|
75
75
|
|
|
76
76
|
exports[`Update default section output 1`] = `
|
|
@@ -61,7 +61,9 @@ const initScript = async (script: string) => {
|
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
const findLink = (element: HTMLElement, linkType: string, linkText: string, onlyEnabled: boolean = false) => {
|
|
64
|
-
const links =
|
|
64
|
+
const links = onlyEnabled
|
|
65
|
+
? element.querySelectorAll(`.squiffy-output-section:last-child a.squiffy-link.link-${linkType}`)
|
|
66
|
+
: element.querySelectorAll(`a.squiffy-link.link-${linkType}`);
|
|
65
67
|
return Array.from(links).find(link => link.textContent === linkText && (onlyEnabled ? !link.classList.contains("disabled") : true)) as HTMLElement;
|
|
66
68
|
};
|
|
67
69
|
|
|
@@ -100,13 +102,14 @@ test('Click a section link', async () => {
|
|
|
100
102
|
expect(linkToPassage).not.toBeNull();
|
|
101
103
|
expect(section3Link).not.toBeNull();
|
|
102
104
|
expect(linkToPassage.classList).not.toContain('disabled');
|
|
103
|
-
expect(section3Link.classList).not.toContain('disabled');
|
|
104
105
|
|
|
105
|
-
squiffyApi.clickLink(section3Link);
|
|
106
|
+
const handled = squiffyApi.clickLink(section3Link);
|
|
107
|
+
expect(handled).toBe(true);
|
|
106
108
|
|
|
107
|
-
expect(linkToPassage.classList).toContain('disabled');
|
|
108
|
-
expect(section3Link.classList).toContain('disabled');
|
|
109
109
|
expect(element.innerHTML).toMatchSnapshot();
|
|
110
|
+
|
|
111
|
+
// passage link is from the previous section, so should be unclickable
|
|
112
|
+
expect(squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
110
113
|
});
|
|
111
114
|
|
|
112
115
|
test('Click a passage link', async () => {
|
|
@@ -121,13 +124,15 @@ test('Click a passage link', async () => {
|
|
|
121
124
|
expect(linkToPassage).not.toBeNull();
|
|
122
125
|
expect(section3Link).not.toBeNull();
|
|
123
126
|
expect(linkToPassage.classList).not.toContain('disabled');
|
|
124
|
-
expect(section3Link.classList).not.toContain('disabled');
|
|
125
127
|
|
|
126
|
-
squiffyApi.clickLink(linkToPassage);
|
|
128
|
+
const handled = squiffyApi.clickLink(linkToPassage);
|
|
129
|
+
expect(handled).toBe(true);
|
|
127
130
|
|
|
128
131
|
expect(linkToPassage.classList).toContain('disabled');
|
|
129
|
-
expect(section3Link.classList).not.toContain('disabled');
|
|
130
132
|
expect(element.innerHTML).toMatchSnapshot();
|
|
133
|
+
|
|
134
|
+
// shouldn't be able to click it again
|
|
135
|
+
expect(squiffyApi.clickLink(linkToPassage)).toBe(false);
|
|
131
136
|
});
|
|
132
137
|
|
|
133
138
|
test('Run JavaScript functions', async () => {
|
|
@@ -156,7 +161,8 @@ test('Run JavaScript functions', async () => {
|
|
|
156
161
|
const clickContinue = () => {
|
|
157
162
|
const continueLink = findLink(element, 'section', 'Continue...', true);
|
|
158
163
|
expect(continueLink).not.toBeNull();
|
|
159
|
-
squiffyApi.clickLink(continueLink);
|
|
164
|
+
const handled = squiffyApi.clickLink(continueLink);
|
|
165
|
+
expect(handled).toBe(true);
|
|
160
166
|
};
|
|
161
167
|
|
|
162
168
|
const { squiffyApi, element } = await initScript(script);
|
|
@@ -208,7 +214,8 @@ test('Update passage output', async () => {
|
|
|
208
214
|
Passage a content`);
|
|
209
215
|
|
|
210
216
|
const link = findLink(element, 'passage', 'a');
|
|
211
|
-
squiffyApi.clickLink(link);
|
|
217
|
+
const handled = squiffyApi.clickLink(link);
|
|
218
|
+
expect(handled).toBe(true);
|
|
212
219
|
|
|
213
220
|
let defaultOutput = getSectionContent(element, '_default');
|
|
214
221
|
expect(defaultOutput).toBe('Click this: a');
|
|
@@ -238,7 +245,8 @@ test('Delete section', async () => {
|
|
|
238
245
|
New section`);
|
|
239
246
|
|
|
240
247
|
const link = findLink(element, 'section', 'a');
|
|
241
|
-
squiffyApi.clickLink(link);
|
|
248
|
+
const handled = squiffyApi.clickLink(link);
|
|
249
|
+
expect(handled).toBe(true);
|
|
242
250
|
|
|
243
251
|
let defaultOutput = getSectionContent(element, '_default');
|
|
244
252
|
expect(defaultOutput).toBe('Click this: a');
|
|
@@ -265,7 +273,8 @@ test('Delete passage', async () => {
|
|
|
265
273
|
New passage`);
|
|
266
274
|
|
|
267
275
|
const link = findLink(element, 'passage', 'a');
|
|
268
|
-
squiffyApi.clickLink(link);
|
|
276
|
+
const handled = squiffyApi.clickLink(link);
|
|
277
|
+
expect(handled).toBe(true);
|
|
269
278
|
|
|
270
279
|
let defaultOutput = getSectionContent(element, '_default');
|
|
271
280
|
expect(defaultOutput).toBe('Click this: a');
|
|
@@ -283,4 +292,42 @@ New passage`);
|
|
|
283
292
|
expect(passageOutput).toBeNull();
|
|
284
293
|
|
|
285
294
|
expect(element.innerHTML).toMatchSnapshot();
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test('Clicked passage links remain disabled after an update', async () => {
|
|
298
|
+
const { squiffyApi, element } = await initScript(`Click one of these: [a] [b]
|
|
299
|
+
|
|
300
|
+
[a]:
|
|
301
|
+
Output for passage A.
|
|
302
|
+
|
|
303
|
+
[b]:
|
|
304
|
+
Output for passage B.`);
|
|
305
|
+
|
|
306
|
+
// click linkA
|
|
307
|
+
|
|
308
|
+
let linkA = findLink(element, 'passage', 'a');
|
|
309
|
+
expect(linkA.classList).not.toContain('disabled');
|
|
310
|
+
expect(squiffyApi.clickLink(linkA)).toBe(true);
|
|
311
|
+
|
|
312
|
+
const updated = await compile(`Click one of these (updated): [a] [b]
|
|
313
|
+
|
|
314
|
+
[a]:
|
|
315
|
+
Output for passage A.
|
|
316
|
+
|
|
317
|
+
[b]:
|
|
318
|
+
Output for passage B.`);
|
|
319
|
+
|
|
320
|
+
squiffyApi.update(updated.story);
|
|
321
|
+
|
|
322
|
+
// linkA should still be disabled
|
|
323
|
+
|
|
324
|
+
linkA = findLink(element, 'passage', 'a');
|
|
325
|
+
expect(linkA.classList).toContain('disabled');
|
|
326
|
+
expect(squiffyApi.clickLink(linkA)).toBe(false);
|
|
327
|
+
|
|
328
|
+
// linkB should still be enabled
|
|
329
|
+
|
|
330
|
+
let linkB = findLink(element, 'passage', 'b');
|
|
331
|
+
expect(linkB.classList).not.toContain('disabled');
|
|
332
|
+
expect(squiffyApi.clickLink(linkB)).toBe(true);
|
|
286
333
|
});
|
package/src/squiffy.runtime.ts
CHANGED
|
@@ -16,7 +16,7 @@ export interface SquiffyApi {
|
|
|
16
16
|
restart: () => void;
|
|
17
17
|
get: (attribute: string) => any;
|
|
18
18
|
set: (attribute: string, value: any) => void;
|
|
19
|
-
clickLink: (link: HTMLElement) =>
|
|
19
|
+
clickLink: (link: HTMLElement) => boolean;
|
|
20
20
|
update: (story: Story) => void;
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -93,8 +93,12 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
93
93
|
return JSON.parse(result);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
function handleLink(link: HTMLElement) {
|
|
97
|
-
|
|
96
|
+
function handleLink(link: HTMLElement): boolean {
|
|
97
|
+
const outputSection = link.closest('.squiffy-output-section');
|
|
98
|
+
if (outputSection !== currentSectionElement) return false;
|
|
99
|
+
|
|
100
|
+
if (link.classList.contains('disabled')) return false;
|
|
101
|
+
|
|
98
102
|
let passage = link.getAttribute('data-passage');
|
|
99
103
|
let section = link.getAttribute('data-section');
|
|
100
104
|
const rotateAttr = link.getAttribute('data-rotate');
|
|
@@ -117,15 +121,20 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
117
121
|
showPassage('@last');
|
|
118
122
|
}
|
|
119
123
|
}
|
|
124
|
+
|
|
125
|
+
return true;
|
|
120
126
|
}
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
|
|
128
|
+
if (section) {
|
|
123
129
|
section = processLink(section);
|
|
124
130
|
if (section) {
|
|
125
131
|
go(section);
|
|
126
132
|
}
|
|
133
|
+
|
|
134
|
+
return true;
|
|
127
135
|
}
|
|
128
|
-
|
|
136
|
+
|
|
137
|
+
if (rotateOrSequenceAttr) {
|
|
129
138
|
const result = rotate(rotateOrSequenceAttr, rotateAttr ? link.innerText : '');
|
|
130
139
|
link.innerHTML = result[0]!.replace(/"/g, '"').replace(/'/g, '\'');
|
|
131
140
|
const dataAttribute = rotateAttr ? 'data-rotate' : 'data-sequence';
|
|
@@ -138,7 +147,11 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
138
147
|
set(attribute, result[0]);
|
|
139
148
|
}
|
|
140
149
|
save();
|
|
150
|
+
|
|
151
|
+
return true;
|
|
141
152
|
}
|
|
153
|
+
|
|
154
|
+
return false;
|
|
142
155
|
}
|
|
143
156
|
|
|
144
157
|
function handleClick(event: Event) {
|
|
@@ -153,10 +166,6 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
153
166
|
link.setAttribute('tabindex', '-1');
|
|
154
167
|
}
|
|
155
168
|
|
|
156
|
-
function disableLinks(links: NodeListOf<Element>) {
|
|
157
|
-
links.forEach(disableLink);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
169
|
function begin() {
|
|
161
170
|
if (!load()) {
|
|
162
171
|
go(story.start);
|
|
@@ -412,7 +421,6 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
412
421
|
|
|
413
422
|
function newSection(sectionName: string | null) {
|
|
414
423
|
if (currentSectionElement) {
|
|
415
|
-
disableLinks(currentSectionElement.querySelectorAll('.squiffy-link'));
|
|
416
424
|
currentSectionElement.querySelectorAll('input').forEach(el => {
|
|
417
425
|
const attribute = el.getAttribute('data-attribute') || el.id;
|
|
418
426
|
if (attribute) set(attribute, el.value);
|
|
@@ -683,9 +691,22 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
683
691
|
return outputElement.querySelectorAll(`[data-source='[[${section}]][${passage}]']`);
|
|
684
692
|
}
|
|
685
693
|
|
|
686
|
-
function
|
|
687
|
-
//
|
|
694
|
+
function updateElementTextPreservingDisabledPassageLinks(element: Element, text: string) {
|
|
695
|
+
// Record which passage links are disabled
|
|
696
|
+
const disabledPassages = Array.from(element
|
|
697
|
+
.querySelectorAll("a.link-passage.disabled"))
|
|
698
|
+
.map((el: HTMLElement) => el.getAttribute("data-passage"));
|
|
688
699
|
|
|
700
|
+
element.innerHTML = text;
|
|
701
|
+
|
|
702
|
+
// Re-disable links that were disabled before the update
|
|
703
|
+
for (const passage of disabledPassages) {
|
|
704
|
+
const link = element.querySelector(`a.link-passage[data-passage="${passage}"]`);
|
|
705
|
+
if (link) disableLink(link);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function update(newStory: Story) {
|
|
689
710
|
for (const existingSection of Object.keys(story.sections)) {
|
|
690
711
|
const elements = getSectionContent(existingSection);
|
|
691
712
|
if (elements.length) {
|
|
@@ -693,13 +714,14 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
693
714
|
if (!newSection) {
|
|
694
715
|
// section has been deleted
|
|
695
716
|
for (const element of elements) {
|
|
696
|
-
element.
|
|
717
|
+
const parentOutputSection = element.closest('.squiffy-output-section');
|
|
718
|
+
parentOutputSection.remove();
|
|
697
719
|
}
|
|
698
720
|
}
|
|
699
721
|
else if (newSection.text && newSection.text != story.sections[existingSection].text) {
|
|
700
722
|
// section has been updated
|
|
701
723
|
for (const element of elements) {
|
|
702
|
-
element
|
|
724
|
+
updateElementTextPreservingDisabledPassageLinks(element, newSection.text);
|
|
703
725
|
}
|
|
704
726
|
}
|
|
705
727
|
}
|
|
@@ -714,13 +736,14 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
|
|
|
714
736
|
if (!newPassage) {
|
|
715
737
|
// passage has been deleted
|
|
716
738
|
for (const element of elements) {
|
|
717
|
-
element.
|
|
739
|
+
const parentOutputBlock = element.closest('.squiffy-output-block');
|
|
740
|
+
parentOutputBlock.remove();
|
|
718
741
|
}
|
|
719
742
|
}
|
|
720
743
|
else if (newPassage.text && newPassage.text != story.sections[existingSection].passages[existingPassage].text) {
|
|
721
744
|
// passage has been updated
|
|
722
745
|
for (const element of elements) {
|
|
723
|
-
element
|
|
746
|
+
updateElementTextPreservingDisabledPassageLinks(element, newPassage.text);
|
|
724
747
|
}
|
|
725
748
|
}
|
|
726
749
|
}
|