squiffy-runtime 6.0.0-alpha.8 → 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.
@@ -591,9 +591,20 @@ export const init = (options) => {
591
591
  function getPassageContent(section, passage) {
592
592
  return outputElement.querySelectorAll(`[data-source='[[${section}]][${passage}]']`);
593
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
+ }
594
607
  function update(newStory) {
595
- // TODO: Re-disable clicked links after update
596
- // TODO: Delete empty output blocks
597
608
  for (const existingSection of Object.keys(story.sections)) {
598
609
  const elements = getSectionContent(existingSection);
599
610
  if (elements.length) {
@@ -601,13 +612,14 @@ export const init = (options) => {
601
612
  if (!newSection) {
602
613
  // section has been deleted
603
614
  for (const element of elements) {
604
- element.remove();
615
+ const parentOutputSection = element.closest('.squiffy-output-section');
616
+ parentOutputSection.remove();
605
617
  }
606
618
  }
607
619
  else if (newSection.text && newSection.text != story.sections[existingSection].text) {
608
620
  // section has been updated
609
621
  for (const element of elements) {
610
- element.innerHTML = ui.processText(newSection.text);
622
+ updateElementTextPreservingDisabledPassageLinks(element, newSection.text);
611
623
  }
612
624
  }
613
625
  }
@@ -621,13 +633,14 @@ export const init = (options) => {
621
633
  if (!newPassage) {
622
634
  // passage has been deleted
623
635
  for (const element of elements) {
624
- element.remove();
636
+ const parentOutputBlock = element.closest('.squiffy-output-block');
637
+ parentOutputBlock.remove();
625
638
  }
626
639
  }
627
640
  else if (newPassage.text && newPassage.text != story.sections[existingSection].passages[existingPassage].text) {
628
641
  // passage has been updated
629
642
  for (const element of elements) {
630
- element.innerHTML = ui.processText(newPassage.text);
643
+ updateElementTextPreservingDisabledPassageLinks(element, newPassage.text);
631
644
  }
632
645
  }
633
646
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squiffy-runtime",
3
- "version": "6.0.0-alpha.8",
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": {
@@ -60,7 +60,7 @@ 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><div class="squiffy-output-block"></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`] = `
@@ -70,7 +70,7 @@ exports[`Delete section 1`] = `
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" 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></div>"
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 = element.querySelectorAll(`.squiffy-output-section:last-child a.squiffy-link.link-${linkType}`);
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
 
@@ -290,4 +292,42 @@ New passage`);
290
292
  expect(passageOutput).toBeNull();
291
293
 
292
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);
293
333
  });
@@ -691,10 +691,22 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
691
691
  return outputElement.querySelectorAll(`[data-source='[[${section}]][${passage}]']`);
692
692
  }
693
693
 
694
- function update(newStory: Story) {
695
- // TODO: Re-disable clicked links after update
696
- // TODO: Delete empty output blocks
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"));
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
+ }
697
708
 
709
+ function update(newStory: Story) {
698
710
  for (const existingSection of Object.keys(story.sections)) {
699
711
  const elements = getSectionContent(existingSection);
700
712
  if (elements.length) {
@@ -702,13 +714,14 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
702
714
  if (!newSection) {
703
715
  // section has been deleted
704
716
  for (const element of elements) {
705
- element.remove();
717
+ const parentOutputSection = element.closest('.squiffy-output-section');
718
+ parentOutputSection.remove();
706
719
  }
707
720
  }
708
721
  else if (newSection.text && newSection.text != story.sections[existingSection].text) {
709
722
  // section has been updated
710
723
  for (const element of elements) {
711
- element.innerHTML = ui.processText(newSection.text);
724
+ updateElementTextPreservingDisabledPassageLinks(element, newSection.text);
712
725
  }
713
726
  }
714
727
  }
@@ -723,13 +736,14 @@ export const init = (options: SquiffyInitOptions): SquiffyApi => {
723
736
  if (!newPassage) {
724
737
  // passage has been deleted
725
738
  for (const element of elements) {
726
- element.remove();
739
+ const parentOutputBlock = element.closest('.squiffy-output-block');
740
+ parentOutputBlock.remove();
727
741
  }
728
742
  }
729
743
  else if (newPassage.text && newPassage.text != story.sections[existingSection].passages[existingPassage].text) {
730
744
  // passage has been updated
731
745
  for (const element of elements) {
732
- element.innerHTML = ui.processText(newPassage.text);
746
+ updateElementTextPreservingDisabledPassageLinks(element, newPassage.text);
733
747
  }
734
748
  }
735
749
  }