extwee 2.3.10 → 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 (180) 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/Passage.js +8 -9
  10. package/src/Story.js +2 -2
  11. package/types/src/Story.d.ts +1 -1
  12. package/.github/FUNDING.yml +0 -3
  13. package/.github/codeql-analysis.yml +0 -51
  14. package/.github/dependabot.yml +0 -11
  15. package/.github/workflows/dependabot-automerge.yml +0 -23
  16. package/.github/workflows/nodejs.yml +0 -28
  17. package/.travis.yml +0 -13
  18. package/babel.config.json +0 -18
  19. package/docs/.nojekyll +0 -0
  20. package/docs/README.md +0 -224
  21. package/docs/_sidebar.md +0 -19
  22. package/docs/build/extwee.core.min.js +0 -1
  23. package/docs/build/extwee.twine1html.min.js +0 -1
  24. package/docs/build/extwee.twine2archive.min.js +0 -1
  25. package/docs/build/extwee.tws.min.js +0 -1
  26. package/docs/demos/compiler/extwee.core.min.js +0 -1
  27. package/docs/demos/compiler/index.css +0 -105
  28. package/docs/demos/compiler/index.html +0 -359
  29. package/docs/demos/decompile/extwee.core.min.js +0 -1
  30. package/docs/demos/decompile/index.css +0 -584
  31. package/docs/demos/decompile/index.html +0 -468
  32. package/docs/examples/dynamicPassages.md +0 -28
  33. package/docs/examples/jsonToTwee.md +0 -23
  34. package/docs/examples/twsToTwee.md +0 -25
  35. package/docs/formats/json.md +0 -17
  36. package/docs/formats/twee.md +0 -13
  37. package/docs/formats/twine1HTML.md +0 -13
  38. package/docs/formats/twine2ArchiveHTML.md +0 -13
  39. package/docs/formats/twine2HTML.md +0 -13
  40. package/docs/formats/tws.md +0 -9
  41. package/docs/index.html +0 -26
  42. package/docs/install/npm.md +0 -16
  43. package/docs/install/npx.md +0 -79
  44. package/docs/objects/passage.md +0 -47
  45. package/docs/objects/story.md +0 -69
  46. package/docs/objects/storyformat.md +0 -27
  47. package/eslint.config.js +0 -28
  48. package/extwee.config.json +0 -6
  49. package/extwee.config.md +0 -67
  50. package/jest.config.json +0 -5
  51. package/test/CLI/CLI.test.js +0 -49
  52. package/test/CLI/files/example.json +0 -1
  53. package/test/CLI/files/example6.twee +0 -22
  54. package/test/CLI/files/harlowe.js +0 -3
  55. package/test/CLI/files/input.html +0 -47
  56. package/test/CLI/files/output/test.twee +0 -0
  57. package/test/CLI/files/test.twee +0 -18
  58. package/test/CLI/files/tweeExample.twee +0 -17
  59. package/test/CLI/files/twine1/LICENSE.txt +0 -32
  60. package/test/CLI/files/twine1/code.js +0 -5
  61. package/test/CLI/files/twine1/engine.js +0 -43
  62. package/test/CLI/files/twine1/header.html +0 -325
  63. package/test/CLI/files/twine1Test.html +0 -371
  64. package/test/CLI/files/twineExample.html +0 -16
  65. package/test/Config/Config.test.js +0 -76
  66. package/test/Config/files/empty.json +0 -3
  67. package/test/Config/files/full.json +0 -8
  68. package/test/Config/files/invalid.json +0 -1
  69. package/test/Config/files/valid.json +0 -6
  70. package/test/Config/isDirectory.test.js +0 -50
  71. package/test/Config/isFile.test.js +0 -53
  72. package/test/Config/loadStoryFormat.test.js +0 -117
  73. package/test/Config/readDirectories.test.js +0 -78
  74. package/test/IFID/IFID.Generate.test.js +0 -10
  75. package/test/JSON/JSON.Parse.test.js +0 -316
  76. package/test/Objects/Passage.test.js +0 -270
  77. package/test/Objects/SnowmanCompatibility.test.js +0 -125
  78. package/test/Objects/Story.test.js +0 -1075
  79. package/test/Objects/StoryFormat.test.js +0 -219
  80. package/test/Roundtrip/Files/Example1.html +0 -64
  81. package/test/Roundtrip/Files/LICENSE +0 -19
  82. package/test/Roundtrip/Files/example1.twee +0 -10
  83. package/test/Roundtrip/Files/example2.twee +0 -27
  84. package/test/Roundtrip/Files/example4.twee +0 -27
  85. package/test/Roundtrip/Files/harlowe.js +0 -3
  86. package/test/Roundtrip/Files/round.html +0 -49
  87. package/test/Roundtrip/Roundtrip.test.js +0 -54
  88. package/test/StoryFormat/StoryFormat.Parse.test.js +0 -479
  89. package/test/TWS/Parse.test.js +0 -56
  90. package/test/TWS/TWSParser/Example5.tws +0 -414
  91. package/test/TWS/TWSParser/noscale.tws +0 -0
  92. package/test/TWS/TWSParser/nostory.tws +0 -0
  93. package/test/Twee/Twee.Escaping.test.js +0 -200
  94. package/test/Twee/Twee.Parse.test.js +0 -108
  95. package/test/Twee/TweeParser/cursed.twee +0 -16
  96. package/test/Twee/TweeParser/cycling.twee +0 -75
  97. package/test/Twee/TweeParser/emptytags.twee +0 -2
  98. package/test/Twee/TweeParser/example.twee +0 -32
  99. package/test/Twee/TweeParser/malformed.twee +0 -2
  100. package/test/Twee/TweeParser/missing.twee +0 -19
  101. package/test/Twee/TweeParser/multipleScriptPassages.twee +0 -19
  102. package/test/Twee/TweeParser/multipleStyleTag.twee +0 -19
  103. package/test/Twee/TweeParser/multipletags.twee +0 -10
  104. package/test/Twee/TweeParser/noTitle.twee +0 -2
  105. package/test/Twee/TweeParser/notes.twee +0 -16
  106. package/test/Twee/TweeParser/pasagemetadataerror.twee +0 -2
  107. package/test/Twee/TweeParser/scriptPassage.twee +0 -16
  108. package/test/Twee/TweeParser/singletag.twee +0 -13
  109. package/test/Twee/TweeParser/start.twee +0 -2
  110. package/test/Twee/TweeParser/startMetadata.twee +0 -14
  111. package/test/Twee/TweeParser/storydataerror.twee +0 -25
  112. package/test/Twee/TweeParser/style.twee +0 -16
  113. package/test/Twee/TweeParser/stylePassage.twee +0 -16
  114. package/test/Twee/TweeParser/test.twee +0 -25
  115. package/test/Twine1HTML/Twine1HTML.Compile.test.js +0 -180
  116. package/test/Twine1HTML/Twine1HTML.Parse.Web.test.js +0 -484
  117. package/test/Twine1HTML/Twine1HTML.Parse.test.js +0 -183
  118. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/LICENSE +0 -674
  119. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/engine.js +0 -43
  120. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/jquery.js +0 -4
  121. package/test/Twine1HTML/Twine1HTMLCompiler/Twine1/modernizr.js +0 -4
  122. package/test/Twine1HTML/Twine1HTMLCompiler/engineTest.html +0 -1
  123. package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/LICENSE +0 -32
  124. package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/code.js +0 -4
  125. package/test/Twine1HTML/Twine1HTMLCompiler/jonah-1.4.2/header.html +0 -327
  126. package/test/Twine1HTML/Twine1HTMLCompiler/test.html +0 -0
  127. package/test/Twine1HTML/Twine1HTMLCompiler/test1.html +0 -6
  128. package/test/Twine1HTML/Twine1HTMLCompiler/test2.html +0 -6
  129. package/test/Twine1HTML/Twine1HTMLCompiler/test3.html +0 -43
  130. package/test/Twine1HTML/Twine1HTMLCompiler/test4.html +0 -372
  131. package/test/Twine1HTML/Twine1HTMLCompiler/test5.html +0 -372
  132. package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Compile.test.js +0 -35
  133. package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.Web.test.js +0 -293
  134. package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +0 -42
  135. package/test/Twine2ArchiveHTML/Twine2ArchiveHTMLCompiler/test1.html +0 -6
  136. package/test/Twine2ArchiveHTML/Twine2ArchiveHTMLParser/test1.html +0 -3
  137. package/test/Twine2HTML/Twine2HTML.Compile.test.js +0 -139
  138. package/test/Twine2HTML/Twine2HTML.Parse.Web.test.js +0 -329
  139. package/test/Twine2HTML/Twine2HTML.Parse.test.js +0 -192
  140. package/test/Twine2HTML/Twine2HTMLCompiler/TestTags.html +0 -42
  141. package/test/Twine2HTML/Twine2HTMLCompiler/creator.html +0 -50
  142. package/test/Twine2HTML/Twine2HTMLCompiler/example6.twee +0 -16
  143. package/test/Twine2HTML/Twine2HTMLCompiler/format.js +0 -9
  144. package/test/Twine2HTML/Twine2HTMLCompiler/missingStoryTitle.twee +0 -29
  145. package/test/Twine2HTML/Twine2HTMLCompiler/test11.html +0 -121
  146. package/test/Twine2HTML/Twine2HTMLCompiler/test2.html +0 -58
  147. package/test/Twine2HTML/Twine2HTMLCompiler/test3.html +0 -49
  148. package/test/Twine2HTML/Twine2HTMLCompiler/test4.html +0 -50
  149. package/test/Twine2HTML/Twine2HTMLCompiler/test6.html +0 -49
  150. package/test/Twine2HTML/Twine2HTMLParser/Example1.html +0 -53
  151. package/test/Twine2HTML/Twine2HTMLParser/Tags.html +0 -15
  152. package/test/Twine2HTML/Twine2HTMLParser/lyingStartnode.html +0 -15
  153. package/test/Twine2HTML/Twine2HTMLParser/lyingTagColors.html +0 -48
  154. package/test/Twine2HTML/Twine2HTMLParser/missingCreator.html +0 -11
  155. package/test/Twine2HTML/Twine2HTMLParser/missingCreatorVersion.html +0 -11
  156. package/test/Twine2HTML/Twine2HTMLParser/missingFormat.html +0 -11
  157. package/test/Twine2HTML/Twine2HTMLParser/missingFormatVersion.html +0 -11
  158. package/test/Twine2HTML/Twine2HTMLParser/missingIFID.html +0 -11
  159. package/test/Twine2HTML/Twine2HTMLParser/missingPassageTags.html +0 -15
  160. package/test/Twine2HTML/Twine2HTMLParser/missingPosition.html +0 -15
  161. package/test/Twine2HTML/Twine2HTMLParser/missingScript.html +0 -14
  162. package/test/Twine2HTML/Twine2HTMLParser/missingSize.html +0 -35
  163. package/test/Twine2HTML/Twine2HTMLParser/missingStartnode.html +0 -11
  164. package/test/Twine2HTML/Twine2HTMLParser/missingStyle.html +0 -14
  165. package/test/Twine2HTML/Twine2HTMLParser/missingZoom.html +0 -11
  166. package/test/Twine2HTML/Twine2HTMLParser/tagColors.html +0 -31
  167. package/test/Twine2HTML/Twine2HTMLParser/twineExample.html +0 -23
  168. package/test/Twine2HTML/Twine2HTMLParser/twineExample2.html +0 -15
  169. package/test/Twine2HTML/Twine2HTMLParser/twineExample3.html +0 -15
  170. package/test/Twine2HTML/Twine2HTMLParser/unescaping.html +0 -33
  171. package/test/Web/web-core-coverage.test.js +0 -175
  172. package/test/Web/web-core-global.test.js +0 -93
  173. package/test/Web/web-core.test.js +0 -156
  174. package/test/Web/web-exports.test.js +0 -136
  175. package/test/Web/web-twine1html.test.js +0 -105
  176. package/test/Web/web-twine2archive.test.js +0 -96
  177. package/test/Web/web-tws.test.js +0 -77
  178. package/test/Web/window.Extwee.test.js +0 -97
  179. package/tsconfig.json +0 -21
  180. package/webpack.config.js +0 -47
