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
|
@@ -1,91 +1,478 @@
|
|
|
1
1
|
import { parse as parseStoryFormat } from '../../src/StoryFormat/parse.js';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
2
|
|
|
4
3
|
describe('StoryFormat', () => {
|
|
5
4
|
describe('parse()', () => {
|
|
5
|
+
describe('Removing setup', () => {
|
|
6
|
+
it('Should remove setup', () => {
|
|
7
|
+
const fr = 'window.storyFormat({"author":"A","description":"B","image":"C","name":"harlowe","proofing":false,"license":"MIT","source":"<html></html>","url":"example.com","version":"1.0.0","setup": function(){}});';
|
|
8
|
+
const sfp = parseStoryFormat(fr);
|
|
9
|
+
expect(sfp.name).toBe('harlowe');
|
|
10
|
+
expect(sfp.version).toBe('1.0.0');
|
|
11
|
+
expect(sfp.author).toBe('A');
|
|
12
|
+
expect(sfp.description).toBe('B');
|
|
13
|
+
expect(sfp.image).toBe('C');
|
|
14
|
+
expect(sfp.url).toBe('example.com');
|
|
15
|
+
expect(sfp.license).toBe('MIT');
|
|
16
|
+
expect(sfp.proofing).toBe(false);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe('name', function () {
|
|
21
|
+
const fr = `{
|
|
22
|
+
"name": "My Story Format",
|
|
23
|
+
"version": "1.0.0",
|
|
24
|
+
"author": "Twine",
|
|
25
|
+
"description": "A story format.",
|
|
26
|
+
"image": "icon.svg",
|
|
27
|
+
"url": "https://example.com",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"proofing": false,
|
|
30
|
+
"source": "<html></html>"
|
|
31
|
+
}`;
|
|
32
|
+
|
|
33
|
+
it('Should parse a name', () => {
|
|
34
|
+
const sfp = parseStoryFormat(fr);
|
|
35
|
+
expect(sfp.name).toBe('My Story Format');
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('Should detect missing name and set default', () => {
|
|
39
|
+
const copy = JSON.parse(fr);
|
|
40
|
+
delete copy.name;
|
|
41
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
42
|
+
expect(sfp.name).toBe('Untitled Story Format');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('author', function () {
|
|
47
|
+
const fr = `{
|
|
48
|
+
"name": "My Story Format",
|
|
49
|
+
"version": "1.0.0",
|
|
50
|
+
"author": "Twine",
|
|
51
|
+
"description": "A story format.",
|
|
52
|
+
"image": "icon.svg",
|
|
53
|
+
"url": "https://example.com",
|
|
54
|
+
"license": "MIT",
|
|
55
|
+
"proofing": false,
|
|
56
|
+
"source": "<html></html>"
|
|
57
|
+
}`;
|
|
58
|
+
|
|
59
|
+
it('Should parse an author', () => {
|
|
60
|
+
const sfp = parseStoryFormat(fr);
|
|
61
|
+
expect(sfp.author).toBe('Twine');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('Should detect missing author and set default', () => {
|
|
65
|
+
const copy = JSON.parse(fr);
|
|
66
|
+
delete copy.author;
|
|
67
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
68
|
+
expect(sfp.author).toBe('');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe('description', function () {
|
|
73
|
+
const fr = `{
|
|
74
|
+
"name": "My Story Format",
|
|
75
|
+
"version": "1.0.0",
|
|
76
|
+
"author": "Twine",
|
|
77
|
+
"description": "A story format.",
|
|
78
|
+
"image": "icon.svg",
|
|
79
|
+
"url": "https://example.com",
|
|
80
|
+
"license": "MIT",
|
|
81
|
+
"proofing": false,
|
|
82
|
+
"source": "<html></html>"
|
|
83
|
+
}`;
|
|
84
|
+
|
|
85
|
+
it('Should parse a description', () => {
|
|
86
|
+
const sfp = parseStoryFormat(fr);
|
|
87
|
+
expect(sfp.description).toBe('A story format.');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('Should detect missing description and set default', () => {
|
|
91
|
+
const copy = JSON.parse(fr);
|
|
92
|
+
delete copy.description;
|
|
93
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
94
|
+
expect(sfp.description).toBe('');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('image', function () {
|
|
99
|
+
const fr = `{
|
|
100
|
+
"name": "My Story Format",
|
|
101
|
+
"version": "1.0.0",
|
|
102
|
+
"author": "Twine",
|
|
103
|
+
"description": "A story format.",
|
|
104
|
+
"image": "icon.svg",
|
|
105
|
+
"url": "https://example.com",
|
|
106
|
+
"license": "MIT",
|
|
107
|
+
"proofing": false,
|
|
108
|
+
"source": "<html></html>"
|
|
109
|
+
}`;
|
|
110
|
+
|
|
111
|
+
it('Should parse an image', () => {
|
|
112
|
+
const sfp = parseStoryFormat(fr);
|
|
113
|
+
expect(sfp.image).toBe('icon.svg');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('Should detect missing image and set default', () => {
|
|
117
|
+
const copy = JSON.parse(fr);
|
|
118
|
+
delete copy.image;
|
|
119
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
120
|
+
expect(sfp.image).toBe('');
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
describe('url', function () {
|
|
125
|
+
const fr = `{
|
|
126
|
+
"name": "My Story Format",
|
|
127
|
+
"version": "1.0.0",
|
|
128
|
+
"author": "Twine",
|
|
129
|
+
"description": "A story format.",
|
|
130
|
+
"image": "icon.svg",
|
|
131
|
+
"url": "https://example.com",
|
|
132
|
+
"license": "MIT",
|
|
133
|
+
"proofing": false,
|
|
134
|
+
"source": "<html></html>"
|
|
135
|
+
}`;
|
|
136
|
+
|
|
137
|
+
it('Should parse a url', () => {
|
|
138
|
+
const sfp = parseStoryFormat(fr);
|
|
139
|
+
expect(sfp.url).toBe('https://example.com');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('Should detect missing url and set default', () => {
|
|
143
|
+
const copy = JSON.parse(fr);
|
|
144
|
+
delete copy.url;
|
|
145
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
146
|
+
expect(sfp.url).toBe('');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
describe('version', function () {
|
|
151
|
+
const fr = `{
|
|
152
|
+
"name": "My Story Format",
|
|
153
|
+
"version": "1.0.0",
|
|
154
|
+
"author": "Twine",
|
|
155
|
+
"description": "A story format.",
|
|
156
|
+
"image": "icon.svg",
|
|
157
|
+
"url": "https://example.com",
|
|
158
|
+
"license": "MIT",
|
|
159
|
+
"proofing": false,
|
|
160
|
+
"source": "<html></html>"
|
|
161
|
+
}`;
|
|
162
|
+
|
|
163
|
+
it('Should parse a version', () => {
|
|
164
|
+
const sfp = parseStoryFormat(fr);
|
|
165
|
+
expect(sfp.version).toBe('1.0.0');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('license', function () {
|
|
170
|
+
const fr = `{
|
|
171
|
+
"name": "My Story Format",
|
|
172
|
+
"version": "1.0.0",
|
|
173
|
+
"author": "Twine",
|
|
174
|
+
"description": "A story format.",
|
|
175
|
+
"image": "icon.svg",
|
|
176
|
+
"url": "https://example.com",
|
|
177
|
+
"license": "MIT",
|
|
178
|
+
"proofing": false,
|
|
179
|
+
"source": "<html></html>"
|
|
180
|
+
}`;
|
|
181
|
+
|
|
182
|
+
it('Should parse a license', () => {
|
|
183
|
+
const sfp = parseStoryFormat(fr);
|
|
184
|
+
expect(sfp.license).toBe('MIT');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('Should detect missing license and set default', () => {
|
|
188
|
+
const copy = JSON.parse(fr);
|
|
189
|
+
delete copy.license;
|
|
190
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
191
|
+
expect(sfp.license).toBe('');
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe('proofing', function () {
|
|
196
|
+
const fr = `{
|
|
197
|
+
"name": "My Story Format",
|
|
198
|
+
"version": "1.0.0",
|
|
199
|
+
"author": "Twine",
|
|
200
|
+
"description": "A story format.",
|
|
201
|
+
"image": "icon.svg",
|
|
202
|
+
"url": "https://example.com",
|
|
203
|
+
"license": "MIT",
|
|
204
|
+
"proofing": true,
|
|
205
|
+
"source": "<html></html>"
|
|
206
|
+
}`;
|
|
207
|
+
|
|
208
|
+
it('Should parse proofing', () => {
|
|
209
|
+
const sfp = parseStoryFormat(fr);
|
|
210
|
+
expect(sfp.proofing).toBe(true);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it('Should detect missing proofing and set default', () => {
|
|
214
|
+
const copy = JSON.parse(fr);
|
|
215
|
+
delete copy.proofing;
|
|
216
|
+
const sfp = parseStoryFormat(JSON.stringify(copy));
|
|
217
|
+
expect(sfp.proofing).toBe(false);
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
describe('source', function () {
|
|
222
|
+
const fr = `{
|
|
223
|
+
"name": "My Story Format",
|
|
224
|
+
"version": "1.0.0",
|
|
225
|
+
"author": "Twine",
|
|
226
|
+
"description": "A story format.",
|
|
227
|
+
"image": "icon.svg",
|
|
228
|
+
"url": "https://example.com",
|
|
229
|
+
"license": "MIT",
|
|
230
|
+
"proofing": true,
|
|
231
|
+
"source": "<html></html>"
|
|
232
|
+
}`;
|
|
233
|
+
|
|
234
|
+
it('Should parse a source', () => {
|
|
235
|
+
const sfp = parseStoryFormat(fr);
|
|
236
|
+
expect(sfp.source).toBe('<html></html>');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
describe('Errors', function () {
|
|
6
242
|
it('Should throw error if JSON missing', () => {
|
|
7
|
-
const fr =
|
|
243
|
+
const fr = '[]';
|
|
8
244
|
expect(() => { parseStoryFormat(fr); }).toThrow();
|
|
9
245
|
});
|
|
10
246
|
|
|
11
|
-
it('Should throw error if JSON malformed', () => {
|
|
12
|
-
const fr =
|
|
247
|
+
it('Should throw error if JSON is malformed', () => {
|
|
248
|
+
const fr = '{"state"}';
|
|
13
249
|
expect(() => { parseStoryFormat(fr); }).toThrow();
|
|
14
250
|
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe('Warnings', () => {
|
|
254
|
+
beforeEach(() => {
|
|
255
|
+
// Mock console.warn.
|
|
256
|
+
jest.spyOn(console, 'warn').mockImplementation();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
afterEach(() => {
|
|
260
|
+
// Restore all mocks.
|
|
261
|
+
jest.restoreAllMocks();
|
|
262
|
+
});
|
|
15
263
|
|
|
16
|
-
it('Should
|
|
17
|
-
const fr =
|
|
18
|
-
|
|
19
|
-
|
|
264
|
+
it('Should produce warning if name is not a string', () => {
|
|
265
|
+
const fr = `{
|
|
266
|
+
"name": null,
|
|
267
|
+
"version": "1.0.0",
|
|
268
|
+
"author": "Twine",
|
|
269
|
+
"description": "A story format.",
|
|
270
|
+
"image": "icon.svg",
|
|
271
|
+
"url": "https://example.com",
|
|
272
|
+
"license": "MIT",
|
|
273
|
+
"proofing": true,
|
|
274
|
+
"source": "<html></html>"
|
|
275
|
+
}`;
|
|
276
|
+
// Parse the story format.
|
|
277
|
+
parseStoryFormat(fr);
|
|
278
|
+
// Expect warning.
|
|
279
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s name is not a string. It will be ignored.');
|
|
20
280
|
});
|
|
21
281
|
|
|
22
|
-
it('Should
|
|
23
|
-
const fr =
|
|
24
|
-
|
|
25
|
-
|
|
282
|
+
it('Should produce warning if author is not a string', () => {
|
|
283
|
+
const fr = `{
|
|
284
|
+
"name": "My Story Format",
|
|
285
|
+
"version": "1.0.0",
|
|
286
|
+
"author": null,
|
|
287
|
+
"description": "A story format.",
|
|
288
|
+
"image": "icon.svg",
|
|
289
|
+
"url": "https://example.com",
|
|
290
|
+
"license": "MIT",
|
|
291
|
+
"proofing": true,
|
|
292
|
+
"source": "<html></html>"
|
|
293
|
+
}`;
|
|
294
|
+
// Parse the story format.
|
|
295
|
+
parseStoryFormat(fr);
|
|
296
|
+
// Expect warning.
|
|
297
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s author is not a string. It will be ignored.');
|
|
26
298
|
});
|
|
27
299
|
|
|
28
|
-
it('Should
|
|
29
|
-
const fr =
|
|
30
|
-
|
|
31
|
-
|
|
300
|
+
it('Should produce warning if description is not a string', () => {
|
|
301
|
+
const fr = `{
|
|
302
|
+
"name": "My Story Format",
|
|
303
|
+
"version": "1.0.0",
|
|
304
|
+
"author": "Twine",
|
|
305
|
+
"description": null,
|
|
306
|
+
"image": "icon.svg",
|
|
307
|
+
"url": "https://example.com",
|
|
308
|
+
"license": "MIT",
|
|
309
|
+
"proofing": true,
|
|
310
|
+
"source": "<html></html>"
|
|
311
|
+
}`;
|
|
312
|
+
// Parse the story format.
|
|
313
|
+
parseStoryFormat(fr);
|
|
314
|
+
// Expect warning.
|
|
315
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s description is not a string. It will be ignored.');
|
|
32
316
|
});
|
|
33
317
|
|
|
34
|
-
it('Should
|
|
35
|
-
const fr =
|
|
36
|
-
|
|
37
|
-
|
|
318
|
+
it('Should produce warning if image is not a string', () => {
|
|
319
|
+
const fr = `{
|
|
320
|
+
"name": "My Story Format",
|
|
321
|
+
"version": "1.0.0",
|
|
322
|
+
"author": "Twine",
|
|
323
|
+
"description": "A story format.",
|
|
324
|
+
"image": null,
|
|
325
|
+
"url": "https://example.com",
|
|
326
|
+
"license": "MIT",
|
|
327
|
+
"proofing": true,
|
|
328
|
+
"source": "<html></html>"
|
|
329
|
+
}`;
|
|
330
|
+
// Parse the story format.
|
|
331
|
+
parseStoryFormat(fr);
|
|
332
|
+
// Expect warning.
|
|
333
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s image is not a string. It will be ignored.');
|
|
38
334
|
});
|
|
39
335
|
|
|
40
|
-
it('Should
|
|
41
|
-
const fr =
|
|
42
|
-
|
|
43
|
-
|
|
336
|
+
it('Should produce warning if url is not a string', () => {
|
|
337
|
+
const fr = `{
|
|
338
|
+
"name": "My Story Format",
|
|
339
|
+
"version": "1.0.0",
|
|
340
|
+
"author": "Twine",
|
|
341
|
+
"description": "A story format.",
|
|
342
|
+
"image": "icon.svg",
|
|
343
|
+
"url": null,
|
|
344
|
+
"license": "MIT",
|
|
345
|
+
"proofing": true,
|
|
346
|
+
"source": "<html></html>"
|
|
347
|
+
}`;
|
|
348
|
+
// Parse the story format.
|
|
349
|
+
parseStoryFormat(fr);
|
|
350
|
+
// Expect warning.
|
|
351
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s url is not a string. It will be ignored.');
|
|
44
352
|
});
|
|
45
353
|
|
|
46
|
-
it('Should
|
|
47
|
-
const fr =
|
|
48
|
-
|
|
49
|
-
|
|
354
|
+
it('Should produce warning if license is not a string', () => {
|
|
355
|
+
const fr = `{
|
|
356
|
+
"name": "My Story Format",
|
|
357
|
+
"version": "1.0.0",
|
|
358
|
+
"author": "Twine",
|
|
359
|
+
"description": "A story format.",
|
|
360
|
+
"image": "icon.svg",
|
|
361
|
+
"url": "https://example.com",
|
|
362
|
+
"license": null,
|
|
363
|
+
"proofing": true,
|
|
364
|
+
"source": "<html></html>"
|
|
365
|
+
}`;
|
|
366
|
+
// Parse the story format.
|
|
367
|
+
parseStoryFormat(fr);
|
|
368
|
+
// Expect warning.
|
|
369
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s license is not a string. It will be ignored.');
|
|
50
370
|
});
|
|
51
371
|
|
|
52
|
-
it('Should
|
|
53
|
-
const fr =
|
|
54
|
-
|
|
55
|
-
|
|
372
|
+
it('Should produce warning if proofing is not a boolean', () => {
|
|
373
|
+
const fr = `{
|
|
374
|
+
"name": "My Story Format",
|
|
375
|
+
"version": "1.0.0",
|
|
376
|
+
"author": "Twine",
|
|
377
|
+
"description": "A story format.",
|
|
378
|
+
"image": "icon.svg",
|
|
379
|
+
"url": "https://example.com",
|
|
380
|
+
"license": "MIT",
|
|
381
|
+
"proofing": null,
|
|
382
|
+
"source": "<html></html>"
|
|
383
|
+
}`;
|
|
384
|
+
// Parse the story format.
|
|
385
|
+
parseStoryFormat(fr);
|
|
386
|
+
// Expect warning.
|
|
387
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s proofing is not a boolean. It will be ignored.');
|
|
56
388
|
});
|
|
57
389
|
|
|
58
|
-
it('Should
|
|
59
|
-
const fr =
|
|
60
|
-
|
|
61
|
-
|
|
390
|
+
it('Should produce warning if source is not a string', () => {
|
|
391
|
+
const fr = `{
|
|
392
|
+
"name": "My Story Format",
|
|
393
|
+
"version": "1.0.0",
|
|
394
|
+
"author": "Twine",
|
|
395
|
+
"description": "A story format.",
|
|
396
|
+
"image": "icon.svg",
|
|
397
|
+
"url": "https://example.com",
|
|
398
|
+
"license": "MIT",
|
|
399
|
+
"proofing": true,
|
|
400
|
+
"source": null
|
|
401
|
+
}`;
|
|
402
|
+
// Parse the story format.
|
|
403
|
+
parseStoryFormat(fr);
|
|
404
|
+
// Expect warning.
|
|
405
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s source is not a string! It will be ignored.');
|
|
62
406
|
});
|
|
63
407
|
|
|
64
|
-
it('Should
|
|
65
|
-
const fr =
|
|
66
|
-
|
|
67
|
-
|
|
408
|
+
it('Should produce warning if source is missing', () => {
|
|
409
|
+
const fr = `{
|
|
410
|
+
"name": "My Story Format",
|
|
411
|
+
"version": "1.0.0",
|
|
412
|
+
"author": "Twine",
|
|
413
|
+
"description": "A story format.",
|
|
414
|
+
"image": "icon.svg",
|
|
415
|
+
"url": "https://example.com",
|
|
416
|
+
"license": "MIT",
|
|
417
|
+
"proofing": true
|
|
418
|
+
}`;
|
|
419
|
+
// Parse the story format.
|
|
420
|
+
parseStoryFormat(fr);
|
|
421
|
+
// Expect warning.
|
|
422
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format does not have source property!');
|
|
68
423
|
});
|
|
69
424
|
|
|
70
|
-
it('Should
|
|
71
|
-
const fr =
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
425
|
+
it('Should produce warning if version is not a string', () => {
|
|
426
|
+
const fr = `{
|
|
427
|
+
"name": "My Story Format",
|
|
428
|
+
"version": null,
|
|
429
|
+
"author": "Twine",
|
|
430
|
+
"description": "A story format.",
|
|
431
|
+
"image": "icon.svg",
|
|
432
|
+
"url": "https://example.com",
|
|
433
|
+
"license": "MIT",
|
|
434
|
+
"proofing": true,
|
|
435
|
+
"source": "<html></html>"
|
|
436
|
+
}`;
|
|
437
|
+
// Parse the story format.
|
|
438
|
+
parseStoryFormat(fr);
|
|
439
|
+
// Expect warning.
|
|
440
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s version is not a string! It will be ignored.');
|
|
75
441
|
});
|
|
76
442
|
|
|
77
|
-
it('Should
|
|
78
|
-
const fr =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
443
|
+
it('Should produce warning if version is not semantic', () => {
|
|
444
|
+
const fr = `{
|
|
445
|
+
"name": "My Story Format",
|
|
446
|
+
"version": "fake version",
|
|
447
|
+
"author": "Twine",
|
|
448
|
+
"description": "A story format.",
|
|
449
|
+
"image": "icon.svg",
|
|
450
|
+
"url": "https://example.com",
|
|
451
|
+
"license": "MIT",
|
|
452
|
+
"proofing": true,
|
|
453
|
+
"source": "<html></html>"
|
|
454
|
+
}`;
|
|
455
|
+
// Parse the story format.
|
|
456
|
+
parseStoryFormat(fr);
|
|
457
|
+
// Expect warning.
|
|
458
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format\'s version is not semantic! It will be ignored.');
|
|
82
459
|
});
|
|
83
460
|
|
|
84
|
-
it('Should
|
|
85
|
-
const fr =
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
461
|
+
it('Should produce warning if version is missing', () => {
|
|
462
|
+
const fr = `{
|
|
463
|
+
"name": "My Story Format",
|
|
464
|
+
"author": "Twine",
|
|
465
|
+
"description": "A story format.",
|
|
466
|
+
"image": "icon.svg",
|
|
467
|
+
"url": "https://example.com",
|
|
468
|
+
"license": "MIT",
|
|
469
|
+
"proofing": true,
|
|
470
|
+
"source": "<html></html>"
|
|
471
|
+
}`;
|
|
472
|
+
// Parse the story format.
|
|
473
|
+
parseStoryFormat(fr);
|
|
474
|
+
// Expect warning.
|
|
475
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: Processed story format does not have version property!');
|
|
89
476
|
});
|
|
90
477
|
});
|
|
91
478
|
});
|
package/test/StoryFormat.test.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import StoryFormat from '../src/StoryFormat.js';
|
|
2
2
|
|
|
3
3
|
describe('StoryFormat', () => {
|
|
4
|
-
describe('
|
|
5
|
-
it('Should
|
|
4
|
+
describe('Default values', () => {
|
|
5
|
+
it('Should have default values', () => {
|
|
6
6
|
const sf = new StoryFormat();
|
|
7
7
|
expect(sf.name).toBe('Untitled Story Format');
|
|
8
8
|
expect(sf.version).toBe('');
|
|
@@ -149,4 +149,11 @@ describe('StoryFormat', () => {
|
|
|
149
149
|
}).toThrow();
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
|
+
|
|
153
|
+
describe('toString', () => {
|
|
154
|
+
it('Should return string representation', () => {
|
|
155
|
+
const sf = new StoryFormat();
|
|
156
|
+
expect(sf.toString()).toBe(JSON.stringify(sf, null, "\t"));
|
|
157
|
+
});
|
|
158
|
+
});
|
|
152
159
|
});
|
package/test/TWS/Parse.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { compile as compileTwine2ArchiveHTML } from '../../src/Twine2ArchiveHTML/compile.js';
|
|
2
|
-
import Story from '../../src/Story.js';
|
|
2
|
+
import { Story } from '../../src/Story.js';
|
|
3
3
|
import Passage from '../../src/Passage.js';
|
|
4
4
|
|
|
5
5
|
describe('Twine2ArchiveHTML', function () {
|
|
@@ -3,10 +3,6 @@ import { readFileSync } from 'node:fs';
|
|
|
3
3
|
|
|
4
4
|
describe('Twine2ArchiveHTML', function () {
|
|
5
5
|
describe('parse()', function () {
|
|
6
|
-
it('Should throw error when given no Twine 2 HTML elements', function () {
|
|
7
|
-
expect(() => { parseTwine2ArchiveHTML(''); }).toThrow();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
6
|
it('Should throw error when content is not string', function () {
|
|
11
7
|
expect(() => { parseTwine2ArchiveHTML(2); }).toThrow();
|
|
12
8
|
});
|
|
@@ -22,4 +18,24 @@ describe('Twine2ArchiveHTML', function () {
|
|
|
22
18
|
expect(stories.length).toBe(2);
|
|
23
19
|
});
|
|
24
20
|
});
|
|
21
|
+
|
|
22
|
+
describe('Warnings', function () {
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
// Mock console.warn.
|
|
25
|
+
jest.spyOn(console, 'warn').mockImplementation();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
// Restore all mocks.
|
|
30
|
+
jest.restoreAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('Should produce warning when no Twine 2 HTML content is found', function () {
|
|
34
|
+
// Parse Twine 2 Story.
|
|
35
|
+
parseTwine2ArchiveHTML('');
|
|
36
|
+
|
|
37
|
+
// Expect warning.
|
|
38
|
+
expect(console.warn).toHaveBeenCalledWith('Warning: No Twine 2 HTML content found!');
|
|
39
|
+
});
|
|
40
|
+
});
|
|
25
41
|
});
|