extwee 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/codeql-analysis.yml +51 -0
- package/README.md +9 -3
- package/build/extwee +0 -0
- package/build/extwee.web.min.js +1 -1
- package/docs/_sidebar.md +1 -0
- package/docs/examples/dynamicPassages.md +1 -1
- package/docs/examples/twsToTwee.md +1 -1
- package/docs/objects/story.md +1 -2
- package/index.js +3 -1
- package/package.json +22 -19
- package/src/IFID/generate.js +20 -0
- package/src/JSON/parse.js +44 -1
- package/src/Passage.js +61 -31
- package/src/Story.js +272 -110
- package/src/StoryFormat/parse.js +190 -80
- package/src/StoryFormat.js +78 -88
- package/src/TWS/parse.js +3 -3
- package/src/Twee/parse.js +3 -4
- package/src/Twine1HTML/compile.js +3 -1
- package/src/Twine1HTML/parse.js +3 -4
- package/src/Twine2ArchiveHTML/compile.js +9 -1
- package/src/Twine2ArchiveHTML/parse.js +33 -3
- package/src/Twine2HTML/compile.js +32 -7
- package/src/Twine2HTML/parse.js +51 -55
- package/test/IFID/IFID.Generate.test.js +10 -0
- package/test/JSON/JSON.Parse.test.js +24 -24
- package/test/Passage.test.js +69 -0
- package/test/Story.test.js +298 -49
- package/test/StoryFormat/StoryFormat.Parse.test.js +442 -55
- package/test/StoryFormat.test.js +9 -2
- package/test/TWS/Parse.test.js +1 -1
- package/test/Twine1HTML/Twine1HTML.Compile.test.js +1 -1
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Compile.test.js +1 -1
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +20 -4
- package/test/Twine2HTML/Twine2HTML.Compile.test.js +36 -121
- package/test/Twine2HTML/Twine2HTML.Parse.test.js +63 -43
- package/test/Twine2HTML/Twine2HTMLCompiler/format.js +9 -0
- package/test/Twine2HTML/Twine2HTMLParser/missingZoom.html +1 -1
- package/test/Twine2HTML/Twine2HTMLParser/unescaping.html +33 -0
- package/tsconfig.json +21 -0
- package/types/index.d.ts +14 -0
- package/types/src/JSON/parse.d.ts +8 -0
- package/types/src/Passage.d.ts +72 -0
- package/types/src/Story.d.ts +161 -0
- package/types/src/StoryFormat/parse.d.ts +7 -0
- package/types/src/StoryFormat.d.ts +97 -0
- package/types/src/TWS/parse.d.ts +10 -0
- package/types/src/Twee/parse.d.ts +10 -0
- package/types/src/Twine1HTML/compile.d.ts +17 -0
- package/types/src/Twine1HTML/parse.d.ts +10 -0
- package/types/src/Twine2ArchiveHTML/compile.d.ts +6 -0
- package/types/src/Twine2ArchiveHTML/parse.d.ts +6 -0
- package/types/src/Twine2HTML/compile.d.ts +9 -0
- package/types/src/Twine2HTML/parse.d.ts +17 -0
- package/types/src/extwee.d.ts +2 -0
- package/web-index.js +3 -1
- package/test/StoryFormat/StoryFormatParser/example.js +0 -3
- package/test/StoryFormat/StoryFormatParser/example2.js +0 -3
- package/test/StoryFormat/StoryFormatParser/format.js +0 -1
- package/test/StoryFormat/StoryFormatParser/format_doublename.js +0 -1
- package/test/StoryFormat/StoryFormatParser/harlowe.js +0 -3
- package/test/StoryFormat/StoryFormatParser/missingAuthor.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingDescription.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingImage.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingLicense.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingName.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingProofing.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingSource.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingURL.js +0 -1
- package/test/StoryFormat/StoryFormatParser/missingVersion.js +0 -1
- package/test/StoryFormat/StoryFormatParser/versionWrong.js +0 -1
- package/test/Twine2HTML/Twine2HTMLParser/missingName.html +0 -33
- package/test/Twine2HTML/Twine2HTMLParser/missingPID.html +0 -15
- package/test/Twine2HTML/Twine2HTMLParser/missingPassageName.html +0 -15
package/docs/_sidebar.md
CHANGED
|
@@ -16,7 +16,7 @@ import { writeFileSync } from 'node:fs';
|
|
|
16
16
|
const example = new Story( 'Example' );
|
|
17
17
|
|
|
18
18
|
// Generate 20 passages and add them to the story.
|
|
19
|
-
for(let i = 0; i < 20; i
|
|
19
|
+
for(let i = 0; i < 20; i++) {
|
|
20
20
|
example.addPassage( new Passage( `Passage ${i}`, 'Some Text') );
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# TWS To Twee
|
|
2
2
|
|
|
3
|
-
Converting from TWS to Twee 3 is similar to many other conversion processes
|
|
3
|
+
Converting from TWS to Twee 3 is similar to many other conversion processes with one small difference. TWS conversion needs to be begin from the [**Buffer** data type in JavaScript](https://nodejs.org/api/buffer.html).
|
|
4
4
|
|
|
5
5
|
1. Read the binary file.
|
|
6
6
|
2. Convert the binary files into a Buffer.
|
package/docs/objects/story.md
CHANGED
|
@@ -12,7 +12,7 @@ Depending on the incoming format or creation method, many possible properties ca
|
|
|
12
12
|
- format ( string ) Name of the story format for Twine 2 HTML.
|
|
13
13
|
- formatVersion ( string ) Semantic version of the named story format for Twine 2 HTML or Twee 3.
|
|
14
14
|
- zoom ( float ) Zoom level for Twine 2 HTML or Twee 3.
|
|
15
|
-
- passages ( array(Passage) )
|
|
15
|
+
- passages ( array(Passage) ) Collection of internal passages.
|
|
16
16
|
- creator ( string ) Name of story creation tool. (Defaults to "Extwee").
|
|
17
17
|
- creatorVersion ( string ) Semantic version of named creation tool.
|
|
18
18
|
- metadata ( object ) Key-value pairs of metadata values.
|
|
@@ -41,7 +41,6 @@ As collections of passages, each **Story** has multiple methods for accessing an
|
|
|
41
41
|
- `getPassagesByTags(string)`: Returns an array of any passages containing a particular tag value.
|
|
42
42
|
- `getPassageByName(string)`: Returns either `null`` or the named passage.
|
|
43
43
|
- `size()`: Returns the number of passages in the collection.
|
|
44
|
-
- `forEachPassage(callback)`: Allows for iterating over the passage collection.
|
|
45
44
|
|
|
46
45
|
## Passage Creation Example
|
|
47
46
|
|
package/index.js
CHANGED
|
@@ -8,7 +8,8 @@ import { parse as parseTWS } from './src/TWS/parse.js';
|
|
|
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 { generate as generateIFID } from './src/IFID/generate.js';
|
|
12
|
+
import { Story } from './src/Story.js';
|
|
12
13
|
import Passage from './src/Passage.js';
|
|
13
14
|
import StoryFormat from './src/StoryFormat.js';
|
|
14
15
|
|
|
@@ -23,6 +24,7 @@ export {
|
|
|
23
24
|
compileTwine1HTML,
|
|
24
25
|
compileTwine2HTML,
|
|
25
26
|
compileTwine2ArchiveHTML,
|
|
27
|
+
generateIFID,
|
|
26
28
|
Story,
|
|
27
29
|
Passage,
|
|
28
30
|
StoryFormat
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extwee",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "A story compiler tool using Twine-compatible formats",
|
|
5
5
|
"author": "Dan Cox",
|
|
6
6
|
"main": "index.js",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"extwee": "src/extwee.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "jest --
|
|
11
|
+
"test": "jest --runInBand --coverage --colors",
|
|
12
12
|
"lint": "eslint ./src/**/*.js --fix",
|
|
13
13
|
"lint:test": "eslint ./test/**/*.test.js --fix",
|
|
14
14
|
"build:web": "webpack",
|
|
@@ -23,43 +23,46 @@
|
|
|
23
23
|
],
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"commander": "^
|
|
27
|
-
"
|
|
26
|
+
"commander": "^12.0.0",
|
|
27
|
+
"html-entities": "^2.5.2",
|
|
28
|
+
"node-html-parser": "^6.1.12",
|
|
28
29
|
"pickleparser": "^0.2.1",
|
|
29
|
-
"semver": "^7.
|
|
30
|
+
"semver": "^7.6.0",
|
|
30
31
|
"uuid": "^9.0.1"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@babel/cli": "^7.23.4",
|
|
34
|
-
"@babel/core": "^7.
|
|
35
|
-
"@babel/eslint-parser": "^7.23.
|
|
35
|
+
"@babel/core": "^7.24.0",
|
|
36
|
+
"@babel/eslint-parser": "^7.23.10",
|
|
36
37
|
"@babel/eslint-plugin": "^7.23.5",
|
|
37
|
-
"@babel/preset-env": "^7.
|
|
38
|
+
"@babel/preset-env": "^7.24.0",
|
|
39
|
+
"@types/uuid": "^9.0.7",
|
|
38
40
|
"babel-loader": "^9.1.3",
|
|
39
41
|
"clean-jsdoc-theme": "^4.2.17",
|
|
40
|
-
"core-js": "^3.
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"eslint": "^8.56.0",
|
|
42
|
+
"core-js": "^3.36.0",
|
|
43
|
+
"esbuild": "^0.20.1",
|
|
44
|
+
"eslint": "^8.57.0",
|
|
44
45
|
"eslint-config-standard": "^17.1.0",
|
|
45
46
|
"eslint-plugin-import": "^2.29.1",
|
|
46
|
-
"eslint-plugin-jest": "^27.
|
|
47
|
-
"eslint-plugin-jsdoc": "^
|
|
48
|
-
"eslint-plugin-node": "^11.
|
|
47
|
+
"eslint-plugin-jest": "^27.9.0",
|
|
48
|
+
"eslint-plugin-jsdoc": "^48.2.0",
|
|
49
|
+
"eslint-plugin-node": "^11.1.0",
|
|
49
50
|
"eslint-plugin-promise": "^6.1.1",
|
|
50
51
|
"jest": "^29.7.0",
|
|
51
52
|
"pkg": "^5.8.1",
|
|
52
53
|
"regenerator-runtime": "^0.14.1",
|
|
53
|
-
"shelljs": "^0.8.
|
|
54
|
-
"
|
|
54
|
+
"shelljs": "^0.8.5",
|
|
55
|
+
"typescript": "^5.4.2",
|
|
56
|
+
"webpack": "^5.90.3",
|
|
55
57
|
"webpack-cli": "^5.1.4"
|
|
56
58
|
},
|
|
57
59
|
"repository": {
|
|
58
60
|
"type": "git",
|
|
59
|
-
"url": "https://github.com/videlais/extwee"
|
|
61
|
+
"url": "git+https://github.com/videlais/extwee.git"
|
|
60
62
|
},
|
|
61
63
|
"bugs": {
|
|
62
64
|
"url": "https://github.com/videlais/extwee/issues"
|
|
63
65
|
},
|
|
64
|
-
"type": "module"
|
|
66
|
+
"type": "module",
|
|
67
|
+
"types": "./types/index.d.ts"
|
|
65
68
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { v4 } from 'uuid';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generates an Interactive Fiction Identification (IFID) based the Treaty of Babel.
|
|
5
|
+
*
|
|
6
|
+
* For Twine works, the IFID is a UUID (v4) in uppercase.
|
|
7
|
+
* @see Treaty of Babel ({@link https://babel.ifarchive.org/babel_rev11.html#the-ifid-for-an-html-story-file})
|
|
8
|
+
* @function generate
|
|
9
|
+
* @description Generates a new IFID.
|
|
10
|
+
* @returns {string} IFID
|
|
11
|
+
* @example
|
|
12
|
+
* const ifid = generate();
|
|
13
|
+
* console.log(ifid);
|
|
14
|
+
* // => 'A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6'
|
|
15
|
+
*/
|
|
16
|
+
function generate () {
|
|
17
|
+
return v4().toUpperCase();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { generate };
|
package/src/JSON/parse.js
CHANGED
|
@@ -1,11 +1,54 @@
|
|
|
1
|
-
import Story from '../Story.js';
|
|
1
|
+
import { Story } from '../Story.js';
|
|
2
2
|
import Passage from '../Passage.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Parse JSON representation into Story.
|
|
6
|
+
* @see {@link https://github.com/iftechfoundation/twine-specs/blob/master/twine-2-jsonoutput-doc.md Twine 2 JSON Specification}
|
|
6
7
|
* @function parse
|
|
7
8
|
* @param {string} jsonString - JSON string to convert to Story.
|
|
9
|
+
* @throws {Error} - Invalid JSON!
|
|
8
10
|
* @returns {Story} Story object.
|
|
11
|
+
* @example
|
|
12
|
+
* const jsonString = `{
|
|
13
|
+
* "name": "My Story",
|
|
14
|
+
* "start": "First Passage",
|
|
15
|
+
* "ifid": "A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6",
|
|
16
|
+
* "format": "SugarCube",
|
|
17
|
+
* "formatVersion": "2.31.0",
|
|
18
|
+
* "creator": "Twine",
|
|
19
|
+
* "creatorVersion": "2.3.9",
|
|
20
|
+
* "zoom": 1,
|
|
21
|
+
* "passages": [
|
|
22
|
+
* {
|
|
23
|
+
* "name": "First Passage",
|
|
24
|
+
* "tags": "",
|
|
25
|
+
* "metadata": "",
|
|
26
|
+
* "text": "This is the first passage."
|
|
27
|
+
* },
|
|
28
|
+
* ]
|
|
29
|
+
* }`;
|
|
30
|
+
* const story = parse(jsonString);
|
|
31
|
+
* console.log(story);
|
|
32
|
+
* // => Story {
|
|
33
|
+
* // name: 'My Story',
|
|
34
|
+
* // start: 'First Passage',
|
|
35
|
+
* // IFID: 'A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6',
|
|
36
|
+
* // format: 'SugarCube',
|
|
37
|
+
* // formatVersion: '2.31.0',
|
|
38
|
+
* // creator: 'Twine',
|
|
39
|
+
* // creatorVersion: '2.3.9',
|
|
40
|
+
* // zoom: 1,
|
|
41
|
+
* // tagColors: {},
|
|
42
|
+
* // metadata: {},
|
|
43
|
+
* // passages: [
|
|
44
|
+
* // Passage {
|
|
45
|
+
* // name: 'First Passage',
|
|
46
|
+
* // tags: '',
|
|
47
|
+
* // metadata: '',
|
|
48
|
+
* // text: 'This is the first passage.'
|
|
49
|
+
* // }
|
|
50
|
+
* // ]
|
|
51
|
+
* // }
|
|
9
52
|
*/
|
|
10
53
|
function parse (jsonString) {
|
|
11
54
|
// Create future object.
|
package/src/Passage.js
CHANGED
|
@@ -1,28 +1,68 @@
|
|
|
1
|
+
import { encode } from 'html-entities';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
+
* Passage class.
|
|
5
|
+
* @class
|
|
6
|
+
* @classdesc Represents a passage in a Twine story.
|
|
7
|
+
* @property {string} name - Name of the passage.
|
|
8
|
+
* @property {Array} tags - Tags for the passage.
|
|
9
|
+
* @property {object} metadata - Metadata for the passage.
|
|
10
|
+
* @property {string} text - Text content of the passage.
|
|
11
|
+
* @method {string} toTwee - Return a Twee representation.
|
|
12
|
+
* @method {string} toJSON - Return JSON representation.
|
|
13
|
+
* @method {string} toTwine2HTML - Return Twine 2 HTML representation.
|
|
14
|
+
* @method {string} toTwine1HTML - Return Twine 1 HTML representation.
|
|
15
|
+
* @example
|
|
16
|
+
* const p = new Passage('Start', 'This is the start of the story.');
|
|
17
|
+
* console.log(p.toTwee());
|
|
18
|
+
* // :: Start
|
|
19
|
+
* // This is the start of the story.
|
|
20
|
+
* //
|
|
21
|
+
* console.log(p.toJSON());
|
|
22
|
+
* // {"name":"Start","tags":[],"metadata":{},"text":"This is the start of the story."}
|
|
23
|
+
* console.log(p.toTwine2HTML());
|
|
24
|
+
* // <tw-passagedata pid="1" name="Start" tags="" >This is the start of the story.</tw-passagedata>
|
|
25
|
+
* console.log(p.toTwine1HTML());
|
|
26
|
+
* // <div tiddler="Start" tags="" modifier="extwee" twine-position="10,10">This is the start of the story.</div>
|
|
27
|
+
* @example
|
|
28
|
+
* const p = new Passage('Start', 'This is the start of the story.', ['start', 'beginning'], {position: '10,10', size: '100,100'});
|
|
29
|
+
* console.log(p.toTwee());
|
|
30
|
+
* // :: Start [start beginning] {"position":"10,10","size":"100,100"}
|
|
31
|
+
* // This is the start of the story.
|
|
32
|
+
* //
|
|
33
|
+
* console.log(p.toJSON());
|
|
34
|
+
* // {"name":"Start","tags":["start","beginning"],"metadata":{"position":"10,10","size":"100,100"},"text":"This is the start of the story."}
|
|
35
|
+
* console.log(p.toTwine2HTML());
|
|
36
|
+
* // <tw-passagedata pid="1" name="Start" tags="start beginning" position="10,10" size="100,100">This is the start of the story.</tw-passagedata>
|
|
37
|
+
* console.log(p.toTwine1HTML());
|
|
38
|
+
* // <div tiddler="Start" tags="start beginning" modifier="extwee" twine-position="10,10">This is the start of the story.</div>
|
|
39
|
+
*/
|
|
4
40
|
export default class Passage {
|
|
5
41
|
/**
|
|
6
42
|
* Name of the Passage
|
|
7
43
|
* @private
|
|
44
|
+
* @type {string}
|
|
8
45
|
*/
|
|
9
|
-
#_name =
|
|
46
|
+
#_name = '';
|
|
10
47
|
|
|
11
48
|
/**
|
|
12
49
|
* Internal array of tags
|
|
13
50
|
* @private
|
|
51
|
+
* @type {Array}
|
|
14
52
|
*/
|
|
15
53
|
#_tags = [];
|
|
16
54
|
|
|
17
55
|
/**
|
|
18
56
|
* Internal metadata of passage
|
|
19
57
|
* @private
|
|
58
|
+
* @type {object}
|
|
20
59
|
*/
|
|
21
60
|
#_metadata = {};
|
|
22
61
|
|
|
23
62
|
/**
|
|
24
63
|
* Internal text of the passage
|
|
25
64
|
* @private
|
|
65
|
+
* @type {string}
|
|
26
66
|
*/
|
|
27
67
|
#_text = '';
|
|
28
68
|
|
|
@@ -55,6 +95,7 @@ export default class Passage {
|
|
|
55
95
|
|
|
56
96
|
/**
|
|
57
97
|
* @param {string} s - Name to replace
|
|
98
|
+
* @throws {Error} Name must be a String!
|
|
58
99
|
*/
|
|
59
100
|
set name (s) {
|
|
60
101
|
if (typeof s === 'string') {
|
|
@@ -72,10 +113,12 @@ export default class Passage {
|
|
|
72
113
|
|
|
73
114
|
/**
|
|
74
115
|
* @param {Array} t - Replacement array
|
|
116
|
+
* @throws {Error} Tags must be an array!
|
|
75
117
|
*/
|
|
76
118
|
set tags (t) {
|
|
77
119
|
// Test if tags is an array
|
|
78
120
|
if (Array.isArray(t)) {
|
|
121
|
+
// Set the tags.
|
|
79
122
|
this.#_tags = t;
|
|
80
123
|
} else {
|
|
81
124
|
throw new Error('Tags must be an array!');
|
|
@@ -90,6 +133,7 @@ export default class Passage {
|
|
|
90
133
|
|
|
91
134
|
/**
|
|
92
135
|
* @param {object} m - Replacement object
|
|
136
|
+
* @throws {Error} Metadata must be an object literal!
|
|
93
137
|
*/
|
|
94
138
|
set metadata (m) {
|
|
95
139
|
// Test if metadata was an object
|
|
@@ -108,6 +152,7 @@ export default class Passage {
|
|
|
108
152
|
|
|
109
153
|
/**
|
|
110
154
|
* @param {string} t - Replacement text
|
|
155
|
+
* @throws {Error} Text should be a String!
|
|
111
156
|
*/
|
|
112
157
|
set text (t) {
|
|
113
158
|
// Test if text is a String
|
|
@@ -120,6 +165,10 @@ export default class Passage {
|
|
|
120
165
|
|
|
121
166
|
/**
|
|
122
167
|
* Return a Twee representation.
|
|
168
|
+
*
|
|
169
|
+
* See: https://github.com/iftechfoundation/twine-specs/blob/master/twee-3-specification.md
|
|
170
|
+
*
|
|
171
|
+
* @method toTwee
|
|
123
172
|
* @returns {string} String form of passage.
|
|
124
173
|
*/
|
|
125
174
|
toTwee () {
|
|
@@ -150,6 +199,7 @@ export default class Passage {
|
|
|
150
199
|
|
|
151
200
|
/**
|
|
152
201
|
* Return JSON representation.
|
|
202
|
+
* @method toJSON
|
|
153
203
|
* @returns {string} JSON string.
|
|
154
204
|
*/
|
|
155
205
|
toJSON () {
|
|
@@ -168,6 +218,7 @@ export default class Passage {
|
|
|
168
218
|
/**
|
|
169
219
|
* Return Twine 2 HTML representation.
|
|
170
220
|
* (Default Passage ID is 1.)
|
|
221
|
+
* @method toTwine2HTML
|
|
171
222
|
* @param {number} pid - Passage ID (PID) to record in HTML.
|
|
172
223
|
* @returns {string} Twine 2 HTML string.
|
|
173
224
|
*/
|
|
@@ -185,13 +236,13 @@ export default class Passage {
|
|
|
185
236
|
* name: (string) Required.
|
|
186
237
|
* The name of the passage.
|
|
187
238
|
*/
|
|
188
|
-
passageData += ` name="${this.name}"`;
|
|
239
|
+
passageData += ` name="${ encode( this.name ) }"`;
|
|
189
240
|
|
|
190
241
|
/**
|
|
191
242
|
* tags: (string) Optional.
|
|
192
243
|
* Any tags for the passage separated by spaces.
|
|
193
244
|
*/
|
|
194
|
-
passageData += ` tags="${this.#_tags.join(' ')}" `;
|
|
245
|
+
passageData += ` tags="${ encode( this.#_tags.join(' ') ) }" `;
|
|
195
246
|
|
|
196
247
|
/**
|
|
197
248
|
* position: (string) Optional.
|
|
@@ -211,30 +262,8 @@ export default class Passage {
|
|
|
211
262
|
passageData += `size="${this.#_metadata.size}" `;
|
|
212
263
|
}
|
|
213
264
|
|
|
214
|
-
/**
|
|
215
|
-
* Escape passage Twine 2 passage text.
|
|
216
|
-
* @param {string} text - Text to escape.
|
|
217
|
-
* @returns {string} Escaped text.
|
|
218
|
-
*/
|
|
219
|
-
const escape = function (text) {
|
|
220
|
-
const rules = [
|
|
221
|
-
['&', '&'],
|
|
222
|
-
['<', '<'],
|
|
223
|
-
['>', '>'],
|
|
224
|
-
['"', '"'],
|
|
225
|
-
["'", '''],
|
|
226
|
-
['`', '`']
|
|
227
|
-
];
|
|
228
|
-
|
|
229
|
-
rules.forEach(([rule, template]) => {
|
|
230
|
-
text = text.replaceAll(rule, template);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
return text;
|
|
234
|
-
};
|
|
235
|
-
|
|
236
265
|
// Add the text and close the element.
|
|
237
|
-
passageData += `>${
|
|
266
|
+
passageData += `>${ encode( this.text ) }</tw-passagedata>\n`;
|
|
238
267
|
|
|
239
268
|
// Return the Twine 2 HTML element.
|
|
240
269
|
return passageData;
|
|
@@ -242,6 +271,7 @@ export default class Passage {
|
|
|
242
271
|
|
|
243
272
|
/**
|
|
244
273
|
* Return Twine 1 HTML representation.
|
|
274
|
+
* @method toTwine1HTML
|
|
245
275
|
* @returns {string} Twine 1 HTML string.
|
|
246
276
|
*/
|
|
247
277
|
toTwine1HTML () {
|
|
@@ -258,13 +288,13 @@ export default class Passage {
|
|
|
258
288
|
* tiddler: (string) Required.
|
|
259
289
|
* The name of the passage.
|
|
260
290
|
*/
|
|
261
|
-
passageData += ` tiddler="${this.name}"`;
|
|
291
|
+
passageData += ` tiddler="${ encode( this.name ) }"`;
|
|
262
292
|
|
|
263
293
|
/**
|
|
264
294
|
* tags: (string) Required.
|
|
265
295
|
* Any tags for the passage separated by spaces.
|
|
266
296
|
*/
|
|
267
|
-
passageData += ` tags="${this.#_tags.join(' ')}" `;
|
|
297
|
+
passageData += ` tags="${ encode( this.#_tags.join(' ') ) }" `;
|
|
268
298
|
|
|
269
299
|
/**
|
|
270
300
|
* modifier: (string) Optional.
|
|
@@ -290,7 +320,7 @@ export default class Passage {
|
|
|
290
320
|
* text: (string) Required.
|
|
291
321
|
* Text content of the passage.
|
|
292
322
|
*/
|
|
293
|
-
passageData += `>${this.#_text}</div>`;
|
|
323
|
+
passageData += `>${ encode( this.#_text ) }</div>`;
|
|
294
324
|
|
|
295
325
|
// Return the HTML representation.
|
|
296
326
|
return passageData;
|