extwee 2.2.5 → 2.3.0
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/workflows/dependabot-automerge.yml +23 -0
- package/.github/workflows/nodejs.yml +4 -1
- package/README.md +29 -14
- package/SECURITY.md +1 -1
- package/build/extwee.web.min.js +2 -0
- package/build/extwee.web.min.js.LICENSE.txt +1 -0
- package/extwee.config.json +6 -0
- package/extwee.config.md +67 -0
- package/index.js +2 -0
- package/package.json +24 -23
- package/src/CLI/CommandLineProcessing.js +196 -0
- package/src/CLI/ProcessConfig/loadStoryFormat.js +102 -0
- package/src/CLI/ProcessConfig/readDirectories.js +46 -0
- package/src/CLI/ProcessConfig.js +175 -0
- package/src/CLI/isDirectory.js +27 -0
- package/src/CLI/isFile.js +28 -0
- package/src/Config/parser.js +30 -8
- package/src/Passage.js +17 -2
- package/src/Story.js +101 -1
- package/src/StoryFormat/compile.js +19 -0
- package/src/StoryFormat.js +51 -0
- package/src/extwee.js +20 -195
- package/test/Config/Config.test.js +40 -10
- package/test/Config/files/full.json +8 -0
- package/test/Config/files/valid.json +4 -3
- package/test/Config/isDirectory.test.js +44 -0
- package/test/Config/isFile.test.js +50 -0
- package/test/Config/loadStoryFormat.test.js +101 -0
- package/test/Config/readDirectories.test.js +68 -0
- package/test/Objects/Passage.test.js +5 -0
- package/test/Objects/Story.test.js +174 -0
- package/test/Objects/StoryFormat.test.js +60 -0
- package/test/TWS/Parse.test.js +0 -22
- package/test/Web/window.Extwee.test.js +85 -0
- package/types/Story.d.ts +26 -1
- package/types/StoryFormat/compile.d.ts +8 -0
- package/types/StoryFormat.d.ts +7 -0
- package/types/index.d.ts +4 -2
- package/types/src/CLI/CommandLineProcessing.d.ts +8 -0
- package/types/src/CLI/ProcessConfig/loadStoryFormat.d.ts +20 -0
- package/types/src/CLI/ProcessConfig/readDirectories.d.ts +9 -0
- package/types/src/CLI/ProcessConfig.d.ts +12 -0
- package/types/src/CLI/isDirectory.d.ts +1 -0
- package/types/src/CLI/isFile.d.ts +1 -0
- package/types/src/Config/parser.d.ts +6 -0
- package/types/src/Config/reader.d.ts +11 -0
- package/types/src/IFID/generate.d.ts +14 -0
- package/types/src/JSON/parse.d.ts +44 -1
- package/types/src/Passage.d.ts +49 -4
- package/types/src/Story.d.ts +110 -16
- package/types/src/StoryFormat/compile.d.ts +8 -0
- package/types/src/StoryFormat/parse.d.ts +46 -3
- package/types/src/StoryFormat.d.ts +69 -38
- package/types/src/TWS/parse.d.ts +3 -3
- package/types/src/Twee/parse.d.ts +3 -4
- package/types/src/Twine1HTML/compile.d.ts +3 -1
- package/types/src/Twine1HTML/parse.d.ts +3 -4
- package/types/src/Twine2ArchiveHTML/compile.d.ts +8 -0
- package/types/src/Twine2ArchiveHTML/parse.d.ts +31 -1
- package/types/src/Twine2HTML/compile.d.ts +7 -2
- package/types/src/Twine2HTML/parse.d.ts +12 -9
- package/index.html +0 -22
- package/test/TWS/TWSParser/Example1.tws +0 -150
|
@@ -229,6 +229,45 @@ describe('Story', () => {
|
|
|
229
229
|
});
|
|
230
230
|
});
|
|
231
231
|
|
|
232
|
+
describe('storyStylesheet', () => {
|
|
233
|
+
let s = null;
|
|
234
|
+
|
|
235
|
+
beforeEach(() => {
|
|
236
|
+
s = new Story();
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('Set storyStylesheet', () => {
|
|
240
|
+
s.storyStylesheet = 'Test';
|
|
241
|
+
expect(s.storyStylesheet).not.toBe('');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('Should throw error if not String', () => {
|
|
245
|
+
expect(() => {
|
|
246
|
+
s.storyStylesheet = 1;
|
|
247
|
+
}).toThrow();
|
|
248
|
+
}
|
|
249
|
+
);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe('storyJavaScript', () => {
|
|
253
|
+
let s = null;
|
|
254
|
+
|
|
255
|
+
beforeEach(() => {
|
|
256
|
+
s = new Story();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('Set storyJavaScript', () => {
|
|
260
|
+
s.storyJavaScript = 'Test';
|
|
261
|
+
expect(s.storyJavaScript).not.toBe('');
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it('Should throw error if not String', () => {
|
|
265
|
+
expect(() => {
|
|
266
|
+
s.storyJavaScript = 1;
|
|
267
|
+
}).toThrow();
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
232
271
|
describe('passages', () => {
|
|
233
272
|
let s = null;
|
|
234
273
|
|
|
@@ -442,6 +481,30 @@ describe('Story', () => {
|
|
|
442
481
|
// Should have a single passage.
|
|
443
482
|
expect(result.passages.length).toBe(1);
|
|
444
483
|
});
|
|
484
|
+
|
|
485
|
+
it('Should have style data', function () {
|
|
486
|
+
// Create default Story.
|
|
487
|
+
const s = new Story();
|
|
488
|
+
// Add a stylesheet.
|
|
489
|
+
s.storyStylesheet = 'Test';
|
|
490
|
+
// Convert to JSON and then back to object.
|
|
491
|
+
const result = JSON.parse(s.toJSON());
|
|
492
|
+
// Should have a stylesheet.
|
|
493
|
+
expect(result.style).toBe('Test');
|
|
494
|
+
}
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
it('Should have script data', function () {
|
|
498
|
+
// Create default Story.
|
|
499
|
+
const s = new Story();
|
|
500
|
+
// Add a script.
|
|
501
|
+
s.storyJavaScript = 'Test';
|
|
502
|
+
// Convert to JSON and then back to object.
|
|
503
|
+
const result = JSON.parse(s.toJSON());
|
|
504
|
+
// Should have a script.
|
|
505
|
+
expect(result.script).toBe('Test');
|
|
506
|
+
}
|
|
507
|
+
);
|
|
445
508
|
});
|
|
446
509
|
|
|
447
510
|
describe('toTwee()', function () {
|
|
@@ -647,6 +710,48 @@ describe('Story', () => {
|
|
|
647
710
|
// Test for passage text.
|
|
648
711
|
expect(p[0].text).toBe('Test');
|
|
649
712
|
});
|
|
713
|
+
|
|
714
|
+
it('Should encode story stylesheet as passage with "stylesheet" tag', () => {
|
|
715
|
+
// Add passages.
|
|
716
|
+
s.storyStylesheet = 'Test';
|
|
717
|
+
|
|
718
|
+
// Set IFID.
|
|
719
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
720
|
+
|
|
721
|
+
// Convert into Twee.
|
|
722
|
+
const t = s.toTwee();
|
|
723
|
+
|
|
724
|
+
// Convert back into Story.
|
|
725
|
+
const story = parseTwee(t);
|
|
726
|
+
|
|
727
|
+
// Search for 'stylesheet'.
|
|
728
|
+
const p = story.getPassagesByTag('stylesheet');
|
|
729
|
+
|
|
730
|
+
// Test for passage text.
|
|
731
|
+
expect(p[0].text).toBe('Test');
|
|
732
|
+
}
|
|
733
|
+
);
|
|
734
|
+
|
|
735
|
+
it('Should encode story JavaScript as passage with "script" tag', () => {
|
|
736
|
+
// Add passages.
|
|
737
|
+
s.storyJavaScript = 'Test';
|
|
738
|
+
|
|
739
|
+
// Set IFID.
|
|
740
|
+
s.IFID = 'DE7DF8AD-E4CD-499E-A4E7-C5B98B73449A';
|
|
741
|
+
|
|
742
|
+
// Convert into Twee.
|
|
743
|
+
const t = s.toTwee();
|
|
744
|
+
|
|
745
|
+
// Convert back into Story.
|
|
746
|
+
const story = parseTwee(t);
|
|
747
|
+
|
|
748
|
+
// Search for 'stylesheet'.
|
|
749
|
+
const p = story.getPassagesByTag('script');
|
|
750
|
+
|
|
751
|
+
// Test for passage text.
|
|
752
|
+
expect(p[0].text).toBe('Test');
|
|
753
|
+
}
|
|
754
|
+
);
|
|
650
755
|
});
|
|
651
756
|
|
|
652
757
|
describe('toTwine2HTML()', () => {
|
|
@@ -695,6 +800,19 @@ describe('Story', () => {
|
|
|
695
800
|
expect(result.includes('<style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css">Word')).toBe(true);
|
|
696
801
|
});
|
|
697
802
|
|
|
803
|
+
it('Should encode stylesheet property', () => {
|
|
804
|
+
// Add passage.
|
|
805
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
806
|
+
// Set start.
|
|
807
|
+
s.start = 'Start';
|
|
808
|
+
// Set stylesheet.
|
|
809
|
+
s.storyStylesheet = 'Test';
|
|
810
|
+
// Create HTML.
|
|
811
|
+
const result = s.toTwine2HTML();
|
|
812
|
+
// Expect the stylesheet passage text to be encoded.
|
|
813
|
+
expect(result.includes('<style role="stylesheet" id="twine-user-stylesheet" type="text/twine-css">Test')).toBe(true);
|
|
814
|
+
});
|
|
815
|
+
|
|
698
816
|
it('Should encode script passages', () => {
|
|
699
817
|
// Add passage.
|
|
700
818
|
s.addPassage(new Passage('Start', 'Word'));
|
|
@@ -708,6 +826,19 @@ describe('Story', () => {
|
|
|
708
826
|
expect(result.includes('<script role="script" id="twine-user-script" type="text/twine-javascript">Word')).toBe(true);
|
|
709
827
|
});
|
|
710
828
|
|
|
829
|
+
it('Should encode script property', () => {
|
|
830
|
+
// Add passage.
|
|
831
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
832
|
+
// Set start.
|
|
833
|
+
s.start = 'Start';
|
|
834
|
+
// Set script.
|
|
835
|
+
s.storyJavaScript = 'Test';
|
|
836
|
+
// Create HTML.
|
|
837
|
+
const result = s.toTwine2HTML();
|
|
838
|
+
// Expect the script passage text to be encoded.
|
|
839
|
+
expect(result.includes('<script role="script" id="twine-user-script" type="text/twine-javascript">Test')).toBe(true);
|
|
840
|
+
});
|
|
841
|
+
|
|
711
842
|
it('Should encode format', () => {
|
|
712
843
|
// Add passage.
|
|
713
844
|
s.addPassage(new Passage('Start', 'Word'));
|
|
@@ -819,6 +950,49 @@ describe('Story', () => {
|
|
|
819
950
|
// Expect the creator to be encoded.
|
|
820
951
|
expect(result.includes(`creator="${creatorName}"`)).not.toBe(true);
|
|
821
952
|
});
|
|
953
|
+
|
|
954
|
+
it('Should not encode story tag colors if none are present', () => {
|
|
955
|
+
// Add passage.
|
|
956
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
957
|
+
// Set start.
|
|
958
|
+
s.start = 'Start';
|
|
959
|
+
// Create HTML.
|
|
960
|
+
const result = s.toTwine2HTML();
|
|
961
|
+
// Expect the tag colors to not be encoded if none are present.
|
|
962
|
+
expect(result.includes('<tw-tag')).toBe(false);
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
it('Should encode single story tag color', () => {
|
|
966
|
+
// Add passage.
|
|
967
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
968
|
+
// Set start.
|
|
969
|
+
s.start = 'Start';
|
|
970
|
+
// Add tag colors.
|
|
971
|
+
s.tagColors = {
|
|
972
|
+
bar: 'green'
|
|
973
|
+
};
|
|
974
|
+
// Create HTML.
|
|
975
|
+
const result = s.toTwine2HTML();
|
|
976
|
+
// Expect the tag colors to be encoded.
|
|
977
|
+
expect(result.includes('<tw-tag name="bar" color="green"></tw-tag>')).toBe(true);
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
it('Should encode multiple story tag colors', () => {
|
|
981
|
+
// Add passage.
|
|
982
|
+
s.addPassage(new Passage('Start', 'Word'));
|
|
983
|
+
// Set start.
|
|
984
|
+
s.start = 'Start';
|
|
985
|
+
// Add tag colors.
|
|
986
|
+
s.tagColors = {
|
|
987
|
+
bar: 'green',
|
|
988
|
+
foo: 'red'
|
|
989
|
+
};
|
|
990
|
+
// Create HTML.
|
|
991
|
+
const result = s.toTwine2HTML();
|
|
992
|
+
// Expect the tag colors to be encoded.
|
|
993
|
+
expect(result.includes('<tw-tag name="bar" color="green"></tw-tag>')).toBe(true);
|
|
994
|
+
expect(result.includes('<tw-tag name="foo" color="red"></tw-tag>')).toBe(true);
|
|
995
|
+
});
|
|
822
996
|
});
|
|
823
997
|
|
|
824
998
|
describe('toTwine1HTML()', function () {
|
|
@@ -15,6 +15,29 @@ describe('StoryFormat', () => {
|
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
describe('Constructor with default values', () => {
|
|
19
|
+
it('Should create an instance of StoryFormat', () => {
|
|
20
|
+
const sf = new StoryFormat();
|
|
21
|
+
expect(sf).toBeInstanceOf(StoryFormat);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('Constructor with parameters', () => {
|
|
26
|
+
it('Should create an instance of StoryFormat with parameters', () => {
|
|
27
|
+
const sf = new StoryFormat('name', 'version', 'description', 'author', 'image', 'url', 'license', true, 'source');
|
|
28
|
+
expect(sf).toBeInstanceOf(StoryFormat);
|
|
29
|
+
expect(sf.name).toBe('name');
|
|
30
|
+
expect(sf.version).toBe('version');
|
|
31
|
+
expect(sf.description).toBe('description');
|
|
32
|
+
expect(sf.author).toBe('author');
|
|
33
|
+
expect(sf.image).toBe('image');
|
|
34
|
+
expect(sf.url).toBe('url');
|
|
35
|
+
expect(sf.license).toBe('license');
|
|
36
|
+
expect(sf.proofing).toBe(true);
|
|
37
|
+
expect(sf.source).toBe('source');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
|
|
18
41
|
describe('name', () => {
|
|
19
42
|
it('Set new String', () => {
|
|
20
43
|
const sf = new StoryFormat();
|
|
@@ -153,7 +176,44 @@ describe('StoryFormat', () => {
|
|
|
153
176
|
describe('toString', () => {
|
|
154
177
|
it('Should return string representation', () => {
|
|
155
178
|
const sf = new StoryFormat();
|
|
179
|
+
sf.version = '1.0.0';
|
|
156
180
|
expect(sf.toString()).toBe(JSON.stringify(sf, null, '\t'));
|
|
157
181
|
});
|
|
182
|
+
|
|
183
|
+
it('Should throw error if version is not valid', () => {
|
|
184
|
+
const sf = new StoryFormat();
|
|
185
|
+
expect(() => {
|
|
186
|
+
sf.toString();
|
|
187
|
+
}).toThrow();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('toJSON', () => {
|
|
192
|
+
it('Should return JSON representation with default name', () => {
|
|
193
|
+
const sf = new StoryFormat();
|
|
194
|
+
sf.version = '1.0.0';
|
|
195
|
+
expect(sf.toJSON().includes("Untitled Story Format")).toEqual(true);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('Should return JSON representation with custom name', () => {
|
|
199
|
+
const sf = new StoryFormat();
|
|
200
|
+
sf.name = 'Custom Name';
|
|
201
|
+
sf.version = '1.0.0';
|
|
202
|
+
expect(sf.toJSON().includes("Custom Name")).toEqual(true);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('Should overwrite with default name if name is empty string', () => {
|
|
206
|
+
const sf = new StoryFormat();
|
|
207
|
+
sf.name = '';
|
|
208
|
+
sf.version = '1.0.0';
|
|
209
|
+
expect(sf.toJSON().includes("Untitled Story Format")).toEqual(true);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it('Should throw error if version is not valid', () => {
|
|
213
|
+
const sf = new StoryFormat();
|
|
214
|
+
expect(() => {
|
|
215
|
+
sf.toJSON();
|
|
216
|
+
}).toThrow();
|
|
217
|
+
});
|
|
158
218
|
});
|
|
159
219
|
});
|
package/test/TWS/Parse.test.js
CHANGED
|
@@ -7,28 +7,6 @@ describe('TWSParser', () => {
|
|
|
7
7
|
expect(() => { parseTWS(0); }).toThrow();
|
|
8
8
|
});
|
|
9
9
|
|
|
10
|
-
describe('Story parsing', function () {
|
|
11
|
-
let r = null;
|
|
12
|
-
|
|
13
|
-
beforeAll(() => {
|
|
14
|
-
const contents = fs.readFileSync('test/TWS/TWSParser/Example1.tws');
|
|
15
|
-
//const b = Buffer.from(contents, 'binary');
|
|
16
|
-
r = parseTWS(contents);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('Should parse StoryTitle', function () {
|
|
20
|
-
expect(r.name).toBe('Untitled Story');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('Should parse zoom', function () {
|
|
24
|
-
expect(r.zoom).toBe(1);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it('Should parse start passage', function () {
|
|
28
|
-
expect(r.start).toBe('Start');
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
10
|
describe('Passage parsing', function () {
|
|
33
11
|
let r = null;
|
|
34
12
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import '../../web-index.js';
|
|
6
|
+
|
|
7
|
+
describe('Extwee', () => {
|
|
8
|
+
it('should have all the expected properties', () => {
|
|
9
|
+
expect(window.Extwee).toHaveProperty('parseTwee');
|
|
10
|
+
expect(window.Extwee).toHaveProperty('parseJSON');
|
|
11
|
+
expect(window.Extwee).toHaveProperty('parseTWS');
|
|
12
|
+
expect(window.Extwee).toHaveProperty('parseStoryFormat');
|
|
13
|
+
expect(window.Extwee).toHaveProperty('parseTwine1HTML');
|
|
14
|
+
expect(window.Extwee).toHaveProperty('parseTwine2HTML');
|
|
15
|
+
expect(window.Extwee).toHaveProperty('parseTwine2ArchiveHTML');
|
|
16
|
+
expect(window.Extwee).toHaveProperty('compileTwine1HTML');
|
|
17
|
+
expect(window.Extwee).toHaveProperty('compileTwine2HTML');
|
|
18
|
+
expect(window.Extwee).toHaveProperty('compileTwine2ArchiveHTML');
|
|
19
|
+
expect(window.Extwee).toHaveProperty('generateIFID');
|
|
20
|
+
expect(window.Extwee).toHaveProperty('Story');
|
|
21
|
+
expect(window.Extwee).toHaveProperty('Passage');
|
|
22
|
+
expect(window.Extwee).toHaveProperty('StoryFormat');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should have the expected types', () => {
|
|
26
|
+
expect(typeof window.Extwee.parseTwee).toBe('function');
|
|
27
|
+
expect(typeof window.Extwee.parseJSON).toBe('function');
|
|
28
|
+
expect(typeof window.Extwee.parseTWS).toBe('function');
|
|
29
|
+
expect(typeof window.Extwee.parseStoryFormat).toBe('function');
|
|
30
|
+
expect(typeof window.Extwee.parseTwine1HTML).toBe('function');
|
|
31
|
+
expect(typeof window.Extwee.parseTwine2HTML).toBe('function');
|
|
32
|
+
expect(typeof window.Extwee.parseTwine2ArchiveHTML).toBe('function');
|
|
33
|
+
expect(typeof window.Extwee.compileTwine1HTML).toBe('function');
|
|
34
|
+
expect(typeof window.Extwee.compileTwine2HTML).toBe('function');
|
|
35
|
+
expect(typeof window.Extwee.compileTwine2ArchiveHTML).toBe('function');
|
|
36
|
+
expect(typeof window.Extwee.generateIFID).toBe('function');
|
|
37
|
+
expect(typeof window.Extwee.Story).toBe('function');
|
|
38
|
+
expect(typeof window.Extwee.Passage).toBe('function');
|
|
39
|
+
expect(typeof window.Extwee.StoryFormat).toBe('function');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should have the expected properties in StoryFormat', () => {
|
|
43
|
+
const storyFormat = new window.Extwee.StoryFormat();
|
|
44
|
+
expect(storyFormat).toHaveProperty('name');
|
|
45
|
+
expect(storyFormat).toHaveProperty('version');
|
|
46
|
+
expect(storyFormat).toHaveProperty('description');
|
|
47
|
+
expect(storyFormat).toHaveProperty('author');
|
|
48
|
+
expect(storyFormat).toHaveProperty('image');
|
|
49
|
+
expect(storyFormat).toHaveProperty('url');
|
|
50
|
+
expect(storyFormat).toHaveProperty('license');
|
|
51
|
+
expect(storyFormat).toHaveProperty('proofing');
|
|
52
|
+
expect(storyFormat).toHaveProperty('source');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should have the expected properties in Story', () => {
|
|
56
|
+
const story = new window.Extwee.Story();
|
|
57
|
+
expect(story).toHaveProperty('name');
|
|
58
|
+
expect(story).toHaveProperty('IFID');
|
|
59
|
+
expect(story).toHaveProperty('start');
|
|
60
|
+
expect(story).toHaveProperty('format');
|
|
61
|
+
expect(story).toHaveProperty('formatVersion');
|
|
62
|
+
expect(story).toHaveProperty('zoom');
|
|
63
|
+
expect(story).toHaveProperty('passages');
|
|
64
|
+
expect(story).toHaveProperty('creator');
|
|
65
|
+
expect(story).toHaveProperty('creatorVersion');
|
|
66
|
+
expect(story).toHaveProperty('metadata');
|
|
67
|
+
expect(story).toHaveProperty('tagColors');
|
|
68
|
+
expect(story).toHaveProperty('storyJavaScript');
|
|
69
|
+
expect(story).toHaveProperty('storyStylesheet');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should have the expected types in Passage', () => {
|
|
73
|
+
const passage = new window.Extwee.Passage();
|
|
74
|
+
expect(passage).toHaveProperty('name');
|
|
75
|
+
expect(passage).toHaveProperty('text');
|
|
76
|
+
expect(passage).toHaveProperty('tags');
|
|
77
|
+
expect(passage).toHaveProperty('metadata');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should generate a valid IFID', () => {
|
|
81
|
+
const ifid = window.Extwee.generateIFID();
|
|
82
|
+
expect(ifid).toMatch(/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
});
|
package/types/Story.d.ts
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
* @property {string} creatorVersion - Version used to create Story.
|
|
14
14
|
* @property {object} metadata - Metadata of Story.
|
|
15
15
|
* @property {object} tagColors - Tag Colors
|
|
16
|
+
* @property {string} storyJavaScript - Story JavaScript
|
|
17
|
+
* @property {string} storyStylesheet - Story Stylesheet
|
|
16
18
|
* @method {number} addPassage - Add a passage to the story and returns the new length of the passages array.
|
|
17
19
|
* @method {number} removePassageByName - Remove a passage from the story by name and returns the new length of the passages array.
|
|
18
20
|
* @method {Array} getPassagesByTag - Find passages by tag.
|
|
@@ -142,6 +144,25 @@ export class Story {
|
|
|
142
144
|
* @property {Array} passages - Passages
|
|
143
145
|
*/
|
|
144
146
|
get passages(): any[];
|
|
147
|
+
/**
|
|
148
|
+
* @param {string} s - Replacement story stylesheet
|
|
149
|
+
*/
|
|
150
|
+
set storyStylesheet(s: string);
|
|
151
|
+
/**
|
|
152
|
+
* Story stylesheet data can be set as a passage, property value, or both.
|
|
153
|
+
* @returns {string} storyStylesheet
|
|
154
|
+
*/
|
|
155
|
+
get storyStylesheet(): string;
|
|
156
|
+
/**
|
|
157
|
+
* Set story JavaScript.
|
|
158
|
+
* @param {string} s - Replacement story JavaScript
|
|
159
|
+
*/
|
|
160
|
+
set storyJavaScript(s: string);
|
|
161
|
+
/**
|
|
162
|
+
* Get story JavaScript.
|
|
163
|
+
* @returns {string} storyJavaScript
|
|
164
|
+
*/
|
|
165
|
+
get storyJavaScript(): string;
|
|
145
166
|
/**
|
|
146
167
|
* Add a passage to the story.
|
|
147
168
|
* Passing `StoryData` will override story metadata and `StoryTitle` will override story name.
|
|
@@ -209,6 +230,10 @@ export class Story {
|
|
|
209
230
|
* - `format`: (string) Optional. The format of the story.
|
|
210
231
|
* - `format-version`: (string) Optional. The version of the format of the story.
|
|
211
232
|
*
|
|
233
|
+
* Because story stylesheet data can be represented as a passage, property value, or both, all approaches are encoded.
|
|
234
|
+
*
|
|
235
|
+
* Because story JavaScript can be represented as a passage, property value, or both, all approaches are encoded.
|
|
236
|
+
*
|
|
212
237
|
* @method toTwine2HTML
|
|
213
238
|
* @returns {string} Twine 2 HTML string
|
|
214
239
|
*/
|
|
@@ -226,5 +251,5 @@ export class Story {
|
|
|
226
251
|
#private;
|
|
227
252
|
}
|
|
228
253
|
export const creatorName: "extwee";
|
|
229
|
-
export const creatorVersion: "2.2.
|
|
254
|
+
export const creatorVersion: "2.2.6";
|
|
230
255
|
import Passage from './Passage.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compiles a {@link StoryFormat} object into a JSONP string for writing to a `format.js` file.
|
|
3
|
+
* @see {@link https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-storyformats-spec.md Twine 2 Story Formats Specification}
|
|
4
|
+
* @param {StoryFormat} storyFormat Story format object to compile.
|
|
5
|
+
* @returns {string} JSONP string.
|
|
6
|
+
*/
|
|
7
|
+
export function compile(storyFormat: StoryFormat): string;
|
|
8
|
+
import StoryFormat from '../StoryFormat.js';
|
package/types/StoryFormat.d.ts
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
* sf.source = 'New';
|
|
31
31
|
*/
|
|
32
32
|
export default class StoryFormat {
|
|
33
|
+
constructor(name?: string, version?: string, description?: string, author?: string, image?: string, url?: string, license?: string, proofing?: boolean, source?: string);
|
|
33
34
|
/**
|
|
34
35
|
* @param {string} n - Replacement name.
|
|
35
36
|
*/
|
|
@@ -117,5 +118,11 @@ export default class StoryFormat {
|
|
|
117
118
|
* @returns {string} - A string representation of the story format.
|
|
118
119
|
*/
|
|
119
120
|
toString(): string;
|
|
121
|
+
/**
|
|
122
|
+
* Produces a JSON representation of the story format object.
|
|
123
|
+
* @method toJSON
|
|
124
|
+
* @returns {object} - A JSON representation of the story format.
|
|
125
|
+
*/
|
|
126
|
+
toJSON(): object;
|
|
120
127
|
#private;
|
|
121
128
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ import { parse as parseTwine2ArchiveHTML } from './src/Twine2ArchiveHTML/parse.j
|
|
|
8
8
|
import { compile as compileTwine1HTML } from './src/Twine1HTML/compile.js';
|
|
9
9
|
import { compile as compileTwine2HTML } from './src/Twine2HTML/compile.js';
|
|
10
10
|
import { compile as compileTwine2ArchiveHTML } from './src/Twine2ArchiveHTML/compile.js';
|
|
11
|
-
import
|
|
11
|
+
import { compile as compileStoryFormat } from './src/StoryFormat/compile.js';
|
|
12
|
+
import { generate as generateIFID } from './src/IFID/generate.js';
|
|
13
|
+
import { Story } from './src/Story.js';
|
|
12
14
|
import Passage from './src/Passage.js';
|
|
13
15
|
import StoryFormat from './src/StoryFormat.js';
|
|
14
|
-
export { parseTwee, parseJSON, parseTWS, parseStoryFormat, parseTwine1HTML, parseTwine2HTML, parseTwine2ArchiveHTML, compileTwine1HTML, compileTwine2HTML, compileTwine2ArchiveHTML, Story, Passage, StoryFormat };
|
|
16
|
+
export { parseTwee, parseJSON, parseTWS, parseStoryFormat, parseTwine1HTML, parseTwine2HTML, parseTwine2ArchiveHTML, compileTwine1HTML, compileTwine2HTML, compileTwine2ArchiveHTML, compileStoryFormat, generateIFID, Story, Passage, StoryFormat };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process command line arguments.
|
|
3
|
+
* @function CommandLineProcessing
|
|
4
|
+
* @description This function processes the command line arguments passed to the Extwee CLI.
|
|
5
|
+
* @module CLI/commandLineProcessing
|
|
6
|
+
* @param {Array} argv - The command line arguments passed to the CLI.
|
|
7
|
+
*/
|
|
8
|
+
export function CommandLineProcessing(argv: any[]): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load the story format from the story-formats directory.
|
|
3
|
+
* @function loadStoryFormat
|
|
4
|
+
* @description This function loads the story format from the story-formats directory.
|
|
5
|
+
* It checks if the story-formats directory exists, if the named story format exists,
|
|
6
|
+
* if the version directory exists, and if the format.js file exists.
|
|
7
|
+
* If any of these checks fail, the function will exit the process with an error message.
|
|
8
|
+
* If all checks pass, the function will return the contents of the format.js file.
|
|
9
|
+
* @param {string} storyFormatName - The name of the story format.
|
|
10
|
+
* @param {string} storyFormatVersion - The version of the story format.
|
|
11
|
+
* @returns {string} - The contents of the format.js file.
|
|
12
|
+
* @throws {Error} - If the story-formats directory does not exist, if the named story format does not exist,
|
|
13
|
+
* if the version directory does not exist, or if the format.js file does not exist.
|
|
14
|
+
* @example
|
|
15
|
+
* // Load the story format from the story-formats directory.
|
|
16
|
+
* const storyFormat = loadStoryFormat('Harlowe', '3.2.0');
|
|
17
|
+
* console.log(storyFormat);
|
|
18
|
+
* // Output: The contents of the format.js file.
|
|
19
|
+
*/
|
|
20
|
+
export function loadStoryFormat(storyFormatName: string, storyFormatVersion: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the contents of a directory and returns all directories.
|
|
3
|
+
* @function readDirectories
|
|
4
|
+
* @description This function reads the contents of a directory and returns a list of directories.
|
|
5
|
+
* @param {string} directory - The path to the directory to read.
|
|
6
|
+
* @returns {Array<string>} - An array of directories in the directory.
|
|
7
|
+
* @throws {Error} - If the directory does not exist or if there is an error reading the directory.
|
|
8
|
+
*/
|
|
9
|
+
export function readDirectories(directory: string): Array<string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Processes the config file, if present.
|
|
3
|
+
* @function ConfigFileProcessing
|
|
4
|
+
* @description This function processes the config file.
|
|
5
|
+
* It checks if the config file exists and if it does, it reads the config file.
|
|
6
|
+
* If the config file does not exist, the function will exit the process with an error message.
|
|
7
|
+
* The config file is used to store configuration options for the Extwee CLI.
|
|
8
|
+
* @returns {void}
|
|
9
|
+
* @throws {Error} - If the config file does not exist or if there is an error parsing the config file.
|
|
10
|
+
*/
|
|
11
|
+
export function ConfigFileProcessing(): void;
|
|
12
|
+
export function ConfigFilePresent(): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function isDirectory(path: any): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function isFile(path: any): boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read a JSON file and return its contents.
|
|
3
|
+
* @param {string} path Path to the JSON file.
|
|
4
|
+
* @returns {object} Parsed JSON object.
|
|
5
|
+
* @throws {Error} If the file does not exist.
|
|
6
|
+
* @throws {Error} If the file is not a valid JSON file.
|
|
7
|
+
* @example
|
|
8
|
+
* const contents = reader('test/Config/files/valid.json');
|
|
9
|
+
* console.log(contents); // {"story-format": 'Harlowe', "story-title": "My Story"}
|
|
10
|
+
*/
|
|
11
|
+
export function reader(path: string): object;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates an Interactive Fiction Identification (IFID) based the Treaty of Babel.
|
|
3
|
+
*
|
|
4
|
+
* For Twine works, the IFID is a UUID (v4) in uppercase.
|
|
5
|
+
* @see Treaty of Babel ({@link https://babel.ifarchive.org/babel_rev11.html#the-ifid-for-an-html-story-file})
|
|
6
|
+
* @function generate
|
|
7
|
+
* @description Generates a new IFID.
|
|
8
|
+
* @returns {string} IFID
|
|
9
|
+
* @example
|
|
10
|
+
* const ifid = generate();
|
|
11
|
+
* console.log(ifid);
|
|
12
|
+
* // => 'A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6'
|
|
13
|
+
*/
|
|
14
|
+
export function generate(): string;
|
|
@@ -1,8 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Parse JSON representation into Story.
|
|
3
|
+
* @see {@link https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-jsonoutput-doc.md Twine 2 JSON Specification}
|
|
3
4
|
* @function parse
|
|
4
5
|
* @param {string} jsonString - JSON string to convert to Story.
|
|
6
|
+
* @throws {Error} - Invalid JSON!
|
|
5
7
|
* @returns {Story} Story object.
|
|
8
|
+
* @example
|
|
9
|
+
* const jsonString = `{
|
|
10
|
+
* "name": "My Story",
|
|
11
|
+
* "start": "First Passage",
|
|
12
|
+
* "ifid": "A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6",
|
|
13
|
+
* "format": "SugarCube",
|
|
14
|
+
* "formatVersion": "2.31.0",
|
|
15
|
+
* "creator": "Twine",
|
|
16
|
+
* "creatorVersion": "2.3.9",
|
|
17
|
+
* "zoom": 1,
|
|
18
|
+
* "passages": [
|
|
19
|
+
* {
|
|
20
|
+
* "name": "First Passage",
|
|
21
|
+
* "tags": "",
|
|
22
|
+
* "metadata": "",
|
|
23
|
+
* "text": "This is the first passage."
|
|
24
|
+
* },
|
|
25
|
+
* ]
|
|
26
|
+
* }`;
|
|
27
|
+
* const story = parse(jsonString);
|
|
28
|
+
* console.log(story);
|
|
29
|
+
* // => Story {
|
|
30
|
+
* // name: 'My Story',
|
|
31
|
+
* // start: 'First Passage',
|
|
32
|
+
* // IFID: 'A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6',
|
|
33
|
+
* // format: 'SugarCube',
|
|
34
|
+
* // formatVersion: '2.31.0',
|
|
35
|
+
* // creator: 'Twine',
|
|
36
|
+
* // creatorVersion: '2.3.9',
|
|
37
|
+
* // zoom: 1,
|
|
38
|
+
* // tagColors: {},
|
|
39
|
+
* // metadata: {},
|
|
40
|
+
* // passages: [
|
|
41
|
+
* // Passage {
|
|
42
|
+
* // name: 'First Passage',
|
|
43
|
+
* // tags: '',
|
|
44
|
+
* // metadata: '',
|
|
45
|
+
* // text: 'This is the first passage.'
|
|
46
|
+
* // }
|
|
47
|
+
* // ]
|
|
48
|
+
* // }
|
|
6
49
|
*/
|
|
7
50
|
export function parse(jsonString: string): Story;
|
|
8
|
-
import Story from '../Story.js';
|
|
51
|
+
import { Story } from '../Story.js';
|