extwee 1.6.2 → 2.0.3
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 -24
- package/.github/workflows/nodejs.yml +24 -24
- package/.travis.yml +13 -13
- package/CODE_OF_CONDUCT.md +82 -0
- package/LICENSE +21 -21
- package/README.md +36 -205
- 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 +59 -45
- package/src/FileReader.js +33 -35
- package/src/HTMLParser.js +343 -206
- package/src/HTMLWriter.js +231 -172
- package/src/Passage.js +202 -24
- package/src/Story.js +490 -122
- package/src/StoryFormat.js +300 -28
- package/src/StoryFormatParser.js +142 -59
- package/src/TweeParser.js +161 -207
- package/src/TweeWriter.js +98 -96
- 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/{HTMLWriter/example7.twee → CLI/example6.twee} +16 -16
- 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.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 -46
- 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/{test10.html → creator.html} +8 -5
- package/test/HTMLWriter/example6.twee +16 -16
- package/test/HTMLWriter/{example.twee → missingStoryTitle.twee} +29 -29
- package/test/HTMLWriter/test11.html +123 -0
- package/test/HTMLWriter/test2.html +14 -11
- package/test/HTMLWriter/test3.html +7 -13
- package/test/HTMLWriter/test4.html +8 -5
- package/test/HTMLWriter/test6.html +7 -5
- package/test/HTMLWriter.test.js +289 -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 -29
- package/test/Story/test.twee +25 -25
- package/test/Story.test.js +369 -0
- package/test/StoryFormat.test.js +152 -0
- package/test/StoryFormatParser/example.js +3 -0
- package/test/StoryFormatParser/{test2.js → example2.js} +3 -3
- package/test/StoryFormatParser/format_doublename.js +1 -0
- package/test/StoryFormatParser/harlowe.js +2 -2
- 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 -2
- package/test/TweeParser/example.twee +32 -29
- package/test/TweeParser/missing.twee +19 -0
- package/test/{HTMLWriter/example5.twee → TweeParser/multipleScriptPassages.twee} +19 -13
- package/test/{HTMLWriter/example4.twee → TweeParser/multipleStyleTag.twee} +19 -13
- package/test/TweeParser/multipletags.twee +10 -2
- package/test/TweeParser/noTitle.twee +2 -0
- package/test/TweeParser/notes.twee +16 -32
- package/test/TweeParser/pasagemetadataerror.twee +2 -2
- package/test/{HTMLWriter/example2.twee → TweeParser/scriptPassage.twee} +16 -13
- package/test/TweeParser/singletag.twee +13 -2
- package/test/TweeParser/startMetadata.twee +14 -0
- package/test/TweeParser/storydataerror.twee +25 -25
- package/test/{HTMLWriter/example3.twee → TweeParser/stylePassage.twee} +16 -13
- package/test/TweeParser/test.twee +25 -25
- package/test/TweeParser.test.js +79 -0
- package/test/TweeWriter/test1.twee +14 -9
- package/test/TweeWriter/test3.twee +7 -10
- package/test/TweeWriter/test4.twee +14 -0
- package/test/TweeWriter/test5.twee +20 -0
- package/test/TweeWriter.test.js +85 -0
- package/main.js +0 -106
- package/src/DirectoryReader.js +0 -114
- package/src/DirectoryWatcher.js +0 -87
- package/test/DirectoryReader/css/test.css +0 -3
- package/test/DirectoryReader1/js/Site.js +0 -1
- package/test/DirectoryReader2/error.js +0 -1
- package/test/DirectoryReader2/example.css +0 -3
- package/test/DirectoryReader2/index.twee +0 -6
- package/test/DirectoryReader3/twee/index.twee +0 -6
- package/test/DirectoryWatcher/example.txt +0 -0
- package/test/DirectoryWatcher/test.txt +0 -0
- package/test/DirectoryWatcher/test1.txt +0 -0
- package/test/HTMLWriter/test5.html +0 -48
- package/test/HTMLWriter/test7.html +0 -48
- package/test/HTMLWriter/test8.html +0 -48
- package/test/HTMLWriter/test9.html +0 -48
- package/test/StoryFormatParser/test.js +0 -2
- package/test/TweeParser/test.twee3 +0 -11
- package/test/TweeWriter/metatest.twee +0 -12
- package/test/TweeWriter/test2.twee +0 -15
- package/test/test.js +0 -736
package/src/HTMLParser.js
CHANGED
|
@@ -1,206 +1,343 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @external HTML
|
|
3
|
-
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML|HTML}
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
*
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @external HTML
|
|
3
|
+
* @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML|HTML}
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { parse as HtmlParser } from 'node-html-parser';
|
|
7
|
+
import Story from './Story.js';
|
|
8
|
+
import Passage from './Passage.js';
|
|
9
|
+
/**
|
|
10
|
+
* @class HTMLParser
|
|
11
|
+
* @module HTMLParser
|
|
12
|
+
*/
|
|
13
|
+
export default class HTMLParser {
|
|
14
|
+
/**
|
|
15
|
+
* Parse HTML text into a JS DOM-like object
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
* @static
|
|
19
|
+
* @function parse
|
|
20
|
+
* @param {string} content - Content to parse
|
|
21
|
+
* @returns {Story} story
|
|
22
|
+
*/
|
|
23
|
+
static parse (content) {
|
|
24
|
+
let story = null;
|
|
25
|
+
let startNode = null;
|
|
26
|
+
|
|
27
|
+
// Send to node-html-parser
|
|
28
|
+
// Enable getting the content of 'script', 'style', and 'pre' elements
|
|
29
|
+
// Get back a DOM
|
|
30
|
+
const dom = new HtmlParser(
|
|
31
|
+
content,
|
|
32
|
+
{
|
|
33
|
+
lowerCaseTagName: false,
|
|
34
|
+
script: true,
|
|
35
|
+
style: true,
|
|
36
|
+
pre: true
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Pull out the tw-storydata element
|
|
40
|
+
const storyData = dom.querySelector('tw-storydata');
|
|
41
|
+
|
|
42
|
+
// Does the <tw-storydata> element exist?
|
|
43
|
+
if (storyData !== null) {
|
|
44
|
+
// Create a Story.
|
|
45
|
+
story = new Story();
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* name: (string) Required.
|
|
49
|
+
* The name of the story.
|
|
50
|
+
*/
|
|
51
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'name')) {
|
|
52
|
+
// Create StoryTitle passage based on name
|
|
53
|
+
story.addPassage(new Passage('StoryTitle', storyData.attributes.name));
|
|
54
|
+
} else {
|
|
55
|
+
// Name is a required filed. Warn user.
|
|
56
|
+
console.warn('Twine 2 HTML must have a name!');
|
|
57
|
+
// Set a default name
|
|
58
|
+
story.addPassage(new Passage('StoryTitle', 'Untitled'));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* ifid: (string) Required.
|
|
63
|
+
* An IFID is a sequence of between 8 and 63 characters,
|
|
64
|
+
* each of which shall be a digit, a capital letter or a
|
|
65
|
+
* hyphen that uniquely identify a story (see Treaty of Babel).
|
|
66
|
+
*/
|
|
67
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'ifid')) {
|
|
68
|
+
// Update story IFID
|
|
69
|
+
story.IFID = storyData.attributes.ifid;
|
|
70
|
+
} else {
|
|
71
|
+
// Name is a required filed. Warn user.
|
|
72
|
+
console.warn('Twine 2 HTML must have an IFID!');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* creator: (string) Optional.
|
|
77
|
+
* The name of program used to create the file.
|
|
78
|
+
*/
|
|
79
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'creator')) {
|
|
80
|
+
// Update story creator
|
|
81
|
+
story.creator = storyData.attributes.creator;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* creator-version: (string) Optional.
|
|
86
|
+
* The version of the program used to create the file.
|
|
87
|
+
*/
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'creator-version')) {
|
|
89
|
+
// Update story creator version
|
|
90
|
+
story.creatorVersion = storyData.attributes['creator-version'];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* format: (string) Optional.
|
|
95
|
+
* The story format used to create the story.
|
|
96
|
+
*/
|
|
97
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'format')) {
|
|
98
|
+
// Update story format
|
|
99
|
+
story.format = storyData.attributes.format;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* format-version: (string) Optional.
|
|
104
|
+
* The version of the story format used to create the story.
|
|
105
|
+
*/
|
|
106
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'format-version')) {
|
|
107
|
+
// Update story format version
|
|
108
|
+
story.formatVersion = storyData.attributes['format-version'];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* zoom: (string) Optional.
|
|
113
|
+
* The decimal level of zoom (i.e. 1.0 is 100% and 1.2 would be 120% zoom level).
|
|
114
|
+
*/
|
|
115
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'zoom')) {
|
|
116
|
+
// Update story zoom
|
|
117
|
+
story.zoom = Number(Number.parseFloat(storyData.attributes.zoom).toFixed(2));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* startnode: (string) Optional.
|
|
122
|
+
* The PID matching a <tw-passagedata> element whose content should be displayed first.
|
|
123
|
+
*/
|
|
124
|
+
if (Object.prototype.hasOwnProperty.call(storyData.attributes, 'startnode')) {
|
|
125
|
+
// Take string value and convert to Int
|
|
126
|
+
startNode = Number.parseInt(storyData.attributes.startnode, 10);
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
// If there is not a <tw-storydata> element, this is not a Twine 2 story!
|
|
130
|
+
throw new Error('Not a Twine 2-style file!');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Pull out the tw-passagedata elements
|
|
134
|
+
const storyPassages = dom.querySelectorAll('tw-passagedata');
|
|
135
|
+
|
|
136
|
+
// Move through the passages
|
|
137
|
+
for (const passage in storyPassages) {
|
|
138
|
+
// Get the passage attributes
|
|
139
|
+
const attr = storyPassages[passage].attributes;
|
|
140
|
+
// Get the passage text
|
|
141
|
+
const text = storyPassages[passage].rawText;
|
|
142
|
+
|
|
143
|
+
// Set a default position.
|
|
144
|
+
let position = null;
|
|
145
|
+
// Does position exist?
|
|
146
|
+
if (Object.prototype.hasOwnProperty.call(attr, 'position')) {
|
|
147
|
+
// Update position.
|
|
148
|
+
position = attr.position;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Set a default size.
|
|
152
|
+
let size = null;
|
|
153
|
+
// Does size exist?
|
|
154
|
+
if (Object.prototype.hasOwnProperty.call(attr, 'size')) {
|
|
155
|
+
// Update size.
|
|
156
|
+
size = attr.size;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* name: (string) Required.
|
|
161
|
+
* The name of the passage.
|
|
162
|
+
*
|
|
163
|
+
* https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-htmloutput-spec.md#passages
|
|
164
|
+
*/
|
|
165
|
+
// Create a default value
|
|
166
|
+
let name = null;
|
|
167
|
+
// Does name exist?
|
|
168
|
+
if (Object.prototype.hasOwnProperty.call(attr, 'name')) {
|
|
169
|
+
// Escape the name
|
|
170
|
+
name = HTMLParser.escapeMetacharacters(attr.name);
|
|
171
|
+
} else {
|
|
172
|
+
console.warn('Encountered passage without a name! Will not add.');
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Create empty tag array.
|
|
176
|
+
let tags = [];
|
|
177
|
+
// Does the tags attribute exist?
|
|
178
|
+
if (Object.prototype.hasOwnProperty.call(attr, 'tags')) {
|
|
179
|
+
// Escape any tags
|
|
180
|
+
// (Attributes can, themselves, be empty strings.)
|
|
181
|
+
if (attr.tags.length > 0 && attr.tags !== '""') {
|
|
182
|
+
// Escape the tags
|
|
183
|
+
tags = HTMLParser.escapeMetacharacters(attr.tags);
|
|
184
|
+
// Split by spaces into an array
|
|
185
|
+
tags = tags.split(' ');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Remove any empty strings.
|
|
189
|
+
tags = tags.filter(tag => tag !== '');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Create metadata for passage.
|
|
193
|
+
const metadata = {};
|
|
194
|
+
|
|
195
|
+
// Does position exist?
|
|
196
|
+
if (position !== null) {
|
|
197
|
+
// Add the property to metadata
|
|
198
|
+
metadata.position = position;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Does size exist?
|
|
202
|
+
if (size !== null) {
|
|
203
|
+
// Add the property to metadata
|
|
204
|
+
metadata.size = size;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* pid: (string) Required.
|
|
209
|
+
* The Passage ID (PID).
|
|
210
|
+
* (Note: This is subject to change during editing with Twine 2.)
|
|
211
|
+
*
|
|
212
|
+
* https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-htmloutput-spec.md#passages
|
|
213
|
+
*/
|
|
214
|
+
// Create a default PID
|
|
215
|
+
let pid = -1;
|
|
216
|
+
// Does pid exist?
|
|
217
|
+
if (Object.prototype.hasOwnProperty.call(attr, 'pid')) {
|
|
218
|
+
// Parse string into int
|
|
219
|
+
// Update PID
|
|
220
|
+
pid = Number.parseInt(attr.pid, 10);
|
|
221
|
+
} else {
|
|
222
|
+
console.warn('Passages are required to have PID. Will not add!');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// If passage is missing name and PID (required attributes),
|
|
226
|
+
// they are not added.
|
|
227
|
+
if (name !== null && pid !== -1) {
|
|
228
|
+
// Add a new Passage into an array
|
|
229
|
+
story.addPassage(
|
|
230
|
+
new Passage(
|
|
231
|
+
name,
|
|
232
|
+
text,
|
|
233
|
+
tags,
|
|
234
|
+
metadata,
|
|
235
|
+
pid
|
|
236
|
+
)
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Look for the style element
|
|
242
|
+
const styleElement = dom.querySelector('#twine-user-stylesheet');
|
|
243
|
+
|
|
244
|
+
// Does the style element exist?
|
|
245
|
+
if (styleElement !== null) {
|
|
246
|
+
// Check if there is any content.
|
|
247
|
+
if (styleElement.rawText.length > 0) {
|
|
248
|
+
// Update stylesheet passage
|
|
249
|
+
story.addPassage(new Passage(
|
|
250
|
+
'UserStylesheet',
|
|
251
|
+
styleElement.rawText,
|
|
252
|
+
['stylesheet'])
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Look for the script element
|
|
258
|
+
const scriptElement = dom.querySelector('#twine-user-script');
|
|
259
|
+
|
|
260
|
+
// Does the script element exist?
|
|
261
|
+
if (scriptElement !== null) {
|
|
262
|
+
// Check if there is any content.
|
|
263
|
+
if (scriptElement.rawText.length > 0) {
|
|
264
|
+
story.addPassage(new Passage(
|
|
265
|
+
'UserScript',
|
|
266
|
+
scriptElement.rawText,
|
|
267
|
+
['script'])
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Was there a startNode?
|
|
273
|
+
if (startNode !== null) {
|
|
274
|
+
// Try to find starting passage by PID.
|
|
275
|
+
const startingPassage = story.getPassageByPID(startNode);
|
|
276
|
+
// Does the passage exist (yet)?
|
|
277
|
+
if (startingPassage !== null) {
|
|
278
|
+
// If so, update property to name of passage.
|
|
279
|
+
story.start = startingPassage.name;
|
|
280
|
+
} else {
|
|
281
|
+
throw new Error('Invalid startnode detected in <tw-storydata>!');
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Look for all <tw-tag> elements
|
|
286
|
+
const twTags = dom.querySelectorAll('tw-tag');
|
|
287
|
+
|
|
288
|
+
// Parse through the entries
|
|
289
|
+
twTags.forEach((tags) => {
|
|
290
|
+
// Parse each tag element
|
|
291
|
+
const attributes = tags.attributes;
|
|
292
|
+
|
|
293
|
+
// Create default value for name
|
|
294
|
+
let name = '';
|
|
295
|
+
|
|
296
|
+
// Create default value for color
|
|
297
|
+
let color = '';
|
|
298
|
+
|
|
299
|
+
// Check for name
|
|
300
|
+
if (Object.prototype.hasOwnProperty.call(attributes, 'name')) {
|
|
301
|
+
name = attributes.name;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Check for color
|
|
305
|
+
if (Object.prototype.hasOwnProperty.call(attributes, 'color')) {
|
|
306
|
+
color = attributes.color;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// If both are not empty strings, use them.
|
|
310
|
+
if (name !== '' && color !== '') {
|
|
311
|
+
// Add name and color to the object
|
|
312
|
+
story.tagColors[name] = color;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Return the parsed story
|
|
317
|
+
return story;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Try to escape meta-characters
|
|
322
|
+
*
|
|
323
|
+
* @public
|
|
324
|
+
* @static
|
|
325
|
+
* @function escapeMetacharacters
|
|
326
|
+
* @param {string} result - Text to parse
|
|
327
|
+
* @returns {string} Escaped characters
|
|
328
|
+
*/
|
|
329
|
+
static escapeMetacharacters (result) {
|
|
330
|
+
// Replace any single backslash with two of them
|
|
331
|
+
result = result.replace(/\\/g, '\\');
|
|
332
|
+
// Double-escape escaped {
|
|
333
|
+
result = result.replace(/\\\{/g, '\\\\{');
|
|
334
|
+
// Double-escape escaped }
|
|
335
|
+
result = result.replace(/\\\}/g, '\\\\}');
|
|
336
|
+
// Double-escape escaped [
|
|
337
|
+
result = result.replace(/\\\[/g, '\\\\[');
|
|
338
|
+
// Double-escape escaped ]
|
|
339
|
+
result = result.replace(/\\\]/g, '\\\\]');
|
|
340
|
+
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
}
|