@@ -1,270 +0,0 @@
1
- import Passage from '../../src/Passage.js';
2
- import { parse as HTMLParser } from 'node-html-parser';
3
-
4
- describe('Passage', () => {
5
- describe('constructor()', () => {
6
- it('Set default values', () => {
7
- const p = new Passage();
8
- expect(p.name).toBe('');
9
- expect(p.tags).toHaveLength(0);
10
- expect(p.text).toBe('');
11
- expect(typeof p.metadata).toBe('object');
12
- });
13
- });
14
-
15
- describe('name', () => {
16
- it('Set name', () => {
17
- const p = new Passage();
18
- p.name = 'New';
19
- expect(p.name).toBe('New');
20
- });
21
-
22
- it('Throw error if name is not String', () => {
23
- const p = new Passage();
24
- expect(() => {
25
- p.name = 1;
26
- }).toThrow();
27
- });
28
- });
29
-
30
- describe('tags', () => {
31
- it('Set tags', () => {
32
- const p = new Passage();
33
- p.tags = ['tag'];
34
- expect(p.tags).toHaveLength(1);
35
- });
36
-
37
- it('Throw error if tags is not Array', () => {
38
- const p = new Passage();
39
- expect(() => {
40
- p.tags = 1;
41
- }).toThrow();
42
- });
43
- });
44
-
45
- describe('metadata', () => {
46
- it('Set metadata', () => {
47
- const p = new Passage();
48
- p.metadata = { position: '100,100' };
49
- expect(p.metadata).toEqual({ position: '100,100' });
50
- });
51
-
52
- it('Throw error if metadata is not an Object', () => {
53
- const p = new Passage();
54
- expect(() => {
55
- p.metadata = 1;
56
- }).toThrow();
57
- });
58
- });
59
-
60
- describe('text', () => {
61
- it('Set text', () => {
62
- const p = new Passage();
63
- p.text = 'New';
64
- expect(p.text).toBe('New');
65
- });
66
-
67
- it('Throw error if text is not a String', () => {
68
- const p = new Passage();
69
- expect(() => {
70
- p.text = 1;
71
- }).toThrow();
72
- });
73
- });
74
-
75
- describe('toTwee()', () => {
76
- it('Create name string', () => {
77
- const p = new Passage('Name', 'Test');
78
- expect(p.toTwee()).toBe(':: Name\nTest\n\n');
79
- });
80
- it('Create tags string', () => {
81
- const p = new Passage('Name', 'Test', ['tags', 'another']);
82
- expect(p.toTwee()).toBe(':: Name [tags another]\nTest\n\n');
83
- });
84
- it('Create metadata string', () => {
85
- const p = new Passage('Name', 'Test', ['tags', 'another'], { position: '100,100' });
86
- expect(p.toTwee()).toBe(':: Name [tags another] {"position":"100,100"}\nTest\n\n');
87
- });
88
- });
89
-
90
- describe('toJSON()', function () {
91
- it('Should hold default values', function () {
92
- const p = new Passage();
93
- const r = JSON.parse(p.toJSON());
94
- expect(r.name).toBe('');
95
- expect(r.text).toBe('');
96
- expect(r.tags.length).toBe(0);
97
- expect(Object.keys(r.metadata).length).toBe(0);
98
- });
99
- });
100
-
101
- describe('toTwine2HTML()', function () {
102
- let p = null;
103
- let result = null;
104
-
105
- beforeEach(() => {
106
- p = new Passage('Test', 'Word', ['tag1'], { some: 'thing' });
107
- result = p.toTwine2HTML();
108
- });
109
-
110
- it('Should contain default PID', function () {
111
- expect(result.includes('pid="1"')).toBe(true);
112
- });
113
-
114
- it('Should include name', function () {
115
- expect(result.includes('name="Test"')).toBe(true);
116
- });
117
-
118
- it('Should include single tag', function () {
119
- expect(result.includes('tags="tag1"')).toBe(true);
120
- });
121
-
122
- it('Should include multiple tags', function () {
123
- p.tags = ['tag1', 'tag2'];
124
- result = p.toTwine2HTML();
125
- expect(result.includes('tags="tag1 tag2"')).toBe(true);
126
- });
127
-
128
- it('Should include position, if it exists', function () {
129
- p.metadata = { position: '102,99' };
130
- result = p.toTwine2HTML();
131
- expect(result.includes('position="102,99"')).toBe(true);
132
- });
133
-
134
- it('Should include size, if it exists', function () {
135
- p.metadata = { size: '100,100' };
136
- result = p.toTwine2HTML();
137
- expect(result.includes('size="100,100"')).toBe(true);
138
- });
139
- });
140
-
141
- describe('toTwine1HTML()', function () {
142
- let p = null;
143
- let result = null;
144
-
145
- beforeEach(() => {
146
- p = new Passage('Test', 'Word', ['tag1'], { position: '12, 12' });
147
- result = p.toTwine1HTML();
148
- });
149
-
150
- it('Should include tiddler', function () {
151
- expect(result.includes('tiddler="Test"')).toBe(true);
152
- });
153
-
154
- it('Should include single tag', function () {
155
- expect(result.includes('tags="tag1"')).toBe(true);
156
- });
157
-
158
- it('Should include multiple tags', function () {
159
- p.tags = ['tag1', 'tag2'];
160
- result = p.toTwine1HTML();
161
- expect(result.includes('tags="tag1 tag2"')).toBe(true);
162
- });
163
-
164
- it('Should include position, if it exists', function () {
165
- p.metadata = { position: '102,99' };
166
- result = p.toTwine1HTML();
167
- expect(result.includes('position="102,99"')).toBe(true);
168
- });
169
-
170
- it('Should use default position', function () {
171
- p.metadata = {};
172
- result = p.toTwine1HTML();
173
- expect(result.includes('position="10,10"')).toBe(true);
174
- });
175
- });
176
-
177
- describe('Escaping', function () {
178
- it('Should NOT HTML-encode passage text content with double quotes', function () {
179
- const p = new Passage('Test', 'Word "word"');
180
- // Passage text should NOT be HTML-encoded (matches Twine 2 behavior)
181
- expect(p.toTwine2HTML().includes('>Word "word"<')).toBe(true);
182
- expect(p.toTwine2HTML().includes('&quot;word&quot;')).toBe(false);
183
- });
184
-
185
- it('Should NOT HTML-encode passage text content with ampersands', function () {
186
- const p = new Passage('Test', 'Word & word');
187
- // Passage text should NOT be HTML-encoded
188
- expect(p.toTwine2HTML().includes('>Word & word<')).toBe(true);
189
- expect(p.toTwine2HTML().includes('&amp;')).toBe(false);
190
- });
191
-
192
- it('Should NOT HTML-encode passage text content with less than', function () {
193
- const p = new Passage('Test', 'Word < word');
194
- // Passage text should NOT be HTML-encoded
195
- expect(p.toTwine2HTML().includes('>Word < word<')).toBe(true);
196
- expect(p.toTwine2HTML().includes('&lt;')).toBe(false);
197
- });
198
-
199
- it('Should NOT HTML-encode passage text content with greater than', function () {
200
- const p = new Passage('Test', 'Word > word');
201
- // Passage text should NOT be HTML-encoded
202
- expect(p.toTwine2HTML().includes('>Word > word<')).toBe(true);
203
- expect(p.toTwine2HTML().includes('&gt;')).toBe(false);
204
- });
205
-
206
- it('Should NOT HTML-encode passage text content with special characters', function () {
207
- const p = new Passage('Test', 'Word &<>"\' word');
208
- // Passage text should NOT be HTML-encoded
209
- expect(p.toTwine2HTML().includes('>Word &<>"\' word<')).toBe(true);
210
- expect(p.toTwine2HTML().includes('&amp;')).toBe(false);
211
- expect(p.toTwine2HTML().includes('&lt;')).toBe(false);
212
- expect(p.toTwine2HTML().includes('&gt;')).toBe(false);
213
- expect(p.toTwine2HTML().includes('&quot;')).toBe(false);
214
- expect(p.toTwine2HTML().includes('&apos;')).toBe(false);
215
- });
216
-
217
- it('Should escape meta-characters safely in name attribute', function () {
218
- const p = new Passage('"Test"');
219
- // Attributes SHOULD be HTML-encoded
220
- expect(p.toTwine2HTML().includes('name="&quot;Test&quot;"')).toBe(true);
221
- expect(p.toTwine1HTML().includes('tiddler="&quot;Test&quot;"')).toBe(true);
222
- });
223
-
224
- it('Should NOT HTML-encode passage text but preserve JavaScript/HTML', function () {
225
- const p = new Passage('Test', '<%\n$.getScript("https://example.com/script.js");\n%>');
226
- const html = p.toTwine2HTML();
227
- // Should preserve the JavaScript code exactly as-is
228
- expect(html.includes('$.getScript("https://example.com/script.js");')).toBe(true);
229
- expect(html.includes('&quot;')).toBe(false);
230
- expect(html.includes('&lt;')).toBe(false);
231
- expect(html.includes('&gt;')).toBe(false);
232
- });
233
-
234
- it('Should escape meta-characters safely in tags attribute', function () {
235
- const p = new Passage('Test', 'Word', ['&tag', '"bad"']);
236
- // Attributes SHOULD be HTML-encoded
237
- expect(p.toTwine2HTML().includes('tags="&amp;tag &quot;bad&quot;"')).toBe(true);
238
- expect(p.toTwine1HTML().includes('tags="&amp;tag &quot;bad&quot;"')).toBe(true);
239
- });
240
-
241
- it('Should escape meta-characters safely in Twee header', function () {
242
- const p = new Passage('Where do tags begin? [well', '', ['hmm']);
243
- expect(p.toTwee().includes('Where do tags begin? \\[well [hmm]')).toBe(true);
244
- });
245
-
246
- it('Should produce valid HTML attributes', function () {
247
- // Generate passage.
248
- const p = new Passage('"Test"', '"Word"', ['&tag', '"bad"'], { position: '100,100' });
249
- // Parse HTML.
250
- const d = new HTMLParser(p.toTwine2HTML());
251
- // Test attributes.
252
- expect(d.querySelector('tw-passagedata').getAttribute('name')).toBe('"Test"');
253
- expect(d.querySelector('tw-passagedata').getAttribute('tags')).toBe('&tag "bad"');
254
- expect(d.querySelector('tw-passagedata').getAttribute('position')).toBe('100,100');
255
- // Use Twine 2 result.
256
- const s = '<tw-passagedata pid="1" name="&quot;Test&quot;" tags="&amp;tag &quot;bad&quot;" position="100,100" size="100,100"></tw-passagedata>';
257
- // Parse HTML.
258
- const t = new HTMLParser(s);
259
- // Test Twine 2 attributes.
260
- expect(t.querySelector('tw-passagedata').getAttribute('name')).toBe('"Test"');
261
- expect(t.querySelector('tw-passagedata').getAttribute('tags')).toBe('&tag "bad"');
262
- expect(t.querySelector('tw-passagedata').getAttribute('position')).toBe('100,100');
263
- });
264
-
265
- it('Should escape double-colon at start of text when exporting to Twee', function () {
266
- const p = new Passage('test', ':: nefarious');
267
- expect(p.toTwee()).toBe(':: test\n\\:: nefarious\n\n');
268
- });
269
- });
270
- });
@@ -1,125 +0,0 @@
1
- import Passage from '../../src/Passage.js';
2
- import { Story } from '../../src/Story.js';
3
-
4
- describe('Snowman Compatibility Tests', function () {
5
- describe('JavaScript Code in Passages', function () {
6
- it('Should not HTML-encode JavaScript with quotes', function () {
7
- const p = new Passage('External', '<%\n$.getScript("https://code.jquery.com/jquery-3.6.0.min.js");\n%>');
8
- const html = p.toTwine2HTML();
9
-
10
- // Should preserve quotes in JavaScript
11
- expect(html.includes('$.getScript("https://code.jquery.com/jquery-3.6.0.min.js");')).toBe(true);
12
- // Should NOT have HTML entities
13
- expect(html.includes('&quot;')).toBe(false);
14
- expect(html.includes('&lt;')).toBe(false);
15
- expect(html.includes('&gt;')).toBe(false);
16
- });
17
-
18
- it('Should preserve complex JavaScript code', function () {
19
- const code = `<%
20
- var data = {"key": "value", "test": true};
21
- if (data.test) {
22
- console.log("This is a test");
23
- }
24
- %>`;
25
- const p = new Passage('Test', code);
26
- const html = p.toTwine2HTML();
27
-
28
- // Verify the exact code is preserved
29
- expect(html.includes(code)).toBe(true);
30
- expect(html.includes('&quot;')).toBe(false);
31
- expect(html.includes('&lt;')).toBe(false);
32
- expect(html.includes('&gt;')).toBe(false);
33
- });
34
- });
35
-
36
- describe('HTML Content in Passages', function () {
37
- it('Should not HTML-encode HTML tags', function () {
38
- const p = new Passage('HUD', '<h1>This is the HUD!</h1>\n<p>Status: <strong>Active</strong></p>');
39
- const html = p.toTwine2HTML();
40
-
41
- // Should preserve HTML tags
42
- expect(html.includes('<h1>This is the HUD!</h1>')).toBe(true);
43
- expect(html.includes('<strong>Active</strong>')).toBe(true);
44
- // Should NOT have HTML entities
45
- expect(html.includes('&lt;h1&gt;')).toBe(false);
46
- expect(html.includes('&lt;strong&gt;')).toBe(false);
47
- });
48
-
49
- it('Should preserve nested HTML structures', function () {
50
- const htmlContent = `<div class="container">
51
- <h2>Title</h2>
52
- <ul>
53
- <li>Item 1</li>
54
- <li>Item 2</li>
55
- </ul>
56
- </div>`;
57
- const p = new Passage('Container', htmlContent);
58
- const html = p.toTwine2HTML();
59
-
60
- // Verify exact HTML is preserved
61
- expect(html.includes(htmlContent)).toBe(true);
62
- expect(html.includes('&lt;')).toBe(false);
63
- expect(html.includes('&gt;')).toBe(false);
64
- });
65
- });
66
-
67
- describe('Round-trip Compatibility', function () {
68
- it('Should round-trip JavaScript code correctly', function () {
69
- const code = '$.getScript("test.js");';
70
- const p1 = new Passage('Test', code);
71
- const html = p1.toTwine2HTML();
72
-
73
- // Parser should be able to read it back
74
- // (This would be tested in parse tests, but we verify the HTML is correct)
75
- expect(html.includes(code)).toBe(true);
76
- });
77
-
78
- it('Should generate valid Story HTML with unencoded content', function () {
79
- const story = new Story();
80
- story.name = 'Test Story';
81
- story.IFID = 'TEST-IFID-1234';
82
-
83
- const p1 = new Passage('Start', '<%\nconsole.log("test");\n%>');
84
- const p2 = new Passage('HUD', '<h1>Header</h1>');
85
-
86
- story.passages = [p1, p2];
87
-
88
- const html = story.toTwine2HTML();
89
-
90
- // Verify both passages have unencoded content
91
- expect(html.includes('console.log("test");')).toBe(true);
92
- expect(html.includes('<h1>Header</h1>')).toBe(true);
93
- expect(html.includes('&quot;')).toBe(false);
94
- expect(html.includes('&lt;h1&gt;')).toBe(false);
95
- });
96
- });
97
-
98
- describe('Edge Cases', function () {
99
- it('Should handle CDATA-like content', function () {
100
- const content = '<![CDATA[Some data]]>';
101
- const p = new Passage('Test', content);
102
- const html = p.toTwine2HTML();
103
-
104
- expect(html.includes(content)).toBe(true);
105
- });
106
-
107
- it('Should handle mixed quotes', function () {
108
- const content = `var str = "She said 'hello' to me";`;
109
- const p = new Passage('Test', content);
110
- const html = p.toTwine2HTML();
111
-
112
- expect(html.includes(content)).toBe(true);
113
- expect(html.includes('&quot;')).toBe(false);
114
- expect(html.includes('&#39;')).toBe(false);
115
- });
116
-
117
- it('Should handle template literals', function () {
118
- const content = 'const msg = `Hello ${name}`;';
119
- const p = new Passage('Test', content);
120
- const html = p.toTwine2HTML();
121
-
122
- expect(html.includes(content)).toBe(true);
123
- });
124
- });
125
- });