extwee 2.3.11 → 2.3.12

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.
Files changed (179) hide show
  1. package/CHANGELOG.md +219 -0
  2. package/CONTRIBUTING.md +305 -0
  3. package/README.md +16 -0
  4. package/build/extwee.core.min.js +1 -1
  5. package/build/extwee.twine1html.min.js +1 -1
  6. package/build/extwee.twine2archive.min.js +1 -1
  7. package/build/extwee.tws.min.js +1 -1
  8. package/package.json +8 -5
  9. package/src/Story.js +2 -2
  10. package/types/src/Story.d.ts +1 -1
  11. package/.github/FUNDING.yml +0 -3
  12. package/.github/codeql-analysis.yml +0 -51
  13. package/.github/dependabot.yml +0 -11
  14. package/.github/workflows/dependabot-automerge.yml +0 -23
  15. package/.github/workflows/nodejs.yml +0 -28
  16. package/.travis.yml +0 -13
  17. package/babel.config.json +0 -18
  18. package/docs/.nojekyll +0 -0
  19. package/docs/README.md +0 -224
  20. package/docs/_sidebar.md +0 -19
  21. package/docs/build/extwee.core.min.js +0 -1
  22. package/docs/build/extwee.twine1html.min.js +0 -1
  23. package/docs/build/extwee.twine2archive.min.js +0 -1
  24. package/docs/build/extwee.tws.min.js +0 -1
  25. package/docs/demos/compiler/extwee.core.min.js +0 -1
  26. package/docs/demos/compiler/index.css +0 -105
  27. package/docs/demos/compiler/index.html +0 -359
  28. package/docs/demos/decompile/extwee.core.min.js +0 -1
  29. package/docs/demos/decompile/index.css +0 -584
  30. package/docs/demos/decompile/index.html +0 -468
  31. package/docs/examples/dynamicPassages.md +0 -28
  32. package/docs/examples/jsonToTwee.md +0 -23
  33. package/docs/examples/twsToTwee.md +0 -25
  34. package/docs/formats/json.md +0 -17
  35. package/docs/formats/twee.md +0 -13
  36. package/docs/formats/twine1HTML.md +0 -13
  37. package/docs/formats/twine2ArchiveHTML.md +0 -13
  38. package/docs/formats/twine2HTML.md +0 -13
  39. package/docs/formats/tws.md +0 -9
  40. package/docs/index.html +0 -26
  41. package/docs/install/npm.md +0 -16
  42. package/docs/install/npx.md +0 -79
  43. package/docs/objects/passage.md +0 -47
  44. package/docs/objects/story.md +0 -69
  45. package/docs/objects/storyformat.md +0 -27
  46. package/eslint.config.js +0 -28
  47. package/extwee.config.json +0 -6
  48. package/extwee.config.md +0 -67
  49. package/jest.config.json +0 -5
  50. package/test/CLI/CLI.test.js +0 -49
  51. package/test/CLI/files/example.json +0 -1
  52. package/test/CLI/files/example6.twee +0 -22
  53. package/test/CLI/files/harlowe.js +0 -3
  54. package/test/CLI/files/input.html +0 -47
  55. package/test/CLI/files/output/test.twee +0 -0
  56. package/test/CLI/files/test.twee +0 -18
  57. package/test/CLI/files/tweeExample.twee +0 -17
  58. package/test/CLI/files/twine1/LICENSE.txt +0 -32
  59. package/test/CLI/files/twine1/code.js +0 -5
  60. package/test/CLI/files/twine1/engine.js +0 -43
  61. package/test/CLI/files/twine1/header.html +0 -325
  62. package/test/CLI/files/twine1Test.html +0 -371
  63. package/test/CLI/files/twineExample.html +0 -16
  64. package/test/Config/Config.test.js +0 -76
  65. package/test/Config/files/empty.json +0 -3
  66. package/test/Config/files/full.json +0 -8
  67. package/test/Config/files/invalid.json +0 -1
  68. package/test/Config/files/valid.json +0 -6
  69. package/test/Config/isDirectory.test.js +0 -50
  70. package/test/Config/isFile.test.js +0 -53
  71. package/test/Config/loadStoryFormat.test.js +0 -117
  72. package/test/Config/readDirectories.test.js +0 -78
  73. package/test/IFID/IFID.Generate.test.js +0 -10
  74. package/test/JSON/JSON.Parse.test.js +0 -316
  75. package/test/Objects/Passage.test.js +0 -274
  76. package/test/Objects/SnowmanCompatibility.test.js +0 -111
  77. package/test/Objects/Story.test.js +0 -1075
  78. package/test/Objects/StoryFormat.test.js +0 -219
  79. package/test/Roundtrip/Files/Example1.html +0 -64
  80. package/test/Roundtrip/Files/LICENSE +0 -19
  81. package/test/Roundtrip/Files/example1.twee +0 -10
  82. package/test/Roundtrip/Files/example2.twee +0 -27
  83. package/test/Roundtrip/Files/example4.twee +0 -27
  84. package/test/Roundtrip/Files/harlowe.js +0 -3
  85. package/test/Roundtrip/Files/round.html +0 -49
  86. package/test/Roundtrip/Roundtrip.test.js +0 -54
  87. package/test/StoryFormat/StoryFormat.Parse.test.js +0 -479
  88. package/test/TWS/Parse.test.js +0 -56
  89. package/test/TWS/TWSParser/Example5.tws +0 -414
  90. package/test/TWS/TWSParser/noscale.tws +0 -0
  91. package/test/TWS/TWSParser/nostory.tws +0 -0
  92. package/test/Twee/Twee.Escaping.test.js +0 -200
  93. package/test/Twee/Twee.Parse.test.js +0 -108
  94. package/test/Twee/TweeParser/cursed.twee +0 -16
  95. package/test/Twee/TweeParser/cycling.twee +0 -75
  96. package/test/Twee/TweeParser/emptytags.twee +0 -2
  97. package/test/Twee/TweeParser/example.twee +0 -32
  98. package/test/Twee/TweeParser/malformed.twee +0 -2
  99. package/test/Twee/TweeParser/missing.twee +0 -19
  100. package/test/Twee/TweeParser/multipleScriptPassages.twee +0 -19
  101. package/test/Twee/TweeParser/multipleStyleTag.twee +0 -19
  102. package/test/Twee/TweeParser/multipletags.twee +0 -10
  103. package/test/Twee/TweeParser/noTitle.twee +0 -2
  104. package/test/Twee/TweeParser/notes.twee +0 -16
  105. package/test/Twee/TweeParser/pasagemetadataerror.twee +0 -2
  106. package/test/Twee/TweeParser/scriptPassage.twee +0 -16
  107. package/test/Twee/TweeParser/singletag.twee +0 -13
  108. package/test/Twee/TweeParser/start.twee +0 -2
  109. package/test/Twee/TweeParser/startMetadata.twee +0 -14
  110. package/test/Twee/TweeParser/storydataerror.twee +0 -25
  111. package/test/Twee/TweeParser/style.twee +0 -16
  112. package/test/Twee/TweeParser/stylePassage.twee +0 -16
  113. package/test/Twee/TweeParser/test.twee +0 -25
  114. package/test/Twine1HTML/Twine1HTML.Compile.test.js +0 -180
  115. package/test/Twine1HTML/Twine1HTML.Parse.Web.test.js +0 -484
  116. package/test/Twine1HTML/Twine1HTML.Parse.test.js +0 -183
  117. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/LICENSE +0 -674
  118. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/engine.js +0 -43
  119. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/jquery.js +0 -4
  120. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/modernizr.js +0 -4
  121. package/test/Twine1HTML/Twine1HTMLCompiler/engineTest.html +0 -1
  122. package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/LICENSE +0 -32
  123. package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/code.js +0 -4
  124. package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/header.html +0 -327
  125. package/test/Twine1HTML/Twine1HTMLCompiler/test.html +0 -0
  126. package/test/Twine1HTML/Twine1HTMLCompiler/test1.html +0 -6
  127. package/test/Twine1HTML/Twine1HTMLCompiler/test2.html +0 -6
  128. package/test/Twine1HTML/Twine1HTMLCompiler/test3.html +0 -43
  129. package/test/Twine1HTML/Twine1HTMLCompiler/test4.html +0 -372
  130. package/test/Twine1HTML/Twine1HTMLCompiler/test5.html +0 -372
  131. package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Compile.test.js +0 -35
  132. package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.Web.test.js +0 -293
  133. package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +0 -42
  134. package/test/Twine2ArchiveHTML/Twine2ArchiveHTMLCompiler/test1.html +0 -6
  135. package/test/Twine2ArchiveHTML/Twine2ArchiveHTMLParser/test1.html +0 -3
  136. package/test/Twine2HTML/Twine2HTML.Compile.test.js +0 -139
  137. package/test/Twine2HTML/Twine2HTML.Parse.Web.test.js +0 -329
  138. package/test/Twine2HTML/Twine2HTML.Parse.test.js +0 -192
  139. package/test/Twine2HTML/Twine2HTMLCompiler/TestTags.html +0 -42
  140. package/test/Twine2HTML/Twine2HTMLCompiler/creator.html +0 -50
  141. package/test/Twine2HTML/Twine2HTMLCompiler/example6.twee +0 -16
  142. package/test/Twine2HTML/Twine2HTMLCompiler/format.js +0 -9
  143. package/test/Twine2HTML/Twine2HTMLCompiler/missingStoryTitle.twee +0 -29
  144. package/test/Twine2HTML/Twine2HTMLCompiler/test11.html +0 -121
  145. package/test/Twine2HTML/Twine2HTMLCompiler/test2.html +0 -58
  146. package/test/Twine2HTML/Twine2HTMLCompiler/test3.html +0 -49
  147. package/test/Twine2HTML/Twine2HTMLCompiler/test4.html +0 -50
  148. package/test/Twine2HTML/Twine2HTMLCompiler/test6.html +0 -49
  149. package/test/Twine2HTML/Twine2HTMLParser/Example1.html +0 -53
  150. package/test/Twine2HTML/Twine2HTMLParser/Tags.html +0 -15
  151. package/test/Twine2HTML/Twine2HTMLParser/lyingStartnode.html +0 -15
  152. package/test/Twine2HTML/Twine2HTMLParser/lyingTagColors.html +0 -48
  153. package/test/Twine2HTML/Twine2HTMLParser/missingCreator.html +0 -11
  154. package/test/Twine2HTML/Twine2HTMLParser/missingCreatorVersion.html +0 -11
  155. package/test/Twine2HTML/Twine2HTMLParser/missingFormat.html +0 -11
  156. package/test/Twine2HTML/Twine2HTMLParser/missingFormatVersion.html +0 -11
  157. package/test/Twine2HTML/Twine2HTMLParser/missingIFID.html +0 -11
  158. package/test/Twine2HTML/Twine2HTMLParser/missingPassageTags.html +0 -15
  159. package/test/Twine2HTML/Twine2HTMLParser/missingPosition.html +0 -15
  160. package/test/Twine2HTML/Twine2HTMLParser/missingScript.html +0 -14
  161. package/test/Twine2HTML/Twine2HTMLParser/missingSize.html +0 -35
  162. package/test/Twine2HTML/Twine2HTMLParser/missingStartnode.html +0 -11
  163. package/test/Twine2HTML/Twine2HTMLParser/missingStyle.html +0 -14
  164. package/test/Twine2HTML/Twine2HTMLParser/missingZoom.html +0 -11
  165. package/test/Twine2HTML/Twine2HTMLParser/tagColors.html +0 -31
  166. package/test/Twine2HTML/Twine2HTMLParser/twineExample.html +0 -23
  167. package/test/Twine2HTML/Twine2HTMLParser/twineExample2.html +0 -15
  168. package/test/Twine2HTML/Twine2HTMLParser/twineExample3.html +0 -15
  169. package/test/Twine2HTML/Twine2HTMLParser/unescaping.html +0 -33
  170. package/test/Web/web-core-coverage.test.js +0 -175
  171. package/test/Web/web-core-global.test.js +0 -93
  172. package/test/Web/web-core.test.js +0 -156
  173. package/test/Web/web-exports.test.js +0 -136
  174. package/test/Web/web-twine1html.test.js +0 -105
  175. package/test/Web/web-twine2archive.test.js +0 -96
  176. package/test/Web/web-tws.test.js +0 -77
  177. package/test/Web/window.Extwee.test.js +0 -97
  178. package/tsconfig.json +0 -21
  179. 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
- });