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,50 +0,0 @@
1
- import {jest} from '@jest/globals';
2
-
3
- // Mock the fs module before importing anything that uses it
4
- const mockStatSync = jest.fn();
5
- jest.unstable_mockModule('node:fs', () => ({
6
- statSync: mockStatSync
7
- }));
8
-
9
- // Now import the modules that depend on the mocked module
10
- const { isDirectory } = await import('../../src/CLI/isDirectory.js');
11
-
12
- describe('isDirectory', () => {
13
- afterEach(() => {
14
- jest.clearAllMocks();
15
- });
16
-
17
- it('should return true if the path is a directory', () => {
18
- const mockStats = { isDirectory: jest.fn(() => true) };
19
- mockStatSync.mockReturnValue(mockStats);
20
-
21
- const result = isDirectory('/valid/directory/path');
22
- expect(mockStatSync).toHaveBeenCalledWith('/valid/directory/path');
23
- expect(mockStats.isDirectory).toHaveBeenCalled();
24
- expect(result).toBe(true);
25
- });
26
-
27
- it('should return false if the path is not a directory', () => {
28
- const mockStats = { isDirectory: jest.fn(() => false) };
29
- mockStatSync.mockReturnValue(mockStats);
30
-
31
- const result = isDirectory('/valid/file/path');
32
- expect(mockStatSync).toHaveBeenCalledWith('/valid/file/path');
33
- expect(mockStats.isDirectory).toHaveBeenCalled();
34
- expect(result).toBe(false);
35
- });
36
-
37
- it('should return false and log an error if statSync throws an error', () => {
38
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
39
- mockStatSync.mockImplementation(() => {
40
- throw new Error('Test error');
41
- });
42
-
43
- const result = isDirectory('/invalid/path');
44
- expect(mockStatSync).toHaveBeenCalledWith('/invalid/path');
45
- expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Error: Test error'));
46
- expect(result).toBe(false);
47
-
48
- consoleErrorSpy.mockRestore();
49
- });
50
- });
@@ -1,53 +0,0 @@
1
- import {jest} from '@jest/globals';
2
-
3
- // Mock the fs module before importing anything that uses it
4
- const mockStatSync = jest.fn();
5
- jest.unstable_mockModule('node:fs', () => ({
6
- statSync: mockStatSync
7
- }));
8
-
9
- // Now import the modules that depend on the mocked module
10
- const { isFile } = await import('../../src/CLI/isFile.js');
11
-
12
- describe('isFile', () => {
13
- afterEach(() => {
14
- jest.clearAllMocks();
15
- });
16
-
17
- it('should return true if the path is a valid file', () => {
18
- // Mock statSync to return an object with isFile() returning true.
19
- mockStatSync.mockReturnValue({
20
- isFile: jest.fn(() => true),
21
- });
22
-
23
- const result = isFile('/path/to/file');
24
- expect(result).toBe(true);
25
- expect(mockStatSync).toHaveBeenCalledWith('/path/to/file');
26
- });
27
-
28
- it('should return false if the path is not a valid file', () => {
29
- // Mock statSync to return an object with isFile() returning false.
30
- mockStatSync.mockReturnValue({
31
- isFile: jest.fn(() => false),
32
- });
33
-
34
- const result = isFile('/path/to/directory');
35
- expect(result).toBe(false);
36
- expect(mockStatSync).toHaveBeenCalledWith('/path/to/directory');
37
- });
38
-
39
- it('should return false and log an error if statSync throws an error', () => {
40
- // Mock statSync to throw an error.
41
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
42
- mockStatSync.mockImplementation(() => {
43
- throw new Error('File not found');
44
- });
45
-
46
- const result = isFile('/invalid/path');
47
- expect(result).toBe(false);
48
- expect(mockStatSync).toHaveBeenCalledWith('/invalid/path');
49
- expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining('Error: Error: File not found'));
50
-
51
- consoleErrorSpy.mockRestore();
52
- });
53
- });
@@ -1,117 +0,0 @@
1
- import {jest} from '@jest/globals';
2
-
3
- // Mock all dependencies before importing anything that uses them
4
- const mockIsDirectory = jest.fn();
5
- const mockIsFile = jest.fn();
6
- const mockReadDirectories = jest.fn();
7
- const mockReadFileSync = jest.fn();
8
-
9
- jest.unstable_mockModule("../../src/CLI/isDirectory.js", () => ({
10
- isDirectory: mockIsDirectory
11
- }));
12
-
13
- jest.unstable_mockModule("../../src/CLI/isFile.js", () => ({
14
- isFile: mockIsFile
15
- }));
16
-
17
- jest.unstable_mockModule("../../src/CLI/ProcessConfig/readDirectories.js", () => ({
18
- readDirectories: mockReadDirectories
19
- }));
20
-
21
- jest.unstable_mockModule("node:fs", () => ({
22
- readFileSync: mockReadFileSync
23
- }));
24
-
25
- // Now import the modules that depend on the mocked modules
26
- const { loadStoryFormat } = await import("../../src/CLI/ProcessConfig/loadStoryFormat.js");
27
-
28
- describe("loadStoryFormat", () => {
29
- afterEach(() => {
30
- jest.clearAllMocks();
31
- });
32
-
33
- it("should throw an error if the story-formats directory does not exist", () => {
34
- mockIsDirectory.mockReturnValueOnce(false);
35
-
36
- expect(() => loadStoryFormat("Harlowe", "3.2.0")).toThrow(
37
- "Error: story-formats directory does not exist. Consider running 'npx sfa-get' to download the latest story formats."
38
- );
39
- });
40
-
41
- it("should throw an error if the named story format directory does not exist", () => {
42
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(false);
43
-
44
- expect(() => loadStoryFormat("Harlowe", "3.2.0")).toThrow(
45
- "Error: story format Harlowe does not exist in the story-formats directory."
46
- );
47
- });
48
-
49
- it("should throw an error if the version directory does not exist", () => {
50
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true).mockReturnValueOnce(false);
51
-
52
- expect(() => loadStoryFormat("Harlowe", "3.2.0")).toThrow(
53
- "Error: story format Harlowe version 3.2.0 does not exist in the story-formats directory."
54
- );
55
- });
56
-
57
- it("should throw an error if the format.js file does not exist in the version directory", () => {
58
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true).mockReturnValueOnce(true);
59
- mockIsFile.mockReturnValueOnce(false);
60
-
61
- expect(() => loadStoryFormat("Harlowe", "3.2.0")).toThrow(
62
- "Error: story format Harlowe version 3.2.0 does not have a format.js file."
63
- );
64
- });
65
-
66
- it("should return the contents of the format.js file if all checks pass", () => {
67
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true).mockReturnValueOnce(true);
68
- mockIsFile.mockReturnValueOnce(true);
69
- mockReadFileSync.mockReturnValueOnce("format.js content");
70
-
71
- const result = loadStoryFormat("Harlowe", "3.2.0");
72
- expect(result).toBe("format.js content");
73
- });
74
-
75
- it("should handle 'latest' version and return the contents of the format.js file", () => {
76
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true);
77
- mockIsFile.mockReturnValueOnce(false).mockReturnValueOnce(true);
78
- mockReadDirectories.mockReturnValueOnce(["3.2.0", "3.1.0"]);
79
- mockReadFileSync.mockReturnValueOnce("latest format.js content");
80
-
81
- const result = loadStoryFormat("Harlowe", "latest");
82
- expect(result).toBe("latest format.js content");
83
- expect(mockReadDirectories).toHaveBeenCalledWith("story-formats/Harlowe");
84
- });
85
-
86
- it("should throw an error if 'latest' version has no format.js file", () => {
87
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true);
88
- mockIsFile.mockReturnValueOnce(false).mockReturnValueOnce(false);
89
- mockReadDirectories.mockReturnValueOnce(["3.2.0", "3.1.0"]);
90
-
91
- expect(() => loadStoryFormat("Harlowe", "latest")).toThrow(
92
- "Error: story format Harlowe version latest does not have a format.js file."
93
- );
94
- });
95
-
96
- it("should read format.js file from the story format directory if it exists", () => {
97
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true);
98
- mockIsFile.mockReturnValueOnce(true);
99
- mockReadDirectories.mockReturnValueOnce([]);
100
- mockReadFileSync.mockReturnValueOnce("latest format.js content");
101
-
102
- const result = loadStoryFormat("Harlowe", "latest");
103
- expect(result).toBe("latest format.js content");
104
- expect(mockReadFileSync).toHaveBeenCalledWith("story-formats/Harlowe/format.js", "utf-8");
105
- });
106
-
107
- it("should throw an error if the story format version is not 'latest' and version directories do not exist", () => {
108
- mockIsDirectory.mockReturnValueOnce(true).mockReturnValueOnce(true);
109
- mockIsFile.mockReturnValueOnce(false);
110
- mockReadDirectories.mockReturnValueOnce([]);
111
-
112
- expect(() => loadStoryFormat("Harlowe", "latest")).toThrow(
113
- `Error: story format Harlowe does not have any version directories.`
114
- );
115
- }
116
- );
117
- });
@@ -1,78 +0,0 @@
1
- import {jest} from '@jest/globals';
2
-
3
- // Mock the fs module and isDirectory before importing anything that uses them
4
- const mockReaddirSync = jest.fn();
5
- const mockIsDirectory = jest.fn();
6
-
7
- jest.unstable_mockModule('node:fs', () => ({
8
- readdirSync: mockReaddirSync
9
- }));
10
-
11
- jest.unstable_mockModule('../../src/CLI/isDirectory.js', () => ({
12
- isDirectory: mockIsDirectory
13
- }));
14
-
15
- // Now import the modules that depend on the mocked modules
16
- const { readDirectories } = await import('../../src/CLI/ProcessConfig/readDirectories.js');
17
-
18
- describe('readDirectories', () => {
19
- afterEach(() => {
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should return an empty array and log an error if the directory does not exist', () => {
24
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
25
- mockIsDirectory.mockReturnValue(false);
26
-
27
- const result = readDirectories('/nonexistent');
28
-
29
- expect(result).toEqual([]);
30
- expect(consoleErrorSpy).toHaveBeenCalledWith('Error: Directory /nonexistent does not exist.');
31
- consoleErrorSpy.mockRestore();
32
- });
33
-
34
- it('should return an empty array and log an error if readdirSync throws an error', () => {
35
- const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
36
- mockIsDirectory.mockReturnValue(true);
37
- mockReaddirSync.mockImplementation(() => {
38
- throw new Error('Permission denied');
39
- });
40
-
41
- const result = readDirectories('/restricted');
42
-
43
- expect(result).toEqual([]);
44
- expect(consoleErrorSpy).toHaveBeenCalledWith('Error reading directory /restricted:', expect.any(Error));
45
- consoleErrorSpy.mockRestore();
46
- });
47
-
48
- it('should return an empty array if the directory is empty', () => {
49
- mockIsDirectory.mockReturnValue(true);
50
- mockReaddirSync.mockReturnValue([]);
51
-
52
- const result = readDirectories('/empty');
53
-
54
- expect(result).toEqual([]);
55
- });
56
-
57
- it('should return an array of directories', () => {
58
- mockIsDirectory.mockReturnValue(true);
59
- mockReaddirSync.mockReturnValue(['dir1', 'file1', 'dir2']);
60
-
61
- mockIsDirectory.mockImplementation((path) => {
62
- return path === '/test/dir1' || path === '/test/dir2';
63
- });
64
-
65
- const result = readDirectories('/test');
66
-
67
- expect(result).toEqual(['dir1', 'dir2']);
68
- });
69
-
70
- it('should return an empty array if the result is not an array', () => {
71
- mockIsDirectory.mockReturnValue(true);
72
- mockReaddirSync.mockReturnValue('not an array');
73
-
74
- const result = readDirectories('/test');
75
-
76
- expect(result).toEqual([]);
77
- });
78
- });
@@ -1,10 +0,0 @@
1
- import { generate } from '../../src/IFID/generate.js';
2
-
3
- describe('src/IFID/generate.js', () => {
4
- describe('generate()', () => {
5
- it('should generate a valid IFID', () => {
6
- const ifid = generate();
7
- expect(ifid).toMatch(/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/);
8
- });
9
- });
10
- });
@@ -1,316 +0,0 @@
1
- import { Story, creatorVersion, creatorName } from '../../src/Story.js';
2
- import Passage from '../../src/Passage.js';
3
- import { parse as parseJSON } from '../../src/JSON/parse.js';
4
-
5
- describe('JSON', () => {
6
- describe('parse()', function () {
7
- it('Should throw error if JSON is invalid', function () {
8
- expect(() => { parseJSON('{'); }).toThrow();
9
- });
10
-
11
- it('Should roundtrip default Story values using toJSON() and fromJSON()', function () {
12
- // Create Story.
13
- const r = new Story();
14
-
15
- // Convert to JSON and back.
16
- const s = parseJSON(r.toJSON());
17
-
18
- // Check all properties.
19
- expect(s.name).toBe('Untitled Story');
20
- expect(Object.keys(s.tagColors).length).toBe(0);
21
- expect(s.IFID).toBe('');
22
- expect(s.start).toBe('');
23
- expect(s.formatVersion).toBe('');
24
- expect(s.format).toBe('');
25
- expect(s.creator).toBe(creatorName);
26
- expect(s.creatorVersion).toBe(creatorVersion);
27
- expect(s.zoom).toBe(1);
28
- expect(Object.keys(s.metadata).length).toBe(0);
29
- });
30
-
31
- it('Should parse passage data', function () {
32
- // Create passage.
33
- const p = new Passage('Test', 'Default');
34
-
35
- // Create Story.
36
- const s = new Story();
37
-
38
- // Add a passage.
39
- s.addPassage(p);
40
-
41
- // Convert to JSON.
42
- const js = s.toJSON(s);
43
-
44
- // Convert back to Story.
45
- const result = parseJSON(js);
46
-
47
- // Should have a single passage.
48
- expect(result.size()).toBe(1);
49
- });
50
-
51
- describe('Partial Story Processing', function () {
52
- it('Should parse everything but name', function () {
53
- const s = '{"tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
54
- const r = parseJSON(s);
55
- expect(r.name).toBe('Untitled Story');
56
- expect(Object.keys(r.tagColors).length).toBe(1);
57
- expect(r.IFID).toBe('DD');
58
- expect(r.start).toBe('Start');
59
- expect(r.formatVersion).toBe('1.0');
60
- expect(Object.keys(r.metadata).length).toBe(1);
61
- expect(r.format).toBe('Snowman');
62
- expect(r.creator).toBe(creatorName);
63
- expect(r.creatorVersion).toBe('2.2.0');
64
- expect(r.zoom).toBe(1);
65
- expect(r.size()).toBe(1);
66
- });
67
-
68
- it('Should parse everything but tagColors', function () {
69
- const s = '{"name":"Test","ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
70
- const r = parseJSON(s);
71
- expect(r.name).toBe('Test');
72
- expect(Object.keys(r.tagColors).length).toBe(0);
73
- expect(r.IFID).toBe('DD');
74
- expect(r.start).toBe('Start');
75
- expect(r.formatVersion).toBe('1.0');
76
- expect(Object.keys(r.metadata).length).toBe(1);
77
- expect(r.format).toBe('Snowman');
78
- expect(r.creator).toBe(creatorName);
79
- expect(r.creatorVersion).toBe('2.2.0');
80
- expect(r.zoom).toBe(1);
81
- expect(r.size()).toBe(1);
82
- });
83
-
84
- it('Should parse everything but ifid', function () {
85
- const s = '{"name":"Test","tagColors":{"r":"red"},"start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
86
- const r = parseJSON(s);
87
- expect(r.name).toBe('Test');
88
- expect(Object.keys(r.tagColors).length).toBe(1);
89
- expect(r.IFID).toBe('');
90
- expect(r.start).toBe('Start');
91
- expect(r.formatVersion).toBe('1.0');
92
- expect(Object.keys(r.metadata).length).toBe(1);
93
- expect(r.format).toBe('Snowman');
94
- expect(r.creator).toBe(creatorName);
95
- expect(r.creatorVersion).toBe('2.2.0');
96
- expect(r.zoom).toBe(1);
97
- expect(r.size()).toBe(1);
98
- });
99
-
100
- it('Should parse everything but start', function () {
101
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Star","tags":["tag1"],"metadata":{},"text":"Word"}]}';
102
- const r = parseJSON(s);
103
- expect(r.name).toBe('Test');
104
- expect(Object.keys(r.tagColors).length).toBe(1);
105
- expect(r.IFID).toBe('DD');
106
- expect(r.start).toBe('');
107
- expect(r.formatVersion).toBe('1.0');
108
- expect(Object.keys(r.metadata).length).toBe(1);
109
- expect(r.format).toBe('Snowman');
110
- expect(r.creator).toBe(creatorName);
111
- expect(r.creatorVersion).toBe('2.2.0');
112
- expect(r.zoom).toBe(1);
113
- expect(r.size()).toBe(1);
114
- });
115
-
116
- it('Should parse everything but formatVersion', function () {
117
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
118
- const r = parseJSON(s);
119
- expect(r.name).toBe('Test');
120
- expect(Object.keys(r.tagColors).length).toBe(1);
121
- expect(r.IFID).toBe('DD');
122
- expect(r.start).toBe('Start');
123
- expect(r.formatVersion).toBe('');
124
- expect(Object.keys(r.metadata).length).toBe(1);
125
- expect(r.format).toBe('Snowman');
126
- expect(r.creator).toBe(creatorName);
127
- expect(r.creatorVersion).toBe('2.2.0');
128
- expect(r.zoom).toBe(1);
129
- expect(r.size()).toBe(1);
130
- });
131
-
132
- it('Should parse everything but format', function () {
133
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
134
- const r = parseJSON(s);
135
- expect(r.name).toBe('Test');
136
- expect(Object.keys(r.tagColors).length).toBe(1);
137
- expect(r.IFID).toBe('DD');
138
- expect(r.start).toBe('Start');
139
- expect(r.formatVersion).toBe('1.0');
140
- expect(Object.keys(r.metadata).length).toBe(1);
141
- expect(r.format).toBe('');
142
- expect(r.creator).toBe(creatorName);
143
- expect(r.creatorVersion).toBe('2.2.0');
144
- expect(r.zoom).toBe(1);
145
- expect(r.size()).toBe(1);
146
- });
147
-
148
- it('Should parse everything but creator', function () {
149
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
150
- const r = parseJSON(s);
151
- expect(r.name).toBe('Test');
152
- expect(Object.keys(r.tagColors).length).toBe(1);
153
- expect(r.IFID).toBe('DD');
154
- expect(r.start).toBe('Start');
155
- expect(r.formatVersion).toBe('1.0');
156
- expect(Object.keys(r.metadata).length).toBe(1);
157
- expect(r.format).toBe('Snowman');
158
- expect(r.creator).toBe(creatorName);
159
- expect(r.creatorVersion).toBe('2.2.0');
160
- expect(r.zoom).toBe(1);
161
- expect(r.size()).toBe(1);
162
- });
163
-
164
- it('Should parse everything but creator version', function () {
165
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
166
- const r = parseJSON(s);
167
- expect(r.name).toBe('Test');
168
- expect(Object.keys(r.tagColors).length).toBe(1);
169
- expect(r.IFID).toBe('DD');
170
- expect(r.start).toBe('Start');
171
- expect(r.formatVersion).toBe('1.0');
172
- expect(Object.keys(r.metadata).length).toBe(1);
173
- expect(r.format).toBe('Snowman');
174
- expect(r.creator).toBe(creatorName);
175
- expect(r.creatorVersion).toBe(creatorVersion);
176
- expect(r.zoom).toBe(1);
177
- expect(r.size()).toBe(1);
178
- });
179
-
180
- it('Should parse everything but zoom', function () {
181
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
182
- const r = parseJSON(s);
183
- expect(r.name).toBe('Test');
184
- expect(Object.keys(r.tagColors).length).toBe(1);
185
- expect(r.IFID).toBe('DD');
186
- expect(r.start).toBe('Start');
187
- expect(r.formatVersion).toBe('1.0');
188
- expect(Object.keys(r.metadata).length).toBe(1);
189
- expect(r.format).toBe('Snowman');
190
- expect(r.creator).toBe(creatorName);
191
- expect(r.creatorVersion).toBe('2.2.0');
192
- expect(r.zoom).toBe(1);
193
- expect(r.size()).toBe(1);
194
- });
195
-
196
- it('Should parse everything but metadata', function () {
197
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{},"text":"Word"}]}';
198
- const r = parseJSON(s);
199
- expect(r.name).toBe('Test');
200
- expect(Object.keys(r.tagColors).length).toBe(1);
201
- expect(r.IFID).toBe('DD');
202
- expect(r.start).toBe('Start');
203
- expect(r.formatVersion).toBe('1.0');
204
- expect(Object.keys(r.metadata).length).toBe(0);
205
- expect(r.format).toBe('Snowman');
206
- expect(r.creator).toBe(creatorName);
207
- expect(r.creatorVersion).toBe('2.2.0');
208
- expect(r.zoom).toBe(1);
209
- expect(r.size()).toBe(1);
210
- });
211
-
212
- it('Should parse everything but passages', function () {
213
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1}';
214
- const r = parseJSON(s);
215
- expect(r.name).toBe('Test');
216
- expect(Object.keys(r.tagColors).length).toBe(1);
217
- expect(r.IFID).toBe('DD');
218
- expect(r.start).toBe('Start');
219
- expect(r.formatVersion).toBe('1.0');
220
- expect(Object.keys(r.metadata).length).toBe(1);
221
- expect(r.format).toBe('Snowman');
222
- expect(r.creator).toBe(creatorName);
223
- expect(r.creatorVersion).toBe('2.2.0');
224
- expect(r.zoom).toBe(1);
225
- expect(r.size()).toBe(0);
226
- });
227
-
228
- it('Should ignore non-arrays for passages', function () {
229
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":{}}';
230
- const r = parseJSON(s);
231
- expect(r.name).toBe('Test');
232
- expect(Object.keys(r.tagColors).length).toBe(1);
233
- expect(r.IFID).toBe('DD');
234
- expect(r.start).toBe('Start');
235
- expect(r.formatVersion).toBe('1.0');
236
- expect(Object.keys(r.metadata).length).toBe(1);
237
- expect(r.format).toBe('Snowman');
238
- expect(r.creator).toBe(creatorName);
239
- expect(r.creatorVersion).toBe('2.2.0');
240
- expect(r.zoom).toBe(1);
241
- expect(r.size()).toBe(0);
242
- });
243
-
244
- it('Should parse everything but passage name', function () {
245
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"tags":["tag1"],"metadata":{},"text":"Word"}]}';
246
- const r = parseJSON(s);
247
- expect(r.name).toBe('Test');
248
- expect(Object.keys(r.tagColors).length).toBe(1);
249
- expect(r.IFID).toBe('DD');
250
- expect(r.start).toBe('Start');
251
- expect(r.formatVersion).toBe('1.0');
252
- expect(Object.keys(r.metadata).length).toBe(1);
253
- expect(r.format).toBe('Snowman');
254
- expect(r.creator).toBe(creatorName);
255
- expect(r.creatorVersion).toBe('2.2.0');
256
- expect(r.zoom).toBe(1);
257
- expect(r.size()).toBe(1);
258
- expect(r.getPassageByName('').name).toBe('');
259
- });
260
-
261
- it('Should parse everything but passage tags', function () {
262
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","metadata":{"s":"e"},"text":"Word"}]}';
263
- const r = parseJSON(s);
264
- expect(r.name).toBe('Test');
265
- expect(Object.keys(r.tagColors).length).toBe(1);
266
- expect(r.IFID).toBe('DD');
267
- expect(r.start).toBe('Start');
268
- expect(r.formatVersion).toBe('1.0');
269
- expect(Object.keys(r.metadata).length).toBe(1);
270
- expect(r.format).toBe('Snowman');
271
- expect(r.creator).toBe(creatorName);
272
- expect(r.creatorVersion).toBe('2.2.0');
273
- expect(r.zoom).toBe(1);
274
- expect(r.size()).toBe(1);
275
- expect(r.getPassageByName('Start').metadata.s).toBe('e');
276
- expect(r.getPassageByName('Start').tags.length).toBe(0);
277
- });
278
-
279
- it('Should parse everything but passage text', function () {
280
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"metadata":{"s":"e"}}]}';
281
- const r = parseJSON(s);
282
- expect(r.name).toBe('Test');
283
- expect(Object.keys(r.tagColors).length).toBe(1);
284
- expect(r.IFID).toBe('DD');
285
- expect(r.start).toBe('Start');
286
- expect(r.formatVersion).toBe('1.0');
287
- expect(Object.keys(r.metadata).length).toBe(1);
288
- expect(r.format).toBe('Snowman');
289
- expect(r.creator).toBe(creatorName);
290
- expect(r.creatorVersion).toBe('2.2.0');
291
- expect(r.zoom).toBe(1);
292
- expect(r.size()).toBe(1);
293
- expect(r.getPassageByName('Start').metadata.s).toBe('e');
294
- expect(r.getPassageByName('Start').text).toBe('');
295
- });
296
-
297
- it('Parse everything but passage metadata', function () {
298
- const s = '{"name":"Test","tagColors":{"r":"red"},"ifid":"dd","start":"Start","formatVersion":"1.0","metadata":{"some":"thing"},"format":"Snowman","creator":"extwee","creatorVersion":"2.2.0","zoom":1,"passages":[{"name":"Start","tags":["tag1"],"text":"Word"}]}';
299
- const r = parseJSON(s);
300
- expect(r.name).toBe('Test');
301
- expect(Object.keys(r.tagColors).length).toBe(1);
302
- expect(r.IFID).toBe('DD');
303
- expect(r.start).toBe('Start');
304
- expect(r.formatVersion).toBe('1.0');
305
- expect(Object.keys(r.metadata).length).toBe(1);
306
- expect(r.format).toBe('Snowman');
307
- expect(r.creator).toBe(creatorName);
308
- expect(r.creatorVersion).toBe('2.2.0');
309
- expect(r.zoom).toBe(1);
310
- expect(r.size()).toBe(1);
311
- expect(Object.prototype.hasOwnProperty.call(r.getPassageByName('Start').metadata, 's')).toBe(false);
312
- expect(r.getPassageByName('Start').text).toBe('Word');
313
- });
314
- });
315
- });
316
- });