extwee 2.3.11 → 2.3.13
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/CHANGELOG.md +219 -0
- package/CONTRIBUTING.md +305 -0
- package/README.md +16 -0
- package/build/extwee.core.min.js +1 -1
- package/build/extwee.twine1html.min.js +1 -1
- package/build/extwee.twine2archive.min.js +1 -1
- package/build/extwee.tws.min.js +1 -1
- package/logs/arrays.html +79 -0
- package/logs/arrays.twee +64 -0
- package/logs/example.html +47 -0
- package/logs/fixing.js +23 -0
- package/logs/format-fixed.js +8 -0
- package/logs/format.js +8 -0
- package/logs/test-entities.cjs +40 -0
- package/package.json +19 -16
- package/src/Story.js +2 -2
- package/types/src/Story.d.ts +1 -1
- package/.github/FUNDING.yml +0 -3
- package/.github/codeql-analysis.yml +0 -51
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/dependabot-automerge.yml +0 -23
- package/.github/workflows/nodejs.yml +0 -28
- package/.travis.yml +0 -13
- package/babel.config.json +0 -18
- package/docs/.nojekyll +0 -0
- package/docs/README.md +0 -224
- package/docs/_sidebar.md +0 -19
- package/docs/build/extwee.core.min.js +0 -1
- package/docs/build/extwee.twine1html.min.js +0 -1
- package/docs/build/extwee.twine2archive.min.js +0 -1
- package/docs/build/extwee.tws.min.js +0 -1
- package/docs/demos/compiler/extwee.core.min.js +0 -1
- package/docs/demos/compiler/index.css +0 -105
- package/docs/demos/compiler/index.html +0 -359
- package/docs/demos/decompile/extwee.core.min.js +0 -1
- package/docs/demos/decompile/index.css +0 -584
- package/docs/demos/decompile/index.html +0 -468
- package/docs/examples/dynamicPassages.md +0 -28
- package/docs/examples/jsonToTwee.md +0 -23
- package/docs/examples/twsToTwee.md +0 -25
- package/docs/formats/json.md +0 -17
- package/docs/formats/twee.md +0 -13
- package/docs/formats/twine1HTML.md +0 -13
- package/docs/formats/twine2ArchiveHTML.md +0 -13
- package/docs/formats/twine2HTML.md +0 -13
- package/docs/formats/tws.md +0 -9
- package/docs/index.html +0 -26
- package/docs/install/npm.md +0 -16
- package/docs/install/npx.md +0 -79
- package/docs/objects/passage.md +0 -47
- package/docs/objects/story.md +0 -69
- package/docs/objects/storyformat.md +0 -27
- package/eslint.config.js +0 -28
- package/extwee.config.json +0 -6
- package/extwee.config.md +0 -67
- package/jest.config.json +0 -5
- package/test/CLI/CLI.test.js +0 -49
- package/test/CLI/files/example.json +0 -1
- package/test/CLI/files/example6.twee +0 -22
- package/test/CLI/files/harlowe.js +0 -3
- package/test/CLI/files/input.html +0 -47
- package/test/CLI/files/output/test.twee +0 -0
- package/test/CLI/files/test.twee +0 -18
- package/test/CLI/files/tweeExample.twee +0 -17
- package/test/CLI/files/twine1/LICENSE.txt +0 -32
- package/test/CLI/files/twine1/code.js +0 -5
- package/test/CLI/files/twine1/engine.js +0 -43
- package/test/CLI/files/twine1/header.html +0 -325
- package/test/CLI/files/twine1Test.html +0 -371
- package/test/CLI/files/twineExample.html +0 -16
- package/test/Config/Config.test.js +0 -76
- package/test/Config/files/empty.json +0 -3
- package/test/Config/files/full.json +0 -8
- package/test/Config/files/invalid.json +0 -1
- package/test/Config/files/valid.json +0 -6
- package/test/Config/isDirectory.test.js +0 -50
- package/test/Config/isFile.test.js +0 -53
- package/test/Config/loadStoryFormat.test.js +0 -117
- package/test/Config/readDirectories.test.js +0 -78
- package/test/IFID/IFID.Generate.test.js +0 -10
- package/test/JSON/JSON.Parse.test.js +0 -316
- package/test/Objects/Passage.test.js +0 -274
- package/test/Objects/SnowmanCompatibility.test.js +0 -111
- package/test/Objects/Story.test.js +0 -1075
- package/test/Objects/StoryFormat.test.js +0 -219
- package/test/Roundtrip/Files/Example1.html +0 -64
- package/test/Roundtrip/Files/LICENSE +0 -19
- package/test/Roundtrip/Files/example1.twee +0 -10
- package/test/Roundtrip/Files/example2.twee +0 -27
- package/test/Roundtrip/Files/example4.twee +0 -27
- package/test/Roundtrip/Files/harlowe.js +0 -3
- package/test/Roundtrip/Files/round.html +0 -49
- package/test/Roundtrip/Roundtrip.test.js +0 -54
- package/test/StoryFormat/StoryFormat.Parse.test.js +0 -479
- package/test/TWS/Parse.test.js +0 -56
- package/test/TWS/TWSParser/Example5.tws +0 -414
- package/test/TWS/TWSParser/noscale.tws +0 -0
- package/test/TWS/TWSParser/nostory.tws +0 -0
- package/test/Twee/Twee.Escaping.test.js +0 -200
- package/test/Twee/Twee.Parse.test.js +0 -108
- package/test/Twee/TweeParser/cursed.twee +0 -16
- package/test/Twee/TweeParser/cycling.twee +0 -75
- package/test/Twee/TweeParser/emptytags.twee +0 -2
- package/test/Twee/TweeParser/example.twee +0 -32
- package/test/Twee/TweeParser/malformed.twee +0 -2
- package/test/Twee/TweeParser/missing.twee +0 -19
- package/test/Twee/TweeParser/multipleScriptPassages.twee +0 -19
- package/test/Twee/TweeParser/multipleStyleTag.twee +0 -19
- package/test/Twee/TweeParser/multipletags.twee +0 -10
- package/test/Twee/TweeParser/noTitle.twee +0 -2
- package/test/Twee/TweeParser/notes.twee +0 -16
- package/test/Twee/TweeParser/pasagemetadataerror.twee +0 -2
- package/test/Twee/TweeParser/scriptPassage.twee +0 -16
- package/test/Twee/TweeParser/singletag.twee +0 -13
- package/test/Twee/TweeParser/start.twee +0 -2
- package/test/Twee/TweeParser/startMetadata.twee +0 -14
- package/test/Twee/TweeParser/storydataerror.twee +0 -25
- package/test/Twee/TweeParser/style.twee +0 -16
- package/test/Twee/TweeParser/stylePassage.twee +0 -16
- package/test/Twee/TweeParser/test.twee +0 -25
- package/test/Twine1HTML/Twine1HTML.Compile.test.js +0 -180
- package/test/Twine1HTML/Twine1HTML.Parse.Web.test.js +0 -484
- package/test/Twine1HTML/Twine1HTML.Parse.test.js +0 -183
- package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/LICENSE +0 -674
- package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/engine.js +0 -43
- package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/jquery.js +0 -4
- package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/modernizr.js +0 -4
- package/test/Twine1HTML/Twine1HTMLCompiler/engineTest.html +0 -1
- package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/LICENSE +0 -32
- package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/code.js +0 -4
- package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/header.html +0 -327
- package/test/Twine1HTML/Twine1HTMLCompiler/test.html +0 -0
- package/test/Twine1HTML/Twine1HTMLCompiler/test1.html +0 -6
- package/test/Twine1HTML/Twine1HTMLCompiler/test2.html +0 -6
- package/test/Twine1HTML/Twine1HTMLCompiler/test3.html +0 -43
- package/test/Twine1HTML/Twine1HTMLCompiler/test4.html +0 -372
- package/test/Twine1HTML/Twine1HTMLCompiler/test5.html +0 -372
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Compile.test.js +0 -35
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.Web.test.js +0 -293
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +0 -42
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTMLCompiler/test1.html +0 -6
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTMLParser/test1.html +0 -3
- package/test/Twine2HTML/Twine2HTML.Compile.test.js +0 -139
- package/test/Twine2HTML/Twine2HTML.Parse.Web.test.js +0 -329
- package/test/Twine2HTML/Twine2HTML.Parse.test.js +0 -192
- package/test/Twine2HTML/Twine2HTMLCompiler/TestTags.html +0 -42
- package/test/Twine2HTML/Twine2HTMLCompiler/creator.html +0 -50
- package/test/Twine2HTML/Twine2HTMLCompiler/example6.twee +0 -16
- package/test/Twine2HTML/Twine2HTMLCompiler/format.js +0 -9
- package/test/Twine2HTML/Twine2HTMLCompiler/missingStoryTitle.twee +0 -29
- package/test/Twine2HTML/Twine2HTMLCompiler/test11.html +0 -121
- package/test/Twine2HTML/Twine2HTMLCompiler/test2.html +0 -58
- package/test/Twine2HTML/Twine2HTMLCompiler/test3.html +0 -49
- package/test/Twine2HTML/Twine2HTMLCompiler/test4.html +0 -50
- package/test/Twine2HTML/Twine2HTMLCompiler/test6.html +0 -49
- package/test/Twine2HTML/Twine2HTMLParser/Example1.html +0 -53
- package/test/Twine2HTML/Twine2HTMLParser/Tags.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/lyingStartnode.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/lyingTagColors.html +0 -48
- package/test/Twine2HTML/Twine2HTMLParser/missingCreator.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/missingCreatorVersion.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/missingFormat.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/missingFormatVersion.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/missingIFID.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/missingPassageTags.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/missingPosition.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/missingScript.html +0 -14
- package/test/Twine2HTML/Twine2HTMLParser/missingSize.html +0 -35
- package/test/Twine2HTML/Twine2HTMLParser/missingStartnode.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/missingStyle.html +0 -14
- package/test/Twine2HTML/Twine2HTMLParser/missingZoom.html +0 -11
- package/test/Twine2HTML/Twine2HTMLParser/tagColors.html +0 -31
- package/test/Twine2HTML/Twine2HTMLParser/twineExample.html +0 -23
- package/test/Twine2HTML/Twine2HTMLParser/twineExample2.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/twineExample3.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/unescaping.html +0 -33
- package/test/Web/web-core-coverage.test.js +0 -175
- package/test/Web/web-core-global.test.js +0 -93
- package/test/Web/web-core.test.js +0 -156
- package/test/Web/web-exports.test.js +0 -136
- package/test/Web/web-twine1html.test.js +0 -105
- package/test/Web/web-twine2archive.test.js +0 -96
- package/test/Web/web-tws.test.js +0 -77
- package/test/Web/window.Extwee.test.js +0 -97
- package/tsconfig.json +0 -21
- package/webpack.config.js +0 -47
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jest-environment jsdom
|
|
3
|
-
*/
|
|
4
|
-
import { parse } from '../../src/Twine2ArchiveHTML/parse-web.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Mock environment to force fallback parsing since jsdom doesn't behave like browser DOMParser
|
|
8
|
-
* @param {string} content Content to parse
|
|
9
|
-
* @returns {Array} Array of Story objects
|
|
10
|
-
*/
|
|
11
|
-
function parseTwine2ArchiveHTMLWeb(content) {
|
|
12
|
-
// Force fallback mode by temporarily hiding DOMParser
|
|
13
|
-
const originalDOMParser = global.DOMParser;
|
|
14
|
-
delete global.DOMParser;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
return parse(content);
|
|
18
|
-
} finally {
|
|
19
|
-
// Restore DOMParser
|
|
20
|
-
if (originalDOMParser) {
|
|
21
|
-
global.DOMParser = originalDOMParser;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
describe('Twine2ArchiveHTML', function () {
|
|
27
|
-
describe('parse-web()', function () {
|
|
28
|
-
describe('Error handling', function () {
|
|
29
|
-
it('Should throw TypeError for non-string content', function () {
|
|
30
|
-
expect(() => { parseTwine2ArchiveHTMLWeb(null); }).toThrow('Content is not a string!');
|
|
31
|
-
expect(() => { parseTwine2ArchiveHTMLWeb(undefined); }).toThrow('Content is not a string!');
|
|
32
|
-
expect(() => { parseTwine2ArchiveHTMLWeb(123); }).toThrow('Content is not a string!');
|
|
33
|
-
expect(() => { parseTwine2ArchiveHTMLWeb({}); }).toThrow('Content is not a string!');
|
|
34
|
-
expect(() => { parseTwine2ArchiveHTMLWeb([]); }).toThrow('Content is not a string!');
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe('Warning generation', function () {
|
|
39
|
-
let originalConsoleWarn;
|
|
40
|
-
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
originalConsoleWarn = console.warn;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
afterEach(() => {
|
|
46
|
-
console.warn = originalConsoleWarn;
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('Should warn when no Twine 2 HTML content is found', function () {
|
|
50
|
-
let warningMessage = '';
|
|
51
|
-
console.warn = (msg) => { warningMessage = msg; };
|
|
52
|
-
|
|
53
|
-
const result = parseTwine2ArchiveHTMLWeb('<div>no twine content here</div>');
|
|
54
|
-
expect(warningMessage).toBe('Warning: No Twine 2 HTML content found!');
|
|
55
|
-
expect(result).toEqual([]);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('Should warn for empty string content', function () {
|
|
59
|
-
let warningMessage = '';
|
|
60
|
-
console.warn = (msg) => { warningMessage = msg; };
|
|
61
|
-
|
|
62
|
-
const result = parseTwine2ArchiveHTMLWeb('');
|
|
63
|
-
expect(warningMessage).toBe('Warning: No Twine 2 HTML content found!');
|
|
64
|
-
expect(result).toEqual([]);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
describe('Basic parsing functionality', function () {
|
|
69
|
-
it('Should parse single story from archive', function () {
|
|
70
|
-
const content = '<tw-storydata name="Test Story" ifid="12345678-1234-1234-1234-123456789012"><tw-passagedata pid="1" name="Start">Hello World</tw-passagedata></tw-storydata>';
|
|
71
|
-
|
|
72
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
73
|
-
|
|
74
|
-
expect(stories.length).toBe(1);
|
|
75
|
-
expect(stories[0].name).toBe('Test Story');
|
|
76
|
-
expect(stories[0].IFID).toBe('12345678-1234-1234-1234-123456789012');
|
|
77
|
-
expect(stories[0].size()).toBe(1);
|
|
78
|
-
|
|
79
|
-
const passage = stories[0].getPassageByName('Start');
|
|
80
|
-
expect(passage.name).toBe('Start');
|
|
81
|
-
expect(passage.text).toBe('Hello World');
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it('Should parse multiple stories from archive', function () {
|
|
85
|
-
const content = `
|
|
86
|
-
<tw-storydata name="First Story" ifid="11111111-1111-1111-1111-111111111111">
|
|
87
|
-
<tw-passagedata pid="1" name="Start">First story content</tw-passagedata>
|
|
88
|
-
</tw-storydata>
|
|
89
|
-
<tw-storydata name="Second Story" ifid="22222222-2222-2222-2222-222222222222">
|
|
90
|
-
<tw-passagedata pid="1" name="Begin">Second story content</tw-passagedata>
|
|
91
|
-
<tw-passagedata pid="2" name="Next">More content</tw-passagedata>
|
|
92
|
-
</tw-storydata>
|
|
93
|
-
`;
|
|
94
|
-
|
|
95
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
96
|
-
|
|
97
|
-
expect(stories.length).toBe(2);
|
|
98
|
-
|
|
99
|
-
// First story
|
|
100
|
-
expect(stories[0].name).toBe('First Story');
|
|
101
|
-
expect(stories[0].IFID).toBe('11111111-1111-1111-1111-111111111111');
|
|
102
|
-
expect(stories[0].size()).toBe(1);
|
|
103
|
-
expect(stories[0].getPassageByName('Start').text).toBe('First story content');
|
|
104
|
-
|
|
105
|
-
// Second story
|
|
106
|
-
expect(stories[1].name).toBe('Second Story');
|
|
107
|
-
expect(stories[1].IFID).toBe('22222222-2222-2222-2222-222222222222');
|
|
108
|
-
expect(stories[1].size()).toBe(2);
|
|
109
|
-
expect(stories[1].getPassageByName('Begin').text).toBe('Second story content');
|
|
110
|
-
expect(stories[1].getPassageByName('Next').text).toBe('More content');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('Should parse story with complex attributes', function () {
|
|
114
|
-
const content = '<tw-storydata name="Complex Story" ifid="12345678-1234-1234-1234-123456789012" creator="Twine" creator-version="2.3.9" format="Harlowe" format-version="3.1.0" startnode="2" zoom="1.5"><tw-passagedata pid="2" name="Start" position="100,200" size="150,100" tags="start important">Welcome to the story</tw-passagedata></tw-storydata>';
|
|
115
|
-
|
|
116
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
117
|
-
|
|
118
|
-
expect(stories.length).toBe(1);
|
|
119
|
-
const story = stories[0];
|
|
120
|
-
|
|
121
|
-
expect(story.name).toBe('Complex Story');
|
|
122
|
-
expect(story.creator).toBe('Twine');
|
|
123
|
-
expect(story.creatorVersion).toBe('2.3.9');
|
|
124
|
-
expect(story.format).toBe('Harlowe');
|
|
125
|
-
expect(story.formatVersion).toBe('3.1.0');
|
|
126
|
-
expect(story.start).toBe('Start');
|
|
127
|
-
expect(story.zoom).toBe(1.5);
|
|
128
|
-
|
|
129
|
-
const passage = story.getPassageByName('Start');
|
|
130
|
-
expect(passage.tags).toEqual(['start', 'important']);
|
|
131
|
-
expect(passage.metadata.position).toBe('100,200');
|
|
132
|
-
expect(passage.metadata.size).toBe('150,100');
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
describe('HTML content handling', function () {
|
|
137
|
-
it('Should handle nested HTML content in stories', function () {
|
|
138
|
-
const content = `
|
|
139
|
-
<div class="wrapper">
|
|
140
|
-
<tw-storydata name="Nested Story" ifid="12345678-1234-1234-1234-123456789012">
|
|
141
|
-
<tw-passagedata pid="1" name="Start">Story content</tw-passagedata>
|
|
142
|
-
</tw-storydata>
|
|
143
|
-
</div>
|
|
144
|
-
`;
|
|
145
|
-
|
|
146
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
147
|
-
|
|
148
|
-
expect(stories.length).toBe(1);
|
|
149
|
-
expect(stories[0].name).toBe('Nested Story');
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('Should handle stories with style elements', function () {
|
|
153
|
-
const content = '<tw-storydata name="Styled Story" ifid="12345678-1234-1234-1234-123456789012"><style>tw-story-tag-important { color: red; }</style><tw-passagedata pid="1" name="Start" tags="important">Styled content</tw-passagedata></tw-storydata>';
|
|
154
|
-
|
|
155
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
156
|
-
|
|
157
|
-
expect(stories.length).toBe(1);
|
|
158
|
-
const story = stories[0];
|
|
159
|
-
expect(story.tagColors.important).toBe('red;');
|
|
160
|
-
|
|
161
|
-
const passage = story.getPassageByName('Start');
|
|
162
|
-
expect(passage.tags).toEqual(['important']);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('Should handle stories with script elements', function () {
|
|
166
|
-
const content = '<tw-storydata name="Scripted Story" ifid="12345678-1234-1234-1234-123456789012"><script>console.log("test");</script><tw-passagedata pid="1" name="Start">Script content</tw-passagedata></tw-storydata>';
|
|
167
|
-
|
|
168
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
169
|
-
|
|
170
|
-
expect(stories.length).toBe(1);
|
|
171
|
-
expect(stories[0].name).toBe('Scripted Story');
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
describe('Malformed content handling', function () {
|
|
176
|
-
it('Should handle incomplete tw-storydata elements', function () {
|
|
177
|
-
const content = '<tw-storydata name="Incomplete" ifid="12345678-1234-1234-1234-123456789012"><tw-passagedata pid="1" name="Start">Content';
|
|
178
|
-
|
|
179
|
-
// Should not throw, but should handle gracefully
|
|
180
|
-
expect(() => parseTwine2ArchiveHTMLWeb(content)).not.toThrow();
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('Should handle mixed valid and invalid content', function () {
|
|
184
|
-
const content = `
|
|
185
|
-
<div>Random content</div>
|
|
186
|
-
<tw-storydata name="Valid Story" ifid="12345678-1234-1234-1234-123456789012">
|
|
187
|
-
<tw-passagedata pid="1" name="Start">Valid content</tw-passagedata>
|
|
188
|
-
</tw-storydata>
|
|
189
|
-
<div>More random content</div>
|
|
190
|
-
`;
|
|
191
|
-
|
|
192
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
193
|
-
|
|
194
|
-
expect(stories.length).toBe(1);
|
|
195
|
-
expect(stories[0].name).toBe('Valid Story');
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
describe('Fallback DOM parsing', function () {
|
|
200
|
-
it('Should work without DOMParser (fallback mode)', function () {
|
|
201
|
-
const originalDOMParser = global.DOMParser;
|
|
202
|
-
global.DOMParser = undefined;
|
|
203
|
-
|
|
204
|
-
try {
|
|
205
|
-
const content = '<tw-storydata name="Fallback Test" ifid="12345678-1234-1234-1234-123456789012"><tw-passagedata pid="1" name="Start">Fallback content</tw-passagedata></tw-storydata>';
|
|
206
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
207
|
-
|
|
208
|
-
expect(stories.length).toBe(1);
|
|
209
|
-
expect(stories[0].name).toBe('Fallback Test');
|
|
210
|
-
expect(stories[0].getPassageByName('Start').text).toBe('Fallback content');
|
|
211
|
-
} finally {
|
|
212
|
-
global.DOMParser = originalDOMParser;
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('Should handle multiple stories in fallback mode', function () {
|
|
217
|
-
const originalDOMParser = global.DOMParser;
|
|
218
|
-
global.DOMParser = undefined;
|
|
219
|
-
|
|
220
|
-
try {
|
|
221
|
-
const content = `
|
|
222
|
-
<tw-storydata name="First" ifid="11111111-1111-1111-1111-111111111111">
|
|
223
|
-
<tw-passagedata pid="1" name="Start">First</tw-passagedata>
|
|
224
|
-
</tw-storydata>
|
|
225
|
-
<tw-storydata name="Second" ifid="22222222-2222-2222-2222-222222222222">
|
|
226
|
-
<tw-passagedata pid="1" name="Begin">Second</tw-passagedata>
|
|
227
|
-
</tw-storydata>
|
|
228
|
-
`;
|
|
229
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
230
|
-
|
|
231
|
-
expect(stories.length).toBe(2);
|
|
232
|
-
expect(stories[0].name).toBe('First');
|
|
233
|
-
expect(stories[1].name).toBe('Second');
|
|
234
|
-
} finally {
|
|
235
|
-
global.DOMParser = originalDOMParser;
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
describe('Edge cases', function () {
|
|
241
|
-
it('Should handle empty archive content', function () {
|
|
242
|
-
const result = parseTwine2ArchiveHTMLWeb('');
|
|
243
|
-
expect(result).toEqual([]);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
it('Should handle whitespace-only content', function () {
|
|
247
|
-
const result = parseTwine2ArchiveHTMLWeb(' \n\t ');
|
|
248
|
-
expect(result).toEqual([]);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('Should handle stories with unusual character encodings', function () {
|
|
252
|
-
const content = '<tw-storydata name="Unicode Story 📚" ifid="12345678-1234-1234-1234-123456789012"><tw-passagedata pid="1" name="Start">Content with emojis 🎮 and unicode ü ñ</tw-passagedata></tw-storydata>';
|
|
253
|
-
|
|
254
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
255
|
-
|
|
256
|
-
expect(stories.length).toBe(1);
|
|
257
|
-
expect(stories[0].name).toBe('Unicode Story 📚');
|
|
258
|
-
expect(stories[0].getPassageByName('Start').text).toBe('Content with emojis 🎮 and unicode ü ñ');
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('Should handle stories with very long content', function () {
|
|
262
|
-
const longContent = 'A'.repeat(10000);
|
|
263
|
-
const content = `<tw-storydata name="Long Story" ifid="12345678-1234-1234-1234-123456789012"><tw-passagedata pid="1" name="Start">${longContent}</tw-passagedata></tw-storydata>`;
|
|
264
|
-
|
|
265
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
266
|
-
|
|
267
|
-
expect(stories.length).toBe(1);
|
|
268
|
-
expect(stories[0].getPassageByName('Start').text).toBe(longContent);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('Should handle archive with multiple identical story names but different IFIDs', function () {
|
|
272
|
-
const content = `
|
|
273
|
-
<tw-storydata name="Same Name" ifid="11111111-1111-1111-1111-111111111111">
|
|
274
|
-
<tw-passagedata pid="1" name="Start">First version</tw-passagedata>
|
|
275
|
-
</tw-storydata>
|
|
276
|
-
<tw-storydata name="Same Name" ifid="22222222-2222-2222-2222-222222222222">
|
|
277
|
-
<tw-passagedata pid="1" name="Start">Second version</tw-passagedata>
|
|
278
|
-
</tw-storydata>
|
|
279
|
-
`;
|
|
280
|
-
|
|
281
|
-
const stories = parseTwine2ArchiveHTMLWeb(content);
|
|
282
|
-
|
|
283
|
-
expect(stories.length).toBe(2);
|
|
284
|
-
expect(stories[0].name).toBe('Same Name');
|
|
285
|
-
expect(stories[1].name).toBe('Same Name');
|
|
286
|
-
expect(stories[0].IFID).toBe('11111111-1111-1111-1111-111111111111');
|
|
287
|
-
expect(stories[1].IFID).toBe('22222222-2222-2222-2222-222222222222');
|
|
288
|
-
expect(stories[0].getPassageByName('Start').text).toBe('First version');
|
|
289
|
-
expect(stories[1].getPassageByName('Start').text).toBe('Second version');
|
|
290
|
-
});
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
});
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import {jest} from '@jest/globals';
|
|
2
|
-
import { parse as parseTwine2ArchiveHTML } from '../../src/Twine2ArchiveHTML/parse.js';
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
4
|
-
|
|
5
|
-
describe('Twine2ArchiveHTML', function () {
|
|
6
|
-
describe('parse()', function () {
|
|
7
|
-
it('Should throw error when content is not string', function () {
|
|
8
|
-
expect(() => { parseTwine2ArchiveHTML(2); }).toThrow();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('Should produce two stories', function () {
|
|
12
|
-
// Read Twine 2 Archive.
|
|
13
|
-
const archiveFile = readFileSync('test/Twine2ArchiveHTML/Twine2ArchiveHTMLParser/test1.html', 'utf-8');
|
|
14
|
-
|
|
15
|
-
// Parse Twine 2 Story.
|
|
16
|
-
const stories = parseTwine2ArchiveHTML(archiveFile);
|
|
17
|
-
|
|
18
|
-
// Expect two stories.
|
|
19
|
-
expect(stories.length).toBe(2);
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
describe('Warnings', function () {
|
|
24
|
-
beforeEach(() => {
|
|
25
|
-
// Mock console.warn.
|
|
26
|
-
jest.spyOn(console, 'warn').mockImplementation();
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
afterEach(() => {
|
|
30
|
-
// Restore all mocks.
|
|
31
|
-
jest.restoreAllMocks();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('Should produce warning when no Twine 2 HTML content is found', function () {
|
|
35
|
-
// Parse Twine 2 Story.
|
|
36
|
-
parseTwine2ArchiveHTML('');
|
|
37
|
-
|
|
38
|
-
// Expect warning.
|
|
39
|
-
expect(console.warn).toHaveBeenCalledWith('Warning: No Twine 2 HTML content found!');
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
<tw-storydata name="Test1" startnode="1" creator="extwee" creator-version="2.2.0" ifid="5216624F-49AD-429F-A563-4F026CC16345" zoom="0" format="" format-version="" options hidden>
|
|
2
|
-
<style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css"></style>
|
|
3
|
-
<script role="script" id="twine-user-script" type="text/twine-javascript"></script>
|
|
4
|
-
<tw-passagedata pid="1" name="Start" tags="" >Work</tw-passagedata>
|
|
5
|
-
</tw-storydata>
|
|
6
|
-
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
<tw-storydata name="Untitled Story 6" startnode="1" creator="Twine" creator-version="2.7.1" format="Harlowe" format-version="3.3.7" ifid="A757E549-1642-4CAC-95A5-66B67A85C268" 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="Untitled Passage" tags="" position="900,400" size="100,100"></tw-passagedata><tw-passagedata pid="2" name="Untitled Passage 1" tags="" position="1025,400" size="100,100"></tw-passagedata></tw-storydata>
|
|
2
|
-
|
|
3
|
-
<tw-storydata name="Untitled Story" startnode="1" creator="Twine" creator-version="2.7.1" format="SugarCube" format-version="2.36.1" ifid="C110B59A-C866-46D5-9BE7-592BD6750E11" 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="Untitled Passage" tags="" position="525,200" size="100,100"></tw-passagedata></tw-storydata>
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { parse as parseStoryFormat } from '../../src/StoryFormat/parse.js';
|
|
2
|
-
import { parse as parseTwine2HTML } from '../../src/Twine2HTML/parse.js';
|
|
3
|
-
import { compile as compileTwine2HTML } from '../../src/Twine2HTML/compile.js';
|
|
4
|
-
import { Story } from '../../src/Story.js';
|
|
5
|
-
import Passage from '../../src/Passage.js';
|
|
6
|
-
import StoryFormat from '../../src/StoryFormat.js';
|
|
7
|
-
import { generate as generateIFID } from '../../src/IFID/generate.js';
|
|
8
|
-
import { readFileSync } from 'node:fs';
|
|
9
|
-
|
|
10
|
-
describe('Twine2HTMLCompiler', () => {
|
|
11
|
-
describe('compile()', () => {
|
|
12
|
-
it('story should be instanceof Story', () => {
|
|
13
|
-
expect(() => { compileTwine2HTML({}); }).toThrow();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('storyFormat should be instanceof StoryFormat', () => {
|
|
17
|
-
const s = new Story();
|
|
18
|
-
expect(() => { compileTwine2HTML(s, {}); }).toThrow();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('Should write one and two-tag passages', () => {
|
|
22
|
-
// Read HTML.
|
|
23
|
-
const fr = readFileSync('test/Twine2HTML/Twine2HTMLCompiler/TestTags.html', 'utf-8');
|
|
24
|
-
|
|
25
|
-
// Parse HTML.
|
|
26
|
-
const story = parseTwine2HTML(fr);
|
|
27
|
-
|
|
28
|
-
// Read StoryFormat.
|
|
29
|
-
const fr2 = readFileSync('test/Twine2HTML/Twine2HTMLCompiler/format.js', 'utf-8');
|
|
30
|
-
|
|
31
|
-
// Parse StoryFormat.
|
|
32
|
-
const storyFormat = parseStoryFormat(fr2);
|
|
33
|
-
|
|
34
|
-
// Write HTML.
|
|
35
|
-
const fr3 = compileTwine2HTML(story, storyFormat);
|
|
36
|
-
|
|
37
|
-
// Parse HTML.
|
|
38
|
-
const story2 = parseTwine2HTML(fr3);
|
|
39
|
-
|
|
40
|
-
let tags = '';
|
|
41
|
-
let tags2 = '';
|
|
42
|
-
|
|
43
|
-
// Combine contents of tags.
|
|
44
|
-
story.passages.forEach((p) => {
|
|
45
|
-
tags += p.tags.join('');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// Combine contents of tags.
|
|
49
|
-
story2.passages.forEach((p) => {
|
|
50
|
-
tags2 += p.tags.join('');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Test combination tags.
|
|
54
|
-
// They should be the same.
|
|
55
|
-
expect(tags).toBe(tags2);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('Throw error if IFID does not exist', () => {
|
|
59
|
-
// Create a new story.
|
|
60
|
-
const story = new Story();
|
|
61
|
-
|
|
62
|
-
// Create a passage.
|
|
63
|
-
story.addPassage(new Passage('A'));
|
|
64
|
-
|
|
65
|
-
// Read StoryFormat.
|
|
66
|
-
const fr2 = readFileSync('test/Twine2HTML/Twine2HTMLCompiler/format.js', 'utf-8');
|
|
67
|
-
|
|
68
|
-
// Parse StoryFormat.
|
|
69
|
-
const storyFormat = parseStoryFormat(fr2);
|
|
70
|
-
|
|
71
|
-
expect(() => {
|
|
72
|
-
compileTwine2HTML(story, storyFormat);
|
|
73
|
-
}).toThrow();
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('Throw error if starting passage property does not exist', () => {
|
|
77
|
-
// Create a new story.
|
|
78
|
-
const story = new Story();
|
|
79
|
-
|
|
80
|
-
// Create a passage.
|
|
81
|
-
story.addPassage(new Passage('A'));
|
|
82
|
-
|
|
83
|
-
// Create StoryTitle
|
|
84
|
-
story.addPassage(new Passage('StoryTitle', 'Name'));
|
|
85
|
-
|
|
86
|
-
// Set a passage that doesn't exist
|
|
87
|
-
story.start = 'Nope';
|
|
88
|
-
|
|
89
|
-
// Read StoryFormat.
|
|
90
|
-
const fr2 = readFileSync('test/Twine2HTML/Twine2HTMLCompiler/format.js', 'utf-8');
|
|
91
|
-
|
|
92
|
-
// Parse StoryFormat.
|
|
93
|
-
const storyFormat = parseStoryFormat(fr2);
|
|
94
|
-
|
|
95
|
-
// Throws error.
|
|
96
|
-
expect(() => {
|
|
97
|
-
compileTwine2HTML(story, storyFormat);
|
|
98
|
-
}).toThrow();
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('Throw error if source is empty string in StoryFormat', () => {
|
|
102
|
-
// Create a new story.
|
|
103
|
-
const story = new Story();
|
|
104
|
-
|
|
105
|
-
// Create StoryFormat.
|
|
106
|
-
const sf = new StoryFormat();
|
|
107
|
-
|
|
108
|
-
// Set source to empty string.
|
|
109
|
-
sf.source = '';
|
|
110
|
-
|
|
111
|
-
// Throws error.
|
|
112
|
-
expect(() => {
|
|
113
|
-
compileTwine2HTML(story, sf);
|
|
114
|
-
}).toThrow();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('Throw error if story name is empty string', () => {
|
|
118
|
-
// Create a new story.
|
|
119
|
-
const story = new Story();
|
|
120
|
-
|
|
121
|
-
// Create StoryFormat.
|
|
122
|
-
const sf = new StoryFormat();
|
|
123
|
-
|
|
124
|
-
// Set source to non-empty string.
|
|
125
|
-
sf.source = 'Test';
|
|
126
|
-
|
|
127
|
-
// Generate IFID (to avoid throwing error).
|
|
128
|
-
story.IFID = generateIFID();
|
|
129
|
-
|
|
130
|
-
// Set story name to empty string.
|
|
131
|
-
story.name = '';
|
|
132
|
-
|
|
133
|
-
// Throws error.
|
|
134
|
-
expect(() => {
|
|
135
|
-
compileTwine2HTML(story, sf);
|
|
136
|
-
}).toThrow();
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
});
|