extwee 2.2.0 → 2.2.2
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/.github/codeql-analysis.yml +51 -0
- package/README.md +9 -3
- package/build/extwee +0 -0
- package/build/extwee.web.min.js +1 -1
- package/docs/_sidebar.md +1 -0
- package/docs/examples/dynamicPassages.md +1 -1
- package/docs/examples/twsToTwee.md +1 -1
- package/docs/objects/story.md +1 -2
- package/index.js +3 -1
- package/package.json +22 -19
- package/src/IFID/generate.js +20 -0
- package/src/JSON/parse.js +44 -1
- package/src/Passage.js +61 -31
- package/src/Story.js +272 -110
- package/src/StoryFormat/parse.js +190 -80
- package/src/StoryFormat.js +78 -88
- package/src/TWS/parse.js +3 -3
- package/src/Twee/parse.js +3 -4
- package/src/Twine1HTML/compile.js +3 -1
- package/src/Twine1HTML/parse.js +3 -4
- package/src/Twine2ArchiveHTML/compile.js +9 -1
- package/src/Twine2ArchiveHTML/parse.js +33 -3
- package/src/Twine2HTML/compile.js +32 -7
- package/src/Twine2HTML/parse.js +51 -55
- package/test/IFID/IFID.Generate.test.js +10 -0
- package/test/JSON/JSON.Parse.test.js +24 -24
- package/test/Passage.test.js +69 -0
- package/test/Story.test.js +298 -49
- package/test/StoryFormat/StoryFormat.Parse.test.js +442 -55
- package/test/StoryFormat.test.js +9 -2
- package/test/TWS/Parse.test.js +1 -1
- package/test/Twine1HTML/Twine1HTML.Compile.test.js +1 -1
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Compile.test.js +1 -1
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +20 -4
- package/test/Twine2HTML/Twine2HTML.Compile.test.js +36 -121
- package/test/Twine2HTML/Twine2HTML.Parse.test.js +63 -43
- package/test/Twine2HTML/Twine2HTMLCompiler/format.js +9 -0
- package/test/Twine2HTML/Twine2HTMLParser/missingZoom.html +1 -1
- package/test/Twine2HTML/Twine2HTMLParser/unescaping.html +33 -0
- package/tsconfig.json +21 -0
- package/types/index.d.ts +14 -0
- package/types/src/JSON/parse.d.ts +8 -0
- package/types/src/Passage.d.ts +72 -0
- package/types/src/Story.d.ts +161 -0
- package/types/src/StoryFormat/parse.d.ts +7 -0
- package/types/src/StoryFormat.d.ts +97 -0
- package/types/src/TWS/parse.d.ts +10 -0
- package/types/src/Twee/parse.d.ts +10 -0
- package/types/src/Twine1HTML/compile.d.ts +17 -0
- package/types/src/Twine1HTML/parse.d.ts +10 -0
- package/types/src/Twine2ArchiveHTML/compile.d.ts +6 -0
- package/types/src/Twine2ArchiveHTML/parse.d.ts +6 -0
- package/types/src/Twine2HTML/compile.d.ts +9 -0
- package/types/src/Twine2HTML/parse.d.ts +17 -0
- package/types/src/extwee.d.ts +2 -0
- package/web-index.js +3 -1
- package/test/StoryFormat/StoryFormatParser/example.js +0 -3
- package/test/StoryFormat/StoryFormatParser/example2.js +0 -3
- package/test/StoryFormat/StoryFormatParser/format.js +0 -1
- package/test/StoryFormat/StoryFormatParser/format_doublename.js +0 -1
- package/test/StoryFormat/StoryFormatParser/harlowe.js +0 -3
- package/test/StoryFormat/StoryFormatParser/missingAuthor.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingDescription.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingImage.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingLicense.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingName.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingProofing.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingSource.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingURL.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingVersion.js +0 -1
- package/test/StoryFormat/StoryFormatParser/versionWrong.js +0 -1
- package/test/Twine2HTML/Twine2HTMLParser/missingName.html +0 -33
- package/test/Twine2HTML/Twine2HTMLParser/missingPID.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/missingPassageName.html +0 -15
package/test/Story.test.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import Story from '../src/Story.js';
|
|
1
|
+
import { Story, creatorName, creatorVersion } from '../src/Story.js';
|
|
2
2
|
import Passage from '../src/Passage';
|
|
3
3
|
import { parse as parseTwee } from '../src/Twee/parse.js';
|
|
4
4
|
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { parse as HTMLParser } from 'node-html-parser';
|
|
6
|
+
import { generate as generateIFID } from '../src/IFID/generate.js';
|
|
5
7
|
|
|
6
8
|
// Pull the name and version of this project from package.json.
|
|
7
9
|
// These are used as the 'creator' and 'creator-version'.
|
|
@@ -27,6 +29,11 @@ describe('Story', () => {
|
|
|
27
29
|
s = new Story('Test');
|
|
28
30
|
expect(s.name).toBe('Test');
|
|
29
31
|
});
|
|
32
|
+
|
|
33
|
+
it('Should have default name', () => {
|
|
34
|
+
s = new Story();
|
|
35
|
+
expect(s.name).toBe('Untitled Story');
|
|
36
|
+
});
|
|
30
37
|
});
|
|
31
38
|
|
|
32
39
|
describe('creator', () => {
|
|
@@ -222,6 +229,31 @@ describe('Story', () => {
|
|
|
222
229
|
});
|
|
223
230
|
});
|
|
224
231
|
|
|
232
|
+
describe('passages', () => {
|
|
233
|
+
let s = null;
|
|
234
|
+
|
|
235
|
+
beforeEach(() => {
|
|
236
|
+
s = new Story();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('Set passages to a new array containing at least one Passage', () => {
|
|
240
|
+
s.passages = [new Passage()];
|
|
241
|
+
expect(s.passages.length).toBe(1);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('Should throw error if trying to set to a non-Array type', () => {
|
|
245
|
+
expect(() => {
|
|
246
|
+
s.passages = null;
|
|
247
|
+
}).toThrow();
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('Should throw error if trying to set to an array containing non-Passage types', () => {
|
|
251
|
+
expect(() => {
|
|
252
|
+
s.passages = [null];
|
|
253
|
+
}).toThrow();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
225
257
|
describe('addPassage()', () => {
|
|
226
258
|
let s = null;
|
|
227
259
|
|
|
@@ -241,14 +273,6 @@ describe('Story', () => {
|
|
|
241
273
|
}).toThrow();
|
|
242
274
|
});
|
|
243
275
|
|
|
244
|
-
it('addPassage() - should prevent passages with same name being added', () => {
|
|
245
|
-
const p = new Passage('A');
|
|
246
|
-
const p2 = new Passage('A');
|
|
247
|
-
s.addPassage(p);
|
|
248
|
-
s.addPassage(p2);
|
|
249
|
-
expect(s.size()).toBe(1);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
276
|
it('addPassage() - should override StoryData: ifid', function () {
|
|
253
277
|
// Generate object.
|
|
254
278
|
const o = {
|
|
@@ -350,30 +374,6 @@ describe('Story', () => {
|
|
|
350
374
|
});
|
|
351
375
|
});
|
|
352
376
|
|
|
353
|
-
describe('forEachPassage()', () => {
|
|
354
|
-
let s = null;
|
|
355
|
-
|
|
356
|
-
beforeEach(() => {
|
|
357
|
-
s = new Story();
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
it('forEachPassage() - should return if non-function', () => {
|
|
361
|
-
s.addPassage(new Passage('A'));
|
|
362
|
-
s.addPassage(new Passage('B'));
|
|
363
|
-
let passageNames = '';
|
|
364
|
-
s.forEachPassage((p) => {
|
|
365
|
-
passageNames += p.name;
|
|
366
|
-
});
|
|
367
|
-
expect(passageNames).toBe('AB');
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
it('forEachPassage() - should throw error if non-function', () => {
|
|
371
|
-
expect(() => {
|
|
372
|
-
s.forEachPassage(null);
|
|
373
|
-
}).toThrow();
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
|
|
377
377
|
describe('size()', () => {
|
|
378
378
|
let s = null;
|
|
379
379
|
|
|
@@ -399,15 +399,15 @@ describe('Story', () => {
|
|
|
399
399
|
const s = new Story();
|
|
400
400
|
// Convert to string and then back to object.
|
|
401
401
|
const result = JSON.parse(s.toJSON());
|
|
402
|
-
expect(result.name).toBe('');
|
|
402
|
+
expect(result.name).toBe('Untitled Story');
|
|
403
403
|
expect(Object.keys(result.tagColors).length).toBe(0);
|
|
404
404
|
expect(result.ifid).toBe('');
|
|
405
405
|
expect(result.start).toBe('');
|
|
406
406
|
expect(result.formatVersion).toBe('');
|
|
407
407
|
expect(result.format).toBe('');
|
|
408
|
-
expect(result.creator).toBe(
|
|
409
|
-
expect(result.creatorVersion).toBe(
|
|
410
|
-
expect(result.zoom).toBe(
|
|
408
|
+
expect(result.creator).toBe(creatorName);
|
|
409
|
+
expect(result.creatorVersion).toBe(creatorVersion);
|
|
410
|
+
expect(result.zoom).toBe(1);
|
|
411
411
|
expect(Object.keys(result.metadata).length).toBe(0);
|
|
412
412
|
});
|
|
413
413
|
|
|
@@ -430,10 +430,81 @@ describe('Story', () => {
|
|
|
430
430
|
s = new Story();
|
|
431
431
|
});
|
|
432
432
|
|
|
433
|
+
it('Should not generate format if empty', function () {
|
|
434
|
+
// Add one passage.
|
|
435
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
436
|
+
|
|
437
|
+
// Add an IFID (to prevent warning)
|
|
438
|
+
s.IFID = generateIFID();
|
|
439
|
+
|
|
440
|
+
// Set format to empty string.
|
|
441
|
+
s.format = '';
|
|
442
|
+
|
|
443
|
+
// Convert to Twee.
|
|
444
|
+
const t = s.toTwee();
|
|
445
|
+
|
|
446
|
+
// Test for format in metadata, should not exist.
|
|
447
|
+
expect(t.includes(`"'format":`)).not.toBe(true);
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it('Should not generate formatVersion if empty', function () {
|
|
451
|
+
// Add one passage.
|
|
452
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
453
|
+
|
|
454
|
+
// Add an IFID (to prevent warning)
|
|
455
|
+
s.IFID = generateIFID();
|
|
456
|
+
|
|
457
|
+
// Set formatVersion to empty string.
|
|
458
|
+
s.formatVersion = '';
|
|
459
|
+
|
|
460
|
+
// Convert to Twee.
|
|
461
|
+
const t = s.toTwee();
|
|
462
|
+
|
|
463
|
+
// Test for formatVersion in metadata, should not exist.
|
|
464
|
+
expect(t.includes(`"'format-version":`)).not.toBe(true);
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
it('Should not generate zoom if zero', function () {
|
|
468
|
+
// Add one passage.
|
|
469
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
470
|
+
|
|
471
|
+
// Add an IFID (to prevent warning)
|
|
472
|
+
s.IFID = generateIFID();
|
|
473
|
+
|
|
474
|
+
// Set zoom to 0.
|
|
475
|
+
s.zoom = 0;
|
|
476
|
+
|
|
477
|
+
// Convert to Twee.
|
|
478
|
+
const t = s.toTwee();
|
|
479
|
+
|
|
480
|
+
// Test for zoom in metadata, should not exist.
|
|
481
|
+
expect(t.includes(`"'zoom":`)).not.toBe(true);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('Should not generate start if empty', function () {
|
|
485
|
+
// Add one passage.
|
|
486
|
+
s.addPassage(new Passage('Start', 'Content'));
|
|
487
|
+
|
|
488
|
+
// Add an IFID (to prevent warning)
|
|
489
|
+
s.IFID = generateIFID();
|
|
490
|
+
|
|
491
|
+
// Set start to empty string.
|
|
492
|
+
s.start = '';
|
|
493
|
+
|
|
494
|
+
// Convert to Twee.
|
|
495
|
+
const t = s.toTwee();
|
|
496
|
+
|
|
497
|
+
// Test for start in metadata, should not exist.
|
|
498
|
+
expect(t.includes(`"'start":`)).not.toBe(true);
|
|
499
|
+
});
|
|
500
|
+
|
|
433
501
|
it('Should detect StoryTitle text', function () {
|
|
434
502
|
// Add one passage.
|
|
435
503
|
s.addPassage(new Passage('StoryTitle', 'Content'));
|
|
436
504
|
|
|
505
|
+
// Add an IFID (to prevent warning)
|
|
506
|
+
s.IFID = generateIFID();
|
|
507
|
+
|
|
437
508
|
// Convert to Twee.
|
|
438
509
|
const t = s.toTwee();
|
|
439
510
|
|
|
@@ -472,6 +543,7 @@ describe('Story', () => {
|
|
|
472
543
|
s.formatVersion = '1.2.3';
|
|
473
544
|
s.zoom = 1;
|
|
474
545
|
s.start = 'Untitled';
|
|
546
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
475
547
|
|
|
476
548
|
// Convert to Twee.
|
|
477
549
|
const t = s.toTwee();
|
|
@@ -484,6 +556,7 @@ describe('Story', () => {
|
|
|
484
556
|
expect(story2.format).toBe('Test');
|
|
485
557
|
expect(story2.zoom).toBe(1);
|
|
486
558
|
expect(story2.start).toBe('Untitled');
|
|
559
|
+
expect(story2.IFID).toBe('DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A');
|
|
487
560
|
});
|
|
488
561
|
|
|
489
562
|
it('Should write tag colors', () => {
|
|
@@ -491,6 +564,8 @@ describe('Story', () => {
|
|
|
491
564
|
s.addPassage(new Passage('Start', 'Content'));
|
|
492
565
|
s.addPassage(new Passage('Untitled', 'Some stuff'));
|
|
493
566
|
|
|
567
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
568
|
+
|
|
494
569
|
// Add tag colors.
|
|
495
570
|
s.tagColors = {
|
|
496
571
|
bar: 'green',
|
|
@@ -515,6 +590,9 @@ describe('Story', () => {
|
|
|
515
590
|
s.addPassage(new Passage('Test', 'Test', ['script']));
|
|
516
591
|
s.addPassage(new Passage('Start', 'Content'));
|
|
517
592
|
|
|
593
|
+
// Set IFID.
|
|
594
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
595
|
+
|
|
518
596
|
// Convert into Twee.
|
|
519
597
|
const t = s.toTwee();
|
|
520
598
|
|
|
@@ -533,6 +611,9 @@ describe('Story', () => {
|
|
|
533
611
|
s.addPassage(new Passage('Test', 'Test', ['stylesheet']));
|
|
534
612
|
s.addPassage(new Passage('Start', 'Content'));
|
|
535
613
|
|
|
614
|
+
// Set IFID.
|
|
615
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
616
|
+
|
|
536
617
|
// Convert into Twee.
|
|
537
618
|
const t = s.toTwee();
|
|
538
619
|
|
|
@@ -554,18 +635,6 @@ describe('Story', () => {
|
|
|
554
635
|
s = new Story();
|
|
555
636
|
});
|
|
556
637
|
|
|
557
|
-
it('Should throw error if no starting passage', function () {
|
|
558
|
-
// No start set.
|
|
559
|
-
expect(() => { s.toTwine2HTML(); }).toThrow();
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
it('Should throw error if starting passage cannot be found', function () {
|
|
563
|
-
// Set start.
|
|
564
|
-
s.start = 'Unknown';
|
|
565
|
-
// Has a start, but not part of collection.
|
|
566
|
-
expect(() => { s.toTwine2HTML(); }).toThrow();
|
|
567
|
-
});
|
|
568
|
-
|
|
569
638
|
it('Should encode name', () => {
|
|
570
639
|
// Add passage.
|
|
571
640
|
s.addPassage(new Passage('Start', 'Word'));
|
|
@@ -617,6 +686,114 @@ describe('Story', () => {
|
|
|
617
686
|
// Expect the script passage text to be encoded.
|
|
618
687
|
expect(result.includes('<script role="script" id="twine-user-script" type="text/twine-javascript">Word')).toBe(true);
|
|
619
688
|
});
|
|
689
|
+
|
|
690
|
+
it('Should encode format', () => {
|
|
691
|
+
// Add passage.
|
|
692
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
693
|
+
// Set start.
|
|
694
|
+
s.start = 'Start';
|
|
695
|
+
// Set format.
|
|
696
|
+
s.format = 'Harlowe';
|
|
697
|
+
// Create HTML.
|
|
698
|
+
const result = s.toTwine2HTML();
|
|
699
|
+
// Expect the format to be encoded.
|
|
700
|
+
expect(result.includes('format="Harlowe"')).toBe(true);
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
it('Should encode formatVersion', () => {
|
|
704
|
+
// Add passage.
|
|
705
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
706
|
+
// Set start.
|
|
707
|
+
s.start = 'Start';
|
|
708
|
+
// Set formatVersion.
|
|
709
|
+
s.formatVersion = '3.2.0';
|
|
710
|
+
// Create HTML.
|
|
711
|
+
const result = s.toTwine2HTML();
|
|
712
|
+
// Expect the formatVersion to be encoded.
|
|
713
|
+
expect(result.includes('format-version="3.2.0"')).toBe(true);
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
it('Should encode zoom', () => {
|
|
717
|
+
// Add passage.
|
|
718
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
719
|
+
// Set start.
|
|
720
|
+
s.start = 'Start';
|
|
721
|
+
// Set zoom.
|
|
722
|
+
s.zoom = 2;
|
|
723
|
+
// Create HTML.
|
|
724
|
+
const result = s.toTwine2HTML();
|
|
725
|
+
// Expect the zoom to be encoded.
|
|
726
|
+
expect(result.includes('zoom="2"')).toBe(true);
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
it('Should encode start', () => {
|
|
730
|
+
// Add passage.
|
|
731
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
732
|
+
// Set start.
|
|
733
|
+
s.start = 'Start';
|
|
734
|
+
// Create HTML.
|
|
735
|
+
const result = s.toTwine2HTML();
|
|
736
|
+
// Expect the start to be encoded.
|
|
737
|
+
expect(result.includes('startnode="1"')).toBe(true);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
it('Should encode start if property is not set but Start passage is', () => {
|
|
741
|
+
// Add passage.
|
|
742
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
743
|
+
// Create HTML.
|
|
744
|
+
const result = s.toTwine2HTML();
|
|
745
|
+
// Expect the start to be encoded.
|
|
746
|
+
expect(result.includes('startnode="1"')).toBe(true);
|
|
747
|
+
});
|
|
748
|
+
|
|
749
|
+
it('Should encode creator', () => {
|
|
750
|
+
// Add passage.
|
|
751
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
752
|
+
// Set start.
|
|
753
|
+
s.start = 'Start';
|
|
754
|
+
// Create HTML.
|
|
755
|
+
const result = s.toTwine2HTML();
|
|
756
|
+
// Expect the creator to be encoded.
|
|
757
|
+
expect(result.includes(`creator="${creatorName}"`)).toBe(true);
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
it('Should encode creatorVersion', () => {
|
|
761
|
+
// Add passage.
|
|
762
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
763
|
+
// Set start.
|
|
764
|
+
s.start = 'Start';
|
|
765
|
+
// Create HTML.
|
|
766
|
+
const result = s.toTwine2HTML();
|
|
767
|
+
// Expect the creatorVersion to be encoded.
|
|
768
|
+
expect(result.includes(`creator-version="${creatorVersion}"`)).toBe(true);
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
it('Should not encode creatorVersion if not set', () => {
|
|
772
|
+
// Add passage.
|
|
773
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
774
|
+
// Set start.
|
|
775
|
+
s.start = 'Start';
|
|
776
|
+
// Set creatorVersion to empty string.
|
|
777
|
+
s.creatorVersion = '';
|
|
778
|
+
// Create HTML.
|
|
779
|
+
const result = s.toTwine2HTML();
|
|
780
|
+
// Expect the creatorVersion to be encoded.
|
|
781
|
+
expect(result.includes(`creator-version="${creatorVersion}"`)).not.toBe(true);
|
|
782
|
+
});
|
|
783
|
+
|
|
784
|
+
it('Should not encode creator if not set', () => {
|
|
785
|
+
// Add passage.
|
|
786
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
787
|
+
// Set start.
|
|
788
|
+
s.start = 'Start';
|
|
789
|
+
// Set creator to empty string.
|
|
790
|
+
s.creator = '';
|
|
791
|
+
// Create HTML.
|
|
792
|
+
const result = s.toTwine2HTML();
|
|
793
|
+
// Expect the creator to be encoded.
|
|
794
|
+
expect(result.includes(`creator="${creatorName}"`)).not.toBe(true);
|
|
795
|
+
});
|
|
796
|
+
|
|
620
797
|
});
|
|
621
798
|
|
|
622
799
|
describe('toTwine1HTML()', function () {
|
|
@@ -635,4 +812,76 @@ describe('Story', () => {
|
|
|
635
812
|
expect(result.includes('<div tiddler="Start"')).toBe(true);
|
|
636
813
|
});
|
|
637
814
|
});
|
|
815
|
+
|
|
816
|
+
describe('Escaping', function () {
|
|
817
|
+
it('Should produce valid Twine 2 Story HTML', function () {
|
|
818
|
+
// Create a new Story.
|
|
819
|
+
const s = new Story('"Abuse" &test');
|
|
820
|
+
// Add a passage.
|
|
821
|
+
s.addPassage(new Passage('"Test"', 'Word'));
|
|
822
|
+
// Set start.
|
|
823
|
+
s.start = '"Test"';
|
|
824
|
+
// Parse HTML.
|
|
825
|
+
const root = HTMLParser(s.toTwine2HTML());
|
|
826
|
+
// Expect correct name attribute for tw-storydata.
|
|
827
|
+
expect(root.querySelector('tw-storydata').getAttribute('name')).toBe('"Abuse" &test');
|
|
828
|
+
// Expect correct name attribute for tw-passagedata.
|
|
829
|
+
expect(root.querySelector('tw-passagedata').getAttribute('name')).toBe('"Test"');
|
|
830
|
+
// Use Twine 2 result.
|
|
831
|
+
const s2 = `<tw-storydata name=""Abuse" &test" startnode="1" creator="Twine" creator-version="2.8.1" format="Harlowe" format-version="3.3.8" ifid="452A9D80-C759-42C5-B001-5B861A2410C5" options="" tags="" zoom="1" hidden><style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style><script role="script" id="twine-user-script" type="text/twine-javascript"></script><tw-passagedata pid="1" name=""Test"" tags="&tag "bad"" position="300,100" size="100,100"></tw-passagedata></tw-storydata>`;
|
|
832
|
+
// Parse HTML.
|
|
833
|
+
const root2 = HTMLParser(s2);
|
|
834
|
+
// Expect correct name attribute for tw-storydata.
|
|
835
|
+
expect(root2.querySelector('tw-storydata').getAttribute('name')).toBe('"Abuse" &test');
|
|
836
|
+
// Expect correct name attribute for tw-passagedata.
|
|
837
|
+
expect(root2.querySelector('tw-passagedata').getAttribute('name')).toBe('"Test"');
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
it('Should produce valid Twine 1 Story HTML', function () {
|
|
841
|
+
// Create a new Story.
|
|
842
|
+
const s = new Story('"Abuse" &test');
|
|
843
|
+
// Add a passage.
|
|
844
|
+
s.addPassage(new Passage('"Test"', 'Word'));
|
|
845
|
+
// Set start.
|
|
846
|
+
s.start = '"Test"';
|
|
847
|
+
// Parse HTML.
|
|
848
|
+
const root = HTMLParser(s.toTwine1HTML());
|
|
849
|
+
// Expect correct name attribute for div.
|
|
850
|
+
expect(root.querySelector('div').getAttribute('tiddler')).toBe('"Test"');
|
|
851
|
+
});
|
|
852
|
+
});
|
|
853
|
+
|
|
854
|
+
describe('Warnings', function () {
|
|
855
|
+
beforeEach(() => {
|
|
856
|
+
// Mock console.warn.
|
|
857
|
+
jest.spyOn(console, 'warn').mockImplementation();
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
afterEach(() => {
|
|
861
|
+
// Restore all mocks.
|
|
862
|
+
jest.restoreAllMocks();
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
it('Should generate warning if a passage with the same name already exists', function () {
|
|
866
|
+
// Create a new Story.
|
|
867
|
+
const s = new Story();
|
|
868
|
+
// Add a passage.
|
|
869
|
+
s.addPassage(new Passage('Test'));
|
|
870
|
+
// Add a passage with the same name.
|
|
871
|
+
s.addPassage(new Passage('Test'));
|
|
872
|
+
// Expect warning.
|
|
873
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: A passage with the name "Test" already exists!');
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
it('Should generate a warning if story IFID is not in the correct format', function () {
|
|
877
|
+
// Create a new Story.
|
|
878
|
+
const s = new Story();
|
|
879
|
+
// Set IFID.
|
|
880
|
+
s.IFID = 'Test';
|
|
881
|
+
// Create Twee
|
|
882
|
+
s.toTwee();
|
|
883
|
+
// Expect warning.
|
|
884
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: IFID is not in UUIDv4 format! A new IFID was generated.');
|
|
885
|
+
});
|
|
886
|
+
});
|
|
638
887
|
});
|