extwee 2.3.14 → 2.3.16
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/CHANGELOG.md +8 -0
- package/build/extwee.core.min.js +1 -1
- package/build/extwee.twine1html.min.js +1 -1
- package/build/extwee.twine2archive.min.js +1 -1
- package/build/extwee.tws.min.js +1 -1
- package/logs/arrays.html +79 -0
- package/logs/arrays.twee +64 -0
- package/logs/example.html +47 -0
- package/logs/fixing.js +23 -0
- package/logs/format-fixed.js +8 -0
- package/logs/format.js +8 -0
- package/logs/test-entities.cjs +40 -0
- package/package.json +26 -25
- package/src/CLI/ProcessConfig/loadStoryFormat.js +8 -3
- package/src/CLI/ProcessConfig/readDirectories.js +1 -3
- package/src/Config/parser.js +6 -6
- package/src/Config/reader.js +2 -2
- package/src/JSON/parse.js +8 -4
- package/src/Passage.js +44 -41
- package/src/Story.js +42 -35
- package/src/StoryFormat/parse.js +2 -2
- package/src/StoryFormat.js +11 -4
- package/src/TWS/parse.js +2 -2
- package/src/Twee/parse.js +3 -3
- package/src/Twine1HTML/compile.js +9 -9
- package/src/Twine1HTML/parse-web.js +1 -1
- package/src/Twine1HTML/parse.js +3 -3
- package/src/Twine2ArchiveHTML/parse-web.js +3 -1
- package/src/Twine2HTML/parse-web.js +1 -1
- package/src/Twine2HTML/parse.js +3 -3
- package/src/Web/getGlobalObject.js +17 -0
- package/src/Web/web-core.js +2 -7
- package/src/Web/web-twine1html.js +2 -7
- package/src/Web/web-twine2archive.js +2 -7
- package/src/Web/web-tws.js +2 -7
- package/types/src/Passage.d.ts +44 -41
- package/types/src/Story.d.ts +32 -24
- package/types/src/StoryFormat.d.ts +11 -4
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const jsdom = require('jsdom');
|
|
2
|
+
const { JSDOM } = jsdom;
|
|
3
|
+
|
|
4
|
+
// Test in a DOM context
|
|
5
|
+
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
|
|
6
|
+
const doc = dom.window.document;
|
|
7
|
+
|
|
8
|
+
// Create elements with both encodings
|
|
9
|
+
const div1 = doc.createElement('div');
|
|
10
|
+
div1.setAttribute('data-test', 'test'value');
|
|
11
|
+
const div2 = doc.createElement('div');
|
|
12
|
+
div2.setAttribute('data-test', 'test'value');
|
|
13
|
+
|
|
14
|
+
console.log('div1 getAttribute:', div1.getAttribute('data-test'));
|
|
15
|
+
console.log('div2 getAttribute:', div2.getAttribute('data-test'));
|
|
16
|
+
console.log('Are they equal?', div1.getAttribute('data-test') === div2.getAttribute('data-test'));
|
|
17
|
+
|
|
18
|
+
// Test with innerHTML
|
|
19
|
+
div1.innerHTML = 'Text with 'quote'';
|
|
20
|
+
div2.innerHTML = 'Text with 'quote'';
|
|
21
|
+
console.log('div1 textContent:', div1.textContent);
|
|
22
|
+
console.log('div2 textContent:', div2.textContent);
|
|
23
|
+
console.log('Text content equal?', div1.textContent === div2.textContent);
|
|
24
|
+
|
|
25
|
+
// Test parsing HTML with both
|
|
26
|
+
const html1 = '<tw-passagedata name="Test" data-value="It's">Content</tw-passagedata>';
|
|
27
|
+
const html2 = '<tw-passagedata name="Test" data-value="It's">Content</tw-passagedata>';
|
|
28
|
+
|
|
29
|
+
const container1 = doc.createElement('div');
|
|
30
|
+
const container2 = doc.createElement('div');
|
|
31
|
+
container1.innerHTML = html1;
|
|
32
|
+
container2.innerHTML = html2;
|
|
33
|
+
|
|
34
|
+
const passage1 = container1.querySelector('tw-passagedata');
|
|
35
|
+
const passage2 = container2.querySelector('tw-passagedata');
|
|
36
|
+
|
|
37
|
+
console.log('\nParsing tw-passagedata:');
|
|
38
|
+
console.log('passage1 data-value:', passage1.getAttribute('data-value'));
|
|
39
|
+
console.log('passage2 data-value:', passage2.getAttribute('data-value'));
|
|
40
|
+
console.log('Attributes equal?', passage1.getAttribute('data-value') === passage2.getAttribute('data-value'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extwee",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.16",
|
|
4
4
|
"description": "A story compiler tool using Twine-compatible formats",
|
|
5
5
|
"author": "Dan Cox",
|
|
6
6
|
"main": "index.js",
|
|
@@ -17,11 +17,11 @@
|
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand",
|
|
20
|
-
"lint": "eslint ./src/**/*.js --fix",
|
|
21
|
-
"lint:test": "eslint ./test/**/*.test.js --fix",
|
|
20
|
+
"lint": "eslint \"./src/**/*.js\" --fix",
|
|
21
|
+
"lint:test": "eslint \"./test/**/*.test.js\" --fix",
|
|
22
22
|
"build:web": "webpack",
|
|
23
23
|
"analyze:web": "webpack-bundle-analyzer build/extwee.web.min.js",
|
|
24
|
-
"gen-types": "npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types",
|
|
24
|
+
"gen-types": "npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types --skipLibCheck",
|
|
25
25
|
"copy:build": "cp build/*.js docs/build",
|
|
26
26
|
"all": "npm run lint && npm run lint:test && npm run test && npm run build:web && npm run gen-types && npm run copy:build"
|
|
27
27
|
},
|
|
@@ -36,34 +36,35 @@
|
|
|
36
36
|
"commander": "^14.0.3",
|
|
37
37
|
"graphemer": "^1.4.0",
|
|
38
38
|
"html-entities": "^2.6.0",
|
|
39
|
-
"node-html-parser": "^7.0
|
|
39
|
+
"node-html-parser": "^7.1.0",
|
|
40
40
|
"pickleparser": "^0.2.1",
|
|
41
|
-
"semver": "^7.7.
|
|
42
|
-
"shelljs": "^0.10.0"
|
|
41
|
+
"semver": "^7.7.4"
|
|
43
42
|
},
|
|
44
43
|
"devDependencies": {
|
|
45
44
|
"@babel/cli": "^7.28.6",
|
|
46
45
|
"@babel/core": "^7.29.0",
|
|
47
|
-
"@babel/preset-env": "^7.29.
|
|
48
|
-
"@eslint/js": "^
|
|
49
|
-
"@inquirer/prompts": "^8.2
|
|
50
|
-
"@types/node": "^25.
|
|
46
|
+
"@babel/preset-env": "^7.29.3",
|
|
47
|
+
"@eslint/js": "^10.0.1",
|
|
48
|
+
"@inquirer/prompts": "^8.4.2",
|
|
49
|
+
"@types/node": "^25.6.0",
|
|
51
50
|
"@types/semver": "^7.7.1",
|
|
52
|
-
"babel-loader": "^10.
|
|
53
|
-
"clean-jsdoc-theme": "^4.3.
|
|
54
|
-
"core-js": "^3.
|
|
55
|
-
"eslint": "^
|
|
56
|
-
"eslint-plugin-jest": "^29.
|
|
57
|
-
"eslint-plugin-jsdoc": "^62.
|
|
58
|
-
"globals": "^17.
|
|
59
|
-
"jest": "^30.
|
|
60
|
-
"jest-environment-jsdom": "^30.
|
|
51
|
+
"babel-loader": "^10.1.1",
|
|
52
|
+
"clean-jsdoc-theme": "^4.3.2",
|
|
53
|
+
"core-js": "^3.49.0",
|
|
54
|
+
"eslint": "^10.3.0",
|
|
55
|
+
"eslint-plugin-jest": "^29.15.2",
|
|
56
|
+
"eslint-plugin-jsdoc": "^62.9.0",
|
|
57
|
+
"globals": "^17.6.0",
|
|
58
|
+
"jest": "^30.3.0",
|
|
59
|
+
"jest-environment-jsdom": "^30.3.0",
|
|
61
60
|
"regenerator-runtime": "^0.14.1",
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"webpack
|
|
61
|
+
"semgrep": "^0.0.1",
|
|
62
|
+
"shelljs": "^0.10.0",
|
|
63
|
+
"typescript": "^6.0.3",
|
|
64
|
+
"typescript-eslint": "^8.59.1",
|
|
65
|
+
"webpack": "^5.106.2",
|
|
66
|
+
"webpack-bundle-analyzer": "^5.3.0",
|
|
67
|
+
"webpack-cli": "^7.0.2"
|
|
67
68
|
},
|
|
68
69
|
"repository": {
|
|
69
70
|
"type": "git",
|
|
@@ -23,6 +23,14 @@ import { readFileSync } from "node:fs";
|
|
|
23
23
|
* // Output: The contents of the format.js file.
|
|
24
24
|
*/
|
|
25
25
|
export function loadStoryFormat(storyFormatName, storyFormatVersion) {
|
|
26
|
+
// Validate path components to prevent path traversal.
|
|
27
|
+
if (/[/\\]|\.\./.test(storyFormatName)) {
|
|
28
|
+
throw new Error('Error: story format name contains invalid characters.');
|
|
29
|
+
}
|
|
30
|
+
if (/[/\\]|\.\./.test(storyFormatVersion)) {
|
|
31
|
+
throw new Error('Error: story format version contains invalid characters.');
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
// If the story-formats directory does not exist, throw error.
|
|
27
35
|
if (isDirectory('story-formats') === false) {
|
|
28
36
|
throw new Error(`Error: story-formats directory does not exist. Consider running 'npx sfa-get' to download the latest story formats.`);
|
|
@@ -49,8 +57,6 @@ export function loadStoryFormat(storyFormatName, storyFormatVersion) {
|
|
|
49
57
|
// The directories are expected to be version directories.
|
|
50
58
|
let directories = readDirectories(`story-formats/${storyFormatName}`);
|
|
51
59
|
|
|
52
|
-
console.log("!!! directories", directories);
|
|
53
|
-
|
|
54
60
|
// Check if there are any version directories.
|
|
55
61
|
if (directories.length === 0) {
|
|
56
62
|
// If there are no version directories, throw error.
|
|
@@ -63,7 +69,6 @@ export function loadStoryFormat(storyFormatName, storyFormatVersion) {
|
|
|
63
69
|
});
|
|
64
70
|
|
|
65
71
|
// Get the latest version directory.
|
|
66
|
-
// The latest version is the last directory in the sorted list.
|
|
67
72
|
const latestVersion = directories[0];
|
|
68
73
|
|
|
69
74
|
// Set the filepath to the latest version directory.
|
|
@@ -11,9 +11,6 @@ import { isDirectory } from '../isDirectory.js';
|
|
|
11
11
|
*/
|
|
12
12
|
export function readDirectories(directory) {
|
|
13
13
|
|
|
14
|
-
// Create default response.
|
|
15
|
-
let results = [];
|
|
16
|
-
|
|
17
14
|
// Check if the directory exists.
|
|
18
15
|
const isDir = isDirectory(directory);
|
|
19
16
|
// If the directory does not exist, return an empty array
|
|
@@ -23,6 +20,7 @@ export function readDirectories(directory) {
|
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
// Read the directory and return the list of files.
|
|
23
|
+
let results;
|
|
26
24
|
try {
|
|
27
25
|
results = readdirSync(directory);
|
|
28
26
|
} catch (error) {
|
package/src/Config/parser.js
CHANGED
|
@@ -20,34 +20,34 @@ export function parser(obj) {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
// Does the object contain 'StoryFormat'?
|
|
23
|
-
if (Object.hasOwnProperty.call(obj, 'story-format')) {
|
|
23
|
+
if (Object.prototype.hasOwnProperty.call(obj, 'story-format')) {
|
|
24
24
|
results.StoryFormat = obj['story-format'];
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// Does the object contain 'StoryFormatVersion'?
|
|
28
|
-
if (Object.hasOwnProperty.call(obj, 'story-format-version')) {
|
|
28
|
+
if (Object.prototype.hasOwnProperty.call(obj, 'story-format-version')) {
|
|
29
29
|
results.StoryFormatVersion = obj['story-format-version'];
|
|
30
30
|
} else {
|
|
31
31
|
results.StoryFormatVersion = "latest";
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
// Does the object contain 'mode'?
|
|
35
|
-
if (Object.hasOwnProperty.call(obj, 'mode')) {
|
|
35
|
+
if (Object.prototype.hasOwnProperty.call(obj, 'mode')) {
|
|
36
36
|
results.Mode = obj['mode'];
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Does the object contain 'input'?
|
|
40
|
-
if (Object.hasOwnProperty.call(obj, 'input')) {
|
|
40
|
+
if (Object.prototype.hasOwnProperty.call(obj, 'input')) {
|
|
41
41
|
results.Input = obj['input'];
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
// Does the object contain 'output'?
|
|
45
|
-
if (Object.hasOwnProperty.call(obj, 'output')) {
|
|
45
|
+
if (Object.prototype.hasOwnProperty.call(obj, 'output')) {
|
|
46
46
|
results.Output = obj['output'];
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Does the object contain 'twine1-project'?
|
|
50
|
-
if (Object.hasOwnProperty.call(obj, 'twine1-project')) {
|
|
50
|
+
if (Object.prototype.hasOwnProperty.call(obj, 'twine1-project')) {
|
|
51
51
|
results.Twine1Project = obj['twine1-project'];
|
|
52
52
|
} else {
|
|
53
53
|
results.Twine1Project = false;
|
package/src/Config/reader.js
CHANGED
|
@@ -20,13 +20,13 @@ export function reader(path) {
|
|
|
20
20
|
const contents = readFileSync(path, 'utf8');
|
|
21
21
|
|
|
22
22
|
// Parsed contents.
|
|
23
|
-
let parsedContents
|
|
23
|
+
let parsedContents;
|
|
24
24
|
|
|
25
25
|
// Try to parse the contents into JSON object.
|
|
26
26
|
try {
|
|
27
27
|
parsedContents = JSON.parse(contents);
|
|
28
28
|
} catch (error) {
|
|
29
|
-
throw new Error(`Error: File ${path} is not a valid JSON file. ${error.message}
|
|
29
|
+
throw new Error(`Error: File ${path} is not a valid JSON file. ${error.message}`, { cause: error });
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Return the parsed contents.
|
package/src/JSON/parse.js
CHANGED
|
@@ -52,7 +52,7 @@ import Passage from '../Passage.js';
|
|
|
52
52
|
*/
|
|
53
53
|
function parse (jsonString) {
|
|
54
54
|
// Create future object.
|
|
55
|
-
let result
|
|
55
|
+
let result;
|
|
56
56
|
|
|
57
57
|
// Create Story.
|
|
58
58
|
const s = new Story();
|
|
@@ -61,7 +61,7 @@ function parse (jsonString) {
|
|
|
61
61
|
try {
|
|
62
62
|
result = JSON.parse(jsonString);
|
|
63
63
|
} catch (error) {
|
|
64
|
-
throw new Error(`Error: JSON could not be parsed! ${error.message}
|
|
64
|
+
throw new Error(`Error: JSON could not be parsed! ${error.message}`, { cause: error });
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// Name
|
|
@@ -142,8 +142,12 @@ function parse (jsonString) {
|
|
|
142
142
|
|
|
143
143
|
// Does s have tags?
|
|
144
144
|
if (Object.prototype.hasOwnProperty.call(p, 'tags')) {
|
|
145
|
-
//
|
|
146
|
-
|
|
145
|
+
// Tags must be an array; coerce space-separated strings for compatibility.
|
|
146
|
+
if (Array.isArray(p.tags)) {
|
|
147
|
+
newP.tags = p.tags;
|
|
148
|
+
} else if (typeof p.tags === 'string') {
|
|
149
|
+
newP.tags = p.tags.length > 0 ? p.tags.split(' ').filter(t => t !== '') : [];
|
|
150
|
+
}
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
// Does s have metadata?
|
package/src/Passage.js
CHANGED
|
@@ -2,42 +2,42 @@ import { encode } from 'html-entities';
|
|
|
2
2
|
import { escapeTweeMetacharacters } from './Twee/parse.js';
|
|
3
3
|
|
|
4
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
|
-
|
|
5
|
+
* Passage class.
|
|
6
|
+
* @class
|
|
7
|
+
* @classdesc Represents a passage in a Twine story.
|
|
8
|
+
* @property {string} name - Name of the passage.
|
|
9
|
+
* @property {Array} tags - Tags for the passage.
|
|
10
|
+
* @property {object} metadata - Metadata for the passage.
|
|
11
|
+
* @property {string} text - Text content of the passage.
|
|
12
|
+
* @function toTwee - Return a Twee representation.
|
|
13
|
+
* @function toJSON - Return JSON representation.
|
|
14
|
+
* @function toTwine2HTML - Return Twine 2 HTML representation.
|
|
15
|
+
* @function toTwine1HTML - Return Twine 1 HTML representation.
|
|
16
|
+
* @example
|
|
17
|
+
* const p = new Passage('Start', 'This is the start of the story.');
|
|
18
|
+
* console.log(p.toTwee());
|
|
19
|
+
* // :: Start
|
|
20
|
+
* // This is the start of the story.
|
|
21
|
+
* //
|
|
22
|
+
* console.log(p.toJSON());
|
|
23
|
+
* // {"name":"Start","tags":[],"metadata":{},"text":"This is the start of the story."}
|
|
24
|
+
* console.log(p.toTwine2HTML());
|
|
25
|
+
* // <tw-passagedata pid="1" name="Start" tags="" >This is the start of the story.</tw-passagedata>
|
|
26
|
+
* console.log(p.toTwine1HTML());
|
|
27
|
+
* // <div tiddler="Start" tags="" modifier="extwee" twine-position="10,10">This is the start of the story.</div>
|
|
28
|
+
* @example
|
|
29
|
+
* const p = new Passage('Start', 'This is the start of the story.', ['start', 'beginning'], {position: '10,10', size: '100,100'});
|
|
30
|
+
* console.log(p.toTwee());
|
|
31
|
+
* // :: Start [start beginning] {"position":"10,10","size":"100,100"}
|
|
32
|
+
* // This is the start of the story.
|
|
33
|
+
* //
|
|
34
|
+
* console.log(p.toJSON());
|
|
35
|
+
* // {"name":"Start","tags":["start","beginning"],"metadata":{"position":"10,10","size":"100,100"},"text":"This is the start of the story."}
|
|
36
|
+
* console.log(p.toTwine2HTML());
|
|
37
|
+
* // <tw-passagedata pid="1" name="Start" tags="start beginning" position="10,10" size="100,100">This is the start of the story.</tw-passagedata>
|
|
38
|
+
* console.log(p.toTwine1HTML());
|
|
39
|
+
* // <div tiddler="Start" tags="start beginning" modifier="extwee" twine-position="10,10">This is the start of the story.</div>
|
|
40
|
+
*/
|
|
41
41
|
export default class Passage {
|
|
42
42
|
/**
|
|
43
43
|
* Name of the Passage
|
|
@@ -95,6 +95,7 @@ export default class Passage {
|
|
|
95
95
|
get name () { return this.#_name; }
|
|
96
96
|
|
|
97
97
|
/**
|
|
98
|
+
* Set passage name.
|
|
98
99
|
* @param {string} s - Name to replace
|
|
99
100
|
* @throws {Error} Name must be a String!
|
|
100
101
|
*/
|
|
@@ -113,6 +114,7 @@ export default class Passage {
|
|
|
113
114
|
get tags () { return this.#_tags; }
|
|
114
115
|
|
|
115
116
|
/**
|
|
117
|
+
* Set passage tags.
|
|
116
118
|
* @param {Array} t - Replacement array
|
|
117
119
|
* @throws {Error} Tags must be an array!
|
|
118
120
|
*/
|
|
@@ -133,6 +135,7 @@ export default class Passage {
|
|
|
133
135
|
get metadata () { return this.#_metadata; }
|
|
134
136
|
|
|
135
137
|
/**
|
|
138
|
+
* Set passage metadata.
|
|
136
139
|
* @param {object} m - Replacement object
|
|
137
140
|
* @throws {Error} Metadata must be an object literal!
|
|
138
141
|
*/
|
|
@@ -152,6 +155,7 @@ export default class Passage {
|
|
|
152
155
|
get text () { return this.#_text; }
|
|
153
156
|
|
|
154
157
|
/**
|
|
158
|
+
* Set passage text.
|
|
155
159
|
* @param {string} t - Replacement text
|
|
156
160
|
* @throws {Error} Text should be a String!
|
|
157
161
|
*/
|
|
@@ -168,8 +172,7 @@ export default class Passage {
|
|
|
168
172
|
* Return a Twee representation.
|
|
169
173
|
*
|
|
170
174
|
* See: https://github.com/iftechfoundation/twine-specs/blob/master/twee-3-specification.md
|
|
171
|
-
*
|
|
172
|
-
* @method toTwee
|
|
175
|
+
* @function toTwee
|
|
173
176
|
* @returns {string} String form of passage.
|
|
174
177
|
*/
|
|
175
178
|
toTwee () {
|
|
@@ -216,7 +219,7 @@ export default class Passage {
|
|
|
216
219
|
|
|
217
220
|
/**
|
|
218
221
|
* Return JSON representation.
|
|
219
|
-
* @
|
|
222
|
+
* @function toJSON
|
|
220
223
|
* @returns {string} JSON string.
|
|
221
224
|
*/
|
|
222
225
|
toJSON () {
|
|
@@ -235,7 +238,7 @@ export default class Passage {
|
|
|
235
238
|
/**
|
|
236
239
|
* Return Twine 2 HTML representation.
|
|
237
240
|
* (Default Passage ID is 1.)
|
|
238
|
-
* @
|
|
241
|
+
* @function toTwine2HTML
|
|
239
242
|
* @param {number} pid - Passage ID (PID) to record in HTML.
|
|
240
243
|
* @returns {string} Twine 2 HTML string.
|
|
241
244
|
*/
|
|
@@ -292,7 +295,7 @@ export default class Passage {
|
|
|
292
295
|
|
|
293
296
|
/**
|
|
294
297
|
* Return Twine 1 HTML representation.
|
|
295
|
-
* @
|
|
298
|
+
* @function toTwine1HTML
|
|
296
299
|
* @returns {string} Twine 1 HTML string.
|
|
297
300
|
*/
|
|
298
301
|
toTwine1HTML () {
|