extwee 1.5.3 → 2.0.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/.eslintrc.json +25 -0
- package/.github/workflows/nodejs.yml +24 -0
- package/.travis.yml +13 -0
- package/CODE_OF_CONDUCT.md +82 -0
- package/LICENSE +21 -21
- package/README.md +36 -203
- package/SECURITY.md +12 -0
- package/babel.config.json +22 -0
- package/bin/extwee.js +49 -0
- package/index.js +31 -26
- package/package.json +60 -39
- package/src/FileReader.js +33 -0
- package/src/HTMLParser.js +343 -0
- package/src/HTMLWriter.js +196 -0
- package/src/Passage.js +202 -0
- package/src/Story.js +461 -0
- package/src/StoryFormat.js +300 -0
- package/src/StoryFormatParser.js +142 -0
- package/src/TweeParser.js +166 -0
- package/src/TweeWriter.js +98 -0
- package/story-formats/chapbook-1.2.0/format.js +1 -0
- package/story-formats/chapbook-1.2.0/logo.svg +1 -0
- package/story-formats/harlowe-1.2.4/format.js +1 -0
- package/story-formats/harlowe-1.2.4/icon.svg +78 -0
- package/story-formats/harlowe-2.1.0/format.js +2 -0
- package/story-formats/harlowe-2.1.0/icon.svg +78 -0
- package/story-formats/harlowe-3.1.0/format.js +3 -0
- package/story-formats/harlowe-3.1.0/icon.svg +78 -0
- package/story-formats/paperthin-1.0.0/format.js +1 -0
- package/story-formats/paperthin-1.0.0/icon.svg +5 -0
- package/story-formats/snowman-1.4.0/format.js +1 -0
- package/story-formats/snowman-1.4.0/icon.svg +436 -0
- package/story-formats/snowman-2.0.2/format.js +1 -0
- package/story-formats/snowman-2.0.2/icon.svg +436 -0
- package/story-formats/sugarcube-1.0.35/LICENSE +23 -0
- package/story-formats/sugarcube-1.0.35/format.js +1 -0
- package/story-formats/sugarcube-1.0.35/icon.svg +56 -0
- package/story-formats/sugarcube-2.31.1/LICENSE +22 -0
- package/story-formats/sugarcube-2.31.1/format.js +1 -0
- package/story-formats/sugarcube-2.31.1/icon.svg +56 -0
- package/test/CLI/example6.twee +16 -0
- package/test/CLI/harlowe.js +3 -0
- package/test/CLI/input.html +47 -0
- package/test/CLI/test.twee +18 -0
- package/test/CLI/test2.html +47 -0
- package/test/CLI/tweeExample.twee +17 -0
- package/test/CLI/twineExample.html +15 -0
- package/test/CLI.test.js +30 -0
- package/test/FileReader/t1.txt +1 -0
- package/test/FileReader.test.js +14 -0
- package/test/HTMLParser/Example1.html +53 -0
- package/test/HTMLParser/Tags.html +15 -0
- package/test/HTMLParser/lyingStartnode.html +15 -0
- package/test/HTMLParser/lyingTagColors.html +48 -0
- package/test/HTMLParser/missingCreator.html +11 -0
- package/test/HTMLParser/missingCreatorVersion.html +11 -0
- package/test/HTMLParser/missingFormat.html +11 -0
- package/test/HTMLParser/missingFormatVersion.html +11 -0
- package/test/HTMLParser/missingIFID.html +11 -0
- package/test/HTMLParser/missingName.html +33 -0
- package/test/HTMLParser/missingPID.html +15 -0
- package/test/HTMLParser/missingPassageName.html +15 -0
- package/test/HTMLParser/missingPassageTags.html +15 -0
- package/test/HTMLParser/missingPosition.html +15 -0
- package/test/HTMLParser/missingScript.html +14 -0
- package/test/HTMLParser/missingSize.html +35 -0
- package/test/HTMLParser/missingStartnode.html +11 -0
- package/test/HTMLParser/missingStyle.html +14 -0
- package/test/HTMLParser/missingZoom.html +11 -0
- package/test/HTMLParser/tagColors.html +31 -0
- package/test/HTMLParser/twineExample.html +15 -0
- package/test/HTMLParser/twineExample2.html +15 -0
- package/test/HTMLParser/twineExample3.html +15 -0
- package/test/HTMLParser.test.js +177 -0
- package/test/HTMLWriter/TestTags.html +42 -0
- package/test/HTMLWriter/creator.html +51 -0
- package/test/HTMLWriter/example6.twee +16 -0
- package/test/HTMLWriter/missingStoryTitle.twee +29 -0
- package/test/HTMLWriter/test11.html +123 -0
- package/test/HTMLWriter/test2.html +59 -0
- package/test/HTMLWriter/test3.html +50 -0
- package/test/HTMLWriter/test4.html +51 -0
- package/test/HTMLWriter/test6.html +50 -0
- package/test/HTMLWriter.test.js +279 -0
- package/test/Passage.test.js +104 -0
- package/test/Roundtrip/Example1.html +64 -0
- package/test/Roundtrip/example1.twee +21 -0
- package/test/Roundtrip/example2.twee +18 -0
- package/test/Roundtrip/harlowe.js +3 -0
- package/test/Roundtrip/round.html +50 -0
- package/test/Roundtrip.test.js +48 -0
- package/test/Story/startmeta.twee +29 -0
- package/test/Story/test.twee +25 -0
- package/test/Story.test.js +282 -0
- package/test/StoryFormat.test.js +152 -0
- package/test/StoryFormatParser/example.js +3 -0
- package/test/StoryFormatParser/example2.js +3 -0
- package/test/StoryFormatParser/format.js +1 -0
- package/test/StoryFormatParser/format_doublename.js +1 -0
- package/test/StoryFormatParser/harlowe.js +3 -0
- package/test/StoryFormatParser/missingAuthor.js +1 -0
- package/test/StoryFormatParser/missingDescription.js +1 -0
- package/test/StoryFormatParser/missingImage.js +1 -0
- package/test/StoryFormatParser/missingLicense.js +1 -0
- package/test/StoryFormatParser/missingName.js +1 -0
- package/test/StoryFormatParser/missingProofing.js +1 -0
- package/test/StoryFormatParser/missingSource.js +1 -0
- package/test/StoryFormatParser/missingURL.js +1 -0
- package/test/StoryFormatParser/missingVersion.js +1 -0
- package/test/StoryFormatParser/versionWrong.js +1 -0
- package/test/StoryFormatParser.test.js +91 -0
- package/test/TweeParser/emptytags.twee +2 -0
- package/test/TweeParser/example.twee +32 -0
- package/test/TweeParser/missing.twee +19 -0
- package/test/TweeParser/multipleScriptPassages.twee +19 -0
- package/test/TweeParser/multipleStyleTag.twee +19 -0
- package/test/TweeParser/multipletags.twee +10 -0
- package/test/TweeParser/noTitle.twee +2 -0
- package/test/TweeParser/notes.twee +16 -0
- package/test/TweeParser/pasagemetadataerror.twee +2 -0
- package/test/TweeParser/scriptPassage.twee +16 -0
- package/test/TweeParser/singletag.twee +13 -0
- package/test/TweeParser/startMetadata.twee +14 -0
- package/test/TweeParser/storydataerror.twee +25 -0
- package/test/TweeParser/stylePassage.twee +16 -0
- package/test/TweeParser/test.twee +25 -0
- package/test/TweeParser.test.js +79 -0
- package/test/TweeWriter/test1.twee +18 -0
- package/test/TweeWriter/test3.twee +12 -0
- package/test/TweeWriter/test4.twee +14 -0
- package/test/TweeWriter/test5.twee +20 -0
- package/test/TweeWriter.test.js +82 -0
- package/DirectoryReader.js +0 -128
- package/DirectoryWatcher.js +0 -63
- package/FileReader.js +0 -36
- package/HTMLParser.js +0 -206
- package/HTMLWriter.js +0 -177
- package/Passage.js +0 -20
- package/Story.js +0 -148
- package/StoryFormat.js +0 -41
- package/StoryFormatParser.js +0 -65
- package/TweeParser.js +0 -255
- package/TweeWriter.js +0 -111
- package/main.js +0 -103
package/src/Passage.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @class Passage
|
|
3
|
+
* @module Passage
|
|
4
|
+
*/
|
|
5
|
+
export default class Passage {
|
|
6
|
+
/**
|
|
7
|
+
* Name of the Passage
|
|
8
|
+
*
|
|
9
|
+
* @private
|
|
10
|
+
*/
|
|
11
|
+
#_name = null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Internal array of tags
|
|
15
|
+
*
|
|
16
|
+
* @private
|
|
17
|
+
*/
|
|
18
|
+
#_tags = [];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Internal metadata of passage
|
|
22
|
+
*
|
|
23
|
+
* @private
|
|
24
|
+
*/
|
|
25
|
+
#_metadata = {};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Internal text of the passage
|
|
29
|
+
*
|
|
30
|
+
* @private
|
|
31
|
+
*/
|
|
32
|
+
#_text = '';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Internal PID of passage
|
|
36
|
+
*
|
|
37
|
+
* @private
|
|
38
|
+
*/
|
|
39
|
+
#_pid = -1;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @function Passage
|
|
43
|
+
* @class
|
|
44
|
+
* @param {string} name - Name
|
|
45
|
+
* @param {string} text - Content
|
|
46
|
+
* @param {Array} tags - Tags
|
|
47
|
+
* @param {object} metadata - Metadata
|
|
48
|
+
* @param {number} pid - Passage ID (PID)
|
|
49
|
+
*/
|
|
50
|
+
constructor (name = '', text = '', tags = [], metadata = {}, pid = -1) {
|
|
51
|
+
// Set name
|
|
52
|
+
this.name = name;
|
|
53
|
+
|
|
54
|
+
// Set tags
|
|
55
|
+
this.tags = tags;
|
|
56
|
+
|
|
57
|
+
// Set metadata
|
|
58
|
+
this.metadata = metadata;
|
|
59
|
+
|
|
60
|
+
// Sets text
|
|
61
|
+
this.text = text;
|
|
62
|
+
|
|
63
|
+
// Sets pid
|
|
64
|
+
this.pid = pid;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Name
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
* @memberof Passage
|
|
72
|
+
* @returns {string} Name
|
|
73
|
+
*/
|
|
74
|
+
get name () { return this.#_name; }
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {string} s - Name to replace
|
|
78
|
+
*/
|
|
79
|
+
set name (s) {
|
|
80
|
+
if (typeof s === 'string') {
|
|
81
|
+
this.#_name = s;
|
|
82
|
+
} else {
|
|
83
|
+
throw new Error('Name must be a String!');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Tags
|
|
89
|
+
*
|
|
90
|
+
* @public
|
|
91
|
+
* @memberof Passage
|
|
92
|
+
* @returns {Array} Tags
|
|
93
|
+
*/
|
|
94
|
+
get tags () { return this.#_tags; }
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @param {Array} t - Replacement array
|
|
98
|
+
*/
|
|
99
|
+
set tags (t) {
|
|
100
|
+
// Test if tags is an array
|
|
101
|
+
if (Array.isArray(t)) {
|
|
102
|
+
this.#_tags = t;
|
|
103
|
+
} else {
|
|
104
|
+
throw new Error('Tags must be an array!');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Metadata
|
|
110
|
+
*
|
|
111
|
+
* @public
|
|
112
|
+
* @memberof Passage
|
|
113
|
+
* @returns {object} Metadata
|
|
114
|
+
*/
|
|
115
|
+
get metadata () { return this.#_metadata; }
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {object} m - Replacement object
|
|
119
|
+
*/
|
|
120
|
+
set metadata (m) {
|
|
121
|
+
// Test if metadata was an object
|
|
122
|
+
if (typeof m === 'object') {
|
|
123
|
+
this.#_metadata = m;
|
|
124
|
+
} else {
|
|
125
|
+
throw new Error('Metadata should be an object literal!');
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Text
|
|
131
|
+
*
|
|
132
|
+
* @public
|
|
133
|
+
* @memberof Passage
|
|
134
|
+
* @returns {string} Text
|
|
135
|
+
*/
|
|
136
|
+
get text () { return this.#_text; }
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @param {string} t - Replacement text
|
|
140
|
+
*/
|
|
141
|
+
set text (t) {
|
|
142
|
+
// Test if text is a String
|
|
143
|
+
if (typeof t === 'string') {
|
|
144
|
+
this.#_text = t;
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error('Text should be a String!');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Passage ID (PID)
|
|
152
|
+
*
|
|
153
|
+
* @public
|
|
154
|
+
* @memberof Passage
|
|
155
|
+
* @returns {number} Passage ID (PID)
|
|
156
|
+
*/
|
|
157
|
+
get pid () { return this.#_pid; }
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @param {number} p - Replacement PID
|
|
161
|
+
*/
|
|
162
|
+
set pid (p) {
|
|
163
|
+
// Test if PID is a number
|
|
164
|
+
if (Number.isInteger(p)) {
|
|
165
|
+
this.#_pid = p;
|
|
166
|
+
} else {
|
|
167
|
+
throw new Error('PID should be a number!');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Return a String representation
|
|
173
|
+
*
|
|
174
|
+
* @public
|
|
175
|
+
* @memberof Passage
|
|
176
|
+
* @returns {string} String form of passage
|
|
177
|
+
*/
|
|
178
|
+
toString () {
|
|
179
|
+
// Start empty string.
|
|
180
|
+
let content = '';
|
|
181
|
+
// Write the name
|
|
182
|
+
content += `:: ${this.name}`;
|
|
183
|
+
|
|
184
|
+
// Test if it has any tags
|
|
185
|
+
if (this.tags.length > 0) {
|
|
186
|
+
// Write output of tags
|
|
187
|
+
content += ` [${this.tags.join(' ')}]`;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Check if any properties exist
|
|
191
|
+
if (Object.keys(this.metadata).length > 0) {
|
|
192
|
+
// Write out a space and then passage metadata
|
|
193
|
+
content += ` ${JSON.stringify(this.metadata)}`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Add newline, text, and two newlines
|
|
197
|
+
content += `\n${this.text}\n\n`;
|
|
198
|
+
|
|
199
|
+
// Return string.
|
|
200
|
+
return content;
|
|
201
|
+
}
|
|
202
|
+
}
|
package/src/Story.js
ADDED
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
import Passage from './Passage.js';
|
|
2
|
+
|
|
3
|
+
const name = 'extwee';
|
|
4
|
+
const version = '2.0.0';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @class Story
|
|
8
|
+
* @module Story
|
|
9
|
+
*/
|
|
10
|
+
export default class Story {
|
|
11
|
+
/**
|
|
12
|
+
* Internal start
|
|
13
|
+
*
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
#_start = '';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Internal IFID
|
|
20
|
+
*
|
|
21
|
+
* @private
|
|
22
|
+
*/
|
|
23
|
+
#_IFID = ''
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Internal story format
|
|
27
|
+
*
|
|
28
|
+
* @private
|
|
29
|
+
*/
|
|
30
|
+
#_format = '';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Internal version of story format
|
|
34
|
+
*/
|
|
35
|
+
#_formatVersion = '';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Internal zoom level
|
|
39
|
+
*/
|
|
40
|
+
#_zoom = 0;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Passages
|
|
44
|
+
*
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
#_passages = [];
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Creator
|
|
51
|
+
*
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
#_creator = '';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* CreatorVersion
|
|
58
|
+
*
|
|
59
|
+
* @private
|
|
60
|
+
*/
|
|
61
|
+
#_creatorVersion = '';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Metadata
|
|
65
|
+
*
|
|
66
|
+
* @private
|
|
67
|
+
*/
|
|
68
|
+
#_metadata = null;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Tag Colors
|
|
72
|
+
*
|
|
73
|
+
* @private
|
|
74
|
+
*/
|
|
75
|
+
#_tagColors = {};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Internal PID counter
|
|
79
|
+
*
|
|
80
|
+
* @private
|
|
81
|
+
*/
|
|
82
|
+
#_PIDCounter = 1;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @function Story
|
|
86
|
+
* @class
|
|
87
|
+
*/
|
|
88
|
+
constructor () {
|
|
89
|
+
// Store the creator and version
|
|
90
|
+
this.#_creator = name;
|
|
91
|
+
this.#_creatorVersion = version;
|
|
92
|
+
// Set metadata to an object
|
|
93
|
+
this.#_metadata = {};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Tag Colors object (each property is a tag and its color)
|
|
98
|
+
*
|
|
99
|
+
* @public
|
|
100
|
+
* @readonly
|
|
101
|
+
* @memberof Story
|
|
102
|
+
* @returns {object} tag colors array
|
|
103
|
+
*/
|
|
104
|
+
get tagColors () { return this.#_tagColors; }
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {object} a - Replacement tag colors
|
|
108
|
+
*/
|
|
109
|
+
set tagColors (a) {
|
|
110
|
+
if (a instanceof Object) {
|
|
111
|
+
this.#_tagColors = a;
|
|
112
|
+
} else {
|
|
113
|
+
throw new Error('Tag colors must be an object!');
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Interactive Fiction ID (IFID) of Story
|
|
119
|
+
*
|
|
120
|
+
* @public
|
|
121
|
+
* @readonly
|
|
122
|
+
* @memberof Story
|
|
123
|
+
* @returns {string} IFID
|
|
124
|
+
*/
|
|
125
|
+
get IFID () { return this.#_IFID; }
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {string} i - Replacement IFID
|
|
129
|
+
*/
|
|
130
|
+
set IFID (i) {
|
|
131
|
+
if (typeof i === 'string') {
|
|
132
|
+
this.#_IFID = i;
|
|
133
|
+
} else {
|
|
134
|
+
throw new Error('IFID must be a String!');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Name of start passage
|
|
140
|
+
*
|
|
141
|
+
* @public
|
|
142
|
+
* @readonly
|
|
143
|
+
* @memberof Story
|
|
144
|
+
* @returns {string} start
|
|
145
|
+
*/
|
|
146
|
+
get start () { return this.#_start; }
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {string} s - Replacement start
|
|
150
|
+
*/
|
|
151
|
+
set start (s) {
|
|
152
|
+
if (typeof s === 'string') {
|
|
153
|
+
this.#_start = s;
|
|
154
|
+
} else {
|
|
155
|
+
throw new Error('start (passage name) must be a String!');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Story format version of Story
|
|
161
|
+
*
|
|
162
|
+
* @public
|
|
163
|
+
* @readonly
|
|
164
|
+
* @memberof Story
|
|
165
|
+
* @returns {string} story format version
|
|
166
|
+
*/
|
|
167
|
+
get formatVersion () { return this.#_formatVersion; }
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {string} f - Replacement format version
|
|
171
|
+
*/
|
|
172
|
+
set formatVersion (f) {
|
|
173
|
+
if (typeof f === 'string') {
|
|
174
|
+
this.#_formatVersion = f;
|
|
175
|
+
} else {
|
|
176
|
+
throw new Error('Story format version must be a String!');
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Metadata of Story
|
|
182
|
+
*
|
|
183
|
+
* @public
|
|
184
|
+
* @readonly
|
|
185
|
+
* @memberof Story
|
|
186
|
+
* @returns {object} metadata of story
|
|
187
|
+
*/
|
|
188
|
+
get metadata () { return this.#_metadata; }
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* @param {object} o - Replacement metadata
|
|
192
|
+
*/
|
|
193
|
+
set metadata (o) {
|
|
194
|
+
if (typeof o === 'object') {
|
|
195
|
+
this.#_metadata = o;
|
|
196
|
+
} else {
|
|
197
|
+
throw new Error('Story metadata must be Object!');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Story format of Story
|
|
203
|
+
*
|
|
204
|
+
* @public
|
|
205
|
+
* @readonly
|
|
206
|
+
* @memberof Story
|
|
207
|
+
* @returns {string} format
|
|
208
|
+
*/
|
|
209
|
+
get format () { return this.#_format; }
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @param {string} f - Replacement format
|
|
213
|
+
*/
|
|
214
|
+
set format (f) {
|
|
215
|
+
if (typeof f === 'string') {
|
|
216
|
+
this.#_format = f;
|
|
217
|
+
} else {
|
|
218
|
+
throw new Error('Story format must be a String!');
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Program used to create Story
|
|
224
|
+
*
|
|
225
|
+
* @public
|
|
226
|
+
* @memberof Story
|
|
227
|
+
* @returns {string} Creator Program
|
|
228
|
+
*/
|
|
229
|
+
get creator () { return this.#_creator; }
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* @param {string} c - Creator Program of Story
|
|
233
|
+
*/
|
|
234
|
+
set creator (c) {
|
|
235
|
+
if (typeof c === 'string') {
|
|
236
|
+
this.#_creator = c;
|
|
237
|
+
} else {
|
|
238
|
+
throw new Error('Creator must be String');
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Version used to create Story
|
|
244
|
+
*
|
|
245
|
+
* @public
|
|
246
|
+
* @memberof Story
|
|
247
|
+
* @returns {string} Version
|
|
248
|
+
*/
|
|
249
|
+
get creatorVersion () { return this.#_creatorVersion; }
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @param {string} c - Version of creator program
|
|
253
|
+
*/
|
|
254
|
+
set creatorVersion (c) {
|
|
255
|
+
if (typeof c === 'string') {
|
|
256
|
+
this.#_creatorVersion = c;
|
|
257
|
+
} else {
|
|
258
|
+
throw new Error('Creator version must be a string!');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Zoom level
|
|
264
|
+
*
|
|
265
|
+
* @public
|
|
266
|
+
* @memberof Story
|
|
267
|
+
* @returns {number} Zoom level
|
|
268
|
+
*/
|
|
269
|
+
get zoom () { return this.#_zoom; }
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* @param {number} n - Replacement zoom level
|
|
273
|
+
*/
|
|
274
|
+
set zoom (n) {
|
|
275
|
+
if (typeof n === 'number') {
|
|
276
|
+
// Parse float with a fixed length and then force into Number
|
|
277
|
+
this.#_zoom = Number(Number.parseFloat(n).toFixed(2));
|
|
278
|
+
} else {
|
|
279
|
+
throw new Error('Zoom level must be a Number!');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Add a passage to the story
|
|
285
|
+
*
|
|
286
|
+
* @public
|
|
287
|
+
* @function addPassage
|
|
288
|
+
* @memberof Story
|
|
289
|
+
* @param {Passage} p - Passage to add to Story
|
|
290
|
+
*/
|
|
291
|
+
addPassage (p) {
|
|
292
|
+
// Check if passed argument is a Passage
|
|
293
|
+
if (p instanceof Passage) {
|
|
294
|
+
// Does this passage already exist in the collection?
|
|
295
|
+
if (this.getPassageByName(p.name) === null) {
|
|
296
|
+
// StoryData is the only passage with special parsing needs.
|
|
297
|
+
// All other passages are added to the internal passages array.
|
|
298
|
+
if (p.name === 'StoryData') {
|
|
299
|
+
// Try to parse JSON
|
|
300
|
+
try {
|
|
301
|
+
// Attempt to parse storyData JSON
|
|
302
|
+
const metadata = JSON.parse(p.text);
|
|
303
|
+
|
|
304
|
+
// IFID
|
|
305
|
+
if (Object.prototype.hasOwnProperty.call(metadata, 'ifid')) {
|
|
306
|
+
this.IFID = metadata.ifid;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// format
|
|
310
|
+
if (Object.prototype.hasOwnProperty.call(metadata, 'format')) {
|
|
311
|
+
this.format = metadata.format;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// formatVersion
|
|
315
|
+
if (Object.prototype.hasOwnProperty.call(metadata, 'formatVersion')) {
|
|
316
|
+
this.formatVersion = metadata.formatVersion;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// zoom
|
|
320
|
+
if (Object.prototype.hasOwnProperty.call(metadata, 'zoom')) {
|
|
321
|
+
this.zoom = metadata.zoom;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// start
|
|
325
|
+
if (Object.prototype.hasOwnProperty.call(metadata, 'start')) {
|
|
326
|
+
this.start = metadata.start;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// tag colors
|
|
330
|
+
if (Object.prototype.hasOwnProperty.call(metadata, 'tag-colors')) {
|
|
331
|
+
this.tagColors = metadata['tag-colors'];
|
|
332
|
+
}
|
|
333
|
+
} catch (event) {
|
|
334
|
+
// Ignore errors
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
// Look for Start
|
|
338
|
+
if (p.name === 'Start' && this.start === '') {
|
|
339
|
+
// Set Start as starting passage (unless overwritten by start property)
|
|
340
|
+
this.start = 'Start';
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Test for default value.
|
|
344
|
+
// (This might occur if using Story directory
|
|
345
|
+
// outside of using HTMLParser or TweeParser.)
|
|
346
|
+
if (p.pid === -1) {
|
|
347
|
+
// Set the internal counter.
|
|
348
|
+
p.pid = this.#_PIDCounter;
|
|
349
|
+
// Update the internal counter.
|
|
350
|
+
this.#_PIDCounter++;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Push the passage to the array
|
|
354
|
+
this.#_passages.push(p);
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
// Warn user
|
|
358
|
+
console.warn('Ignored passage with same name as existing one!');
|
|
359
|
+
}
|
|
360
|
+
} else {
|
|
361
|
+
// We can only add passages to array
|
|
362
|
+
throw new Error('Can only add Passages to the story!');
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Remove a passage from the story by name
|
|
368
|
+
*
|
|
369
|
+
* @public
|
|
370
|
+
* @function removePassage
|
|
371
|
+
* @memberof Story
|
|
372
|
+
* @param {string} name - Passage name to remove
|
|
373
|
+
*/
|
|
374
|
+
removePassage (name) {
|
|
375
|
+
this.#_passages = this.#_passages.filter(passage => passage.name !== name);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Find passages by tag
|
|
380
|
+
*
|
|
381
|
+
* @public
|
|
382
|
+
* @function getPassagesByTag
|
|
383
|
+
* @memberof Story
|
|
384
|
+
* @param {string} t - Passage name to search for
|
|
385
|
+
* @returns {Array} Return array of passages
|
|
386
|
+
*/
|
|
387
|
+
getPassagesByTag (t) {
|
|
388
|
+
// Look through passages
|
|
389
|
+
return this.#_passages.filter((passage) => {
|
|
390
|
+
// Look through each passage's tags
|
|
391
|
+
return passage.tags.some((tag) => t === tag);
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Find passage by name
|
|
397
|
+
*
|
|
398
|
+
* @public
|
|
399
|
+
* @function getPassageByName
|
|
400
|
+
* @memberof Story
|
|
401
|
+
* @param {string} name - Passage name to search for
|
|
402
|
+
* @returns {Passage | null} Return passage or null
|
|
403
|
+
*/
|
|
404
|
+
getPassageByName (name) {
|
|
405
|
+
// Look through passages
|
|
406
|
+
const results = this.#_passages.find((passage) => passage.name === name);
|
|
407
|
+
// Return entry or null, if not found
|
|
408
|
+
return results !== undefined ? results : null;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Find passage by PID
|
|
413
|
+
*
|
|
414
|
+
* @public
|
|
415
|
+
* @function getPassageByPID
|
|
416
|
+
* @memberof Story
|
|
417
|
+
* @param {number} pid - Passage PID to search for
|
|
418
|
+
* @returns {Passage | null} Return passage or null
|
|
419
|
+
*/
|
|
420
|
+
getPassageByPID (pid) {
|
|
421
|
+
// Look through passages
|
|
422
|
+
const results = this.#_passages.find((passage) => passage.pid === pid);
|
|
423
|
+
// Return passages or null
|
|
424
|
+
return results !== undefined ? results : null;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Size (number of passages).
|
|
429
|
+
* Does not include StoryAuthor, StoryTitle, UserScript, or UserStylesheet passages
|
|
430
|
+
*
|
|
431
|
+
* @public
|
|
432
|
+
* @function size
|
|
433
|
+
* @memberof Story
|
|
434
|
+
* @returns {number} Return number of passages
|
|
435
|
+
*/
|
|
436
|
+
size () {
|
|
437
|
+
return this.#_passages.length;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* forEach-style iterator of passages in Story
|
|
442
|
+
*
|
|
443
|
+
* @public
|
|
444
|
+
* @function forEach
|
|
445
|
+
* @memberof Story
|
|
446
|
+
* @param {Function} callback - Callback function
|
|
447
|
+
*/
|
|
448
|
+
forEach (callback) {
|
|
449
|
+
// Check if argument is a function
|
|
450
|
+
if (typeof callback !== 'function') {
|
|
451
|
+
// Throw error
|
|
452
|
+
throw new Error('Callback must be a function!');
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Use internal forEach
|
|
456
|
+
this.#_passages.forEach((element, index) => {
|
|
457
|
+
// Call callback function with element and index
|
|
458
|
+
callback(element, index);
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|