@rohal12/twee-ts 1.2.0 → 1.4.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/README.md +9 -0
- package/dist/bin/twee-ts.js +157 -41
- package/dist/bin/twee-ts.js.map +1 -1
- package/dist/{chunk-S4SWCQLW.js → chunk-76URFKGD.js} +158 -42
- package/dist/chunk-76URFKGD.js.map +1 -0
- package/dist/index.cjs +157 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +157 -41
- package/dist/index.js.map +1 -1
- package/dist/plugins/rollup.js +1 -1
- package/dist/plugins/vite.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-S4SWCQLW.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# twee-ts
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@rohal12/twee-ts)
|
|
4
|
+
[](https://github.com/rohal12/twee-ts/actions)
|
|
5
|
+
[](https://bundlephobia.com/package/@rohal12/twee-ts)
|
|
6
|
+
[]()
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://nodejs.org/)
|
|
9
|
+
[](https://github.com/rohal12/twee-ts/commits)
|
|
10
|
+
[](./UNLICENSE)
|
|
11
|
+
|
|
3
12
|
TypeScript reimplementation of [Tweego](https://www.motoslave.net/tweego/) — a command-line compiler for Twine/Twee interactive fiction projects.
|
|
4
13
|
|
|
5
14
|
Zero runtime dependencies. Node.js 22+.
|
package/dist/bin/twee-ts.js
CHANGED
|
@@ -64,6 +64,10 @@ function attrEscape(s) {
|
|
|
64
64
|
if (s.length === 0) return s;
|
|
65
65
|
return s.replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'");
|
|
66
66
|
}
|
|
67
|
+
function fullAttrEscape(s) {
|
|
68
|
+
if (s.length === 0) return s;
|
|
69
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
70
|
+
}
|
|
67
71
|
function htmlEscape(s) {
|
|
68
72
|
if (s.length === 0) return s;
|
|
69
73
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -86,6 +90,13 @@ function commentSanitize(s) {
|
|
|
86
90
|
function htmlCommentSanitize(s) {
|
|
87
91
|
return s.replace(/-->/g, "-- >");
|
|
88
92
|
}
|
|
93
|
+
function rot13(s) {
|
|
94
|
+
if (s.length === 0) return s;
|
|
95
|
+
return s.replace(/[A-Za-z]/g, (ch) => {
|
|
96
|
+
const base = ch <= "Z" ? 65 : 97;
|
|
97
|
+
return String.fromCharCode((ch.charCodeAt(0) - base + 13) % 26 + base);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
89
100
|
function tweeUnescape(s) {
|
|
90
101
|
if (s.length === 0) return s;
|
|
91
102
|
let result = "";
|
|
@@ -150,12 +161,14 @@ function hasMetadataSize(p) {
|
|
|
150
161
|
return p.metadata != null && p.metadata.size != null && p.metadata.size !== "";
|
|
151
162
|
}
|
|
152
163
|
function hasAnyMetadata(p) {
|
|
153
|
-
|
|
164
|
+
if (!p.metadata) return false;
|
|
165
|
+
return Object.values(p.metadata).some((v) => v != null && v !== "");
|
|
154
166
|
}
|
|
155
167
|
function marshalMetadata(meta) {
|
|
156
168
|
const obj = {};
|
|
157
|
-
|
|
158
|
-
|
|
169
|
+
for (const [key, value] of Object.entries(meta)) {
|
|
170
|
+
if (typeof value === "string" && value) obj[key] = value;
|
|
171
|
+
}
|
|
159
172
|
return JSON.stringify(obj);
|
|
160
173
|
}
|
|
161
174
|
function passageToTwee(p, outMode) {
|
|
@@ -198,9 +211,9 @@ function passageToPassagedata(p, pid) {
|
|
|
198
211
|
} else {
|
|
199
212
|
size = "100,100";
|
|
200
213
|
}
|
|
201
|
-
return `<tw-passagedata pid="${pid}" name=${quote(
|
|
214
|
+
return `<tw-passagedata pid="${pid}" name=${quote(fullAttrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(" ")))} position=${quote(attrEscape(position))} size=${quote(attrEscape(size))}>${htmlEscape(p.text)}</tw-passagedata>`;
|
|
202
215
|
}
|
|
203
|
-
function passageToTiddler(p, pid) {
|
|
216
|
+
function passageToTiddler(p, pid, obfuscateRot13 = false) {
|
|
204
217
|
let position;
|
|
205
218
|
if (hasMetadataPosition(p)) {
|
|
206
219
|
position = p.metadata?.position ?? "";
|
|
@@ -211,7 +224,10 @@ function passageToTiddler(p, pid) {
|
|
|
211
224
|
const yp = x === 0 ? y : y + 1;
|
|
212
225
|
position = `${xp * 140 - 130},${yp * 140 - 130}`;
|
|
213
226
|
}
|
|
214
|
-
|
|
227
|
+
const created = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T]/g, "").slice(0, 12);
|
|
228
|
+
const content = obfuscateRot13 && p.name !== "StorySettings" ? tiddlerEscape(rot13(p.text)) : tiddlerEscape(p.text);
|
|
229
|
+
const nameComment = obfuscateRot13 ? `<!-- ${commentSanitize(p.name)} -->` : "";
|
|
230
|
+
return `<div tiddler=${quote(attrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(" ")))} created=${quote(created)} modifier=${quote("twee")} twine-position=${quote(attrEscape(position))}>${nameComment}${content}</div>`;
|
|
215
231
|
}
|
|
216
232
|
function countWords(p) {
|
|
217
233
|
let text = p.text;
|
|
@@ -254,6 +270,7 @@ function createStory() {
|
|
|
254
270
|
formatVersion: "",
|
|
255
271
|
options: /* @__PURE__ */ new Map(),
|
|
256
272
|
start: "",
|
|
273
|
+
tags: "",
|
|
257
274
|
tagColors: /* @__PURE__ */ new Map(),
|
|
258
275
|
zoom: 1
|
|
259
276
|
}
|
|
@@ -300,6 +317,7 @@ function marshalStoryData(story) {
|
|
|
300
317
|
}
|
|
301
318
|
if (options.length > 0) data.options = options;
|
|
302
319
|
if (story.twine2.start) data.start = story.twine2.start;
|
|
320
|
+
if (story.twine2.tags) data.tags = story.twine2.tags;
|
|
303
321
|
if (story.twine2.tagColors.size > 0) {
|
|
304
322
|
data["tag-colors"] = Object.fromEntries(story.twine2.tagColors);
|
|
305
323
|
}
|
|
@@ -327,6 +345,7 @@ function unmarshalStoryData(story, json) {
|
|
|
327
345
|
}
|
|
328
346
|
}
|
|
329
347
|
if (typeof data.start === "string" && data.start) story.twine2.start = data.start;
|
|
348
|
+
if (typeof data.tags === "string") story.twine2.tags = data.tags;
|
|
330
349
|
if (typeof data["tag-colors"] === "object" && data["tag-colors"] !== null && !Array.isArray(data["tag-colors"])) {
|
|
331
350
|
for (const [tag, color] of Object.entries(data["tag-colors"])) {
|
|
332
351
|
if (typeof color === "string") story.twine2.tagColors.set(tag, color);
|
|
@@ -398,7 +417,7 @@ function storyAdd(story, p, diagnostics) {
|
|
|
398
417
|
processed = { ...p, text: marshalStoryData(story) };
|
|
399
418
|
} else {
|
|
400
419
|
diagnostics.push({
|
|
401
|
-
level: "
|
|
420
|
+
level: "warning",
|
|
402
421
|
message: `Cannot unmarshal "StoryData" compiler special passage; ${err}.`
|
|
403
422
|
});
|
|
404
423
|
}
|
|
@@ -621,17 +640,41 @@ function baseNameWithoutExt(filename) {
|
|
|
621
640
|
}
|
|
622
641
|
|
|
623
642
|
// src/formats.ts
|
|
643
|
+
function relaxedJSONParse(json) {
|
|
644
|
+
try {
|
|
645
|
+
return JSON.parse(json);
|
|
646
|
+
} catch {
|
|
647
|
+
}
|
|
648
|
+
let fixed = json;
|
|
649
|
+
fixed = fixed.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"');
|
|
650
|
+
fixed = fixed.replace(/(?<=^|[{,]\s*)([A-Za-z_$][A-Za-z0-9_$]*)\s*:/gm, '"$1":');
|
|
651
|
+
fixed = fixed.replace(/,\s*([}\]])/g, "$1");
|
|
652
|
+
return JSON.parse(fixed);
|
|
653
|
+
}
|
|
624
654
|
function parseFormatJSON(source, formatId) {
|
|
625
655
|
const first = source.indexOf("{");
|
|
626
656
|
const last = source.lastIndexOf("}");
|
|
627
657
|
if (first === -1 || last === -1) return null;
|
|
628
658
|
let chunk = source.slice(first, last + 1);
|
|
629
659
|
const parse = (json) => {
|
|
630
|
-
const raw =
|
|
660
|
+
const raw = relaxedJSONParse(json);
|
|
631
661
|
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return null;
|
|
632
662
|
const obj = raw;
|
|
633
|
-
if (typeof obj.
|
|
634
|
-
|
|
663
|
+
if (typeof obj.version !== "string" || typeof obj.source !== "string") return null;
|
|
664
|
+
if (!parseSemver(obj.version)) return null;
|
|
665
|
+
const name = typeof obj.name === "string" ? obj.name : "Untitled Story Format";
|
|
666
|
+
const result = {
|
|
667
|
+
name,
|
|
668
|
+
version: obj.version,
|
|
669
|
+
source: obj.source,
|
|
670
|
+
proofing: obj.proofing === true
|
|
671
|
+
};
|
|
672
|
+
if (typeof obj.author === "string") result.author = obj.author;
|
|
673
|
+
if (typeof obj.description === "string") result.description = obj.description;
|
|
674
|
+
if (typeof obj.image === "string") result.image = obj.image;
|
|
675
|
+
if (typeof obj.url === "string") result.url = obj.url;
|
|
676
|
+
if (typeof obj.license === "string") result.license = obj.license;
|
|
677
|
+
return result;
|
|
635
678
|
};
|
|
636
679
|
try {
|
|
637
680
|
return parse(chunk);
|
|
@@ -697,17 +740,55 @@ function discoverFormats(searchDirs) {
|
|
|
697
740
|
format.name = data.name;
|
|
698
741
|
format.version = data.version;
|
|
699
742
|
format.proofing = data.proofing ?? false;
|
|
743
|
+
if (data.author) format.author = data.author;
|
|
744
|
+
if (data.description) format.description = data.description;
|
|
745
|
+
if (data.image) format.image = data.image;
|
|
746
|
+
if (data.url) format.url = data.url;
|
|
747
|
+
if (data.license) format.license = data.license;
|
|
700
748
|
} catch {
|
|
701
749
|
continue;
|
|
702
750
|
}
|
|
751
|
+
} else {
|
|
752
|
+
format.name = entry;
|
|
703
753
|
}
|
|
704
754
|
formats.set(entry, format);
|
|
705
755
|
break;
|
|
706
756
|
}
|
|
707
757
|
}
|
|
708
758
|
}
|
|
759
|
+
pruneFormats(formats);
|
|
709
760
|
return formats;
|
|
710
761
|
}
|
|
762
|
+
function pruneFormats(formats) {
|
|
763
|
+
const bestByNameMajor = /* @__PURE__ */ new Map();
|
|
764
|
+
const seenNameVersion = /* @__PURE__ */ new Set();
|
|
765
|
+
for (const [id, f] of formats) {
|
|
766
|
+
if (!f.isTwine2 || !f.name || !f.version) continue;
|
|
767
|
+
const v = parseSemver(f.version);
|
|
768
|
+
if (!v) continue;
|
|
769
|
+
const nameVersionKey = `${f.name}@${f.version}`;
|
|
770
|
+
if (seenNameVersion.has(nameVersionKey)) {
|
|
771
|
+
formats.delete(id);
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
seenNameVersion.add(nameVersionKey);
|
|
775
|
+
const groupKey = `${f.name}@${v[0]}`;
|
|
776
|
+
const existing = bestByNameMajor.get(groupKey);
|
|
777
|
+
if (!existing || semverCompare(v, existing.version) > 0) {
|
|
778
|
+
bestByNameMajor.set(groupKey, { id, version: v });
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
for (const [id, f] of [...formats]) {
|
|
782
|
+
if (!f.isTwine2 || !f.name || !f.version) continue;
|
|
783
|
+
const v = parseSemver(f.version);
|
|
784
|
+
if (!v) continue;
|
|
785
|
+
const groupKey = `${f.name}@${v[0]}`;
|
|
786
|
+
const best = bestByNameMajor.get(groupKey);
|
|
787
|
+
if (best && best.id !== id) {
|
|
788
|
+
formats.delete(id);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
711
792
|
function getFormatSearchDirs(extraPaths = [], useTweegoPath = true) {
|
|
712
793
|
const subdirNames = ["storyformats", ".storyformats", "story-formats", "storyFormats", "targets"];
|
|
713
794
|
const basePaths = /* @__PURE__ */ new Set();
|
|
@@ -1144,8 +1225,11 @@ function parseTwee(source, options = {}) {
|
|
|
1144
1225
|
}
|
|
1145
1226
|
const parsed = raw;
|
|
1146
1227
|
const meta = {};
|
|
1147
|
-
|
|
1148
|
-
|
|
1228
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
1229
|
+
if (typeof value === "string") {
|
|
1230
|
+
meta[key] = value;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1149
1233
|
current.metadata = meta;
|
|
1150
1234
|
} catch (e) {
|
|
1151
1235
|
diagnostics.push({
|
|
@@ -1159,7 +1243,11 @@ function parseTwee(source, options = {}) {
|
|
|
1159
1243
|
}
|
|
1160
1244
|
case 6 /* Content */: {
|
|
1161
1245
|
if (!current) break;
|
|
1162
|
-
|
|
1246
|
+
if (trim) {
|
|
1247
|
+
current.text = item.val.trim();
|
|
1248
|
+
} else {
|
|
1249
|
+
current.text = item.val.replace(/\n\s*$/, "");
|
|
1250
|
+
}
|
|
1163
1251
|
break;
|
|
1164
1252
|
}
|
|
1165
1253
|
default: {
|
|
@@ -1387,8 +1475,12 @@ function getTwine2DataChunk(story, startName, diagnostics) {
|
|
|
1387
1475
|
}
|
|
1388
1476
|
}
|
|
1389
1477
|
parts.push(`<script role="script" id="twine-user-script" type="text/twine-javascript">${scriptContent}</script>`);
|
|
1478
|
+
const validTagColors = /* @__PURE__ */ new Set(["gray", "red", "orange", "yellow", "green", "blue", "purple"]);
|
|
1479
|
+
const hexColorPattern = /^#[0-9a-fA-F]{3,8}$/;
|
|
1390
1480
|
for (const [tag, color] of story.twine2.tagColors) {
|
|
1391
|
-
|
|
1481
|
+
if (validTagColors.has(color) || hexColorPattern.test(color)) {
|
|
1482
|
+
parts.push(`<tw-tag name="${attrEscape(tag)}" color="${attrEscape(color)}"></tw-tag>`);
|
|
1483
|
+
}
|
|
1392
1484
|
}
|
|
1393
1485
|
pid = 1;
|
|
1394
1486
|
for (const p of story.passages) {
|
|
@@ -1409,23 +1501,24 @@ function getTwine2DataChunk(story, startName, diagnostics) {
|
|
|
1409
1501
|
if (val) opts.push(opt);
|
|
1410
1502
|
}
|
|
1411
1503
|
const options = opts.join(" ");
|
|
1412
|
-
const zoom =
|
|
1413
|
-
const wrapper = `<!-- UUID://${htmlCommentSanitize(story.ifid)}// --><tw-storydata name="${attrEscape(story.name)}" startnode="${attrEscape(startID)}" creator="${attrEscape(CREATOR_NAME)}" creator-version="${attrEscape(VERSION)}" ifid="${attrEscape(story.ifid)}" zoom="${attrEscape(zoom)}" format="${attrEscape(story.twine2.format)}" format-version="${attrEscape(story.twine2.formatVersion)}" options="${attrEscape(options)}" hidden>`;
|
|
1504
|
+
const zoom = String(story.twine2.zoom);
|
|
1505
|
+
const wrapper = `<!-- UUID://${htmlCommentSanitize(story.ifid)}// --><tw-storydata name="${attrEscape(story.name)}" startnode="${attrEscape(startID)}" creator="${attrEscape(CREATOR_NAME)}" creator-version="${attrEscape(VERSION)}" ifid="${attrEscape(story.ifid)}" zoom="${attrEscape(zoom)}" format="${attrEscape(story.twine2.format)}" format-version="${attrEscape(story.twine2.formatVersion)}" options="${attrEscape(options)}" tags="${attrEscape(story.twine2.tags)}" hidden>`;
|
|
1414
1506
|
return wrapper + parts.join("") + "</tw-storydata>";
|
|
1415
1507
|
}
|
|
1416
1508
|
function ensureIFID(story, diagnostics) {
|
|
1417
1509
|
if (story.ifid !== "") return;
|
|
1418
1510
|
if (story.legacyIFID !== "") {
|
|
1511
|
+
story.ifid = story.legacyIFID;
|
|
1419
1512
|
diagnostics.push({
|
|
1420
1513
|
level: "warning",
|
|
1421
1514
|
message: 'Story IFID not found; reusing "ifid" entry from the "StorySettings" special passage.'
|
|
1422
1515
|
});
|
|
1423
|
-
story.ifid = story.legacyIFID;
|
|
1424
1516
|
} else {
|
|
1425
|
-
|
|
1517
|
+
const ifid = generateIFID();
|
|
1518
|
+
story.ifid = ifid;
|
|
1426
1519
|
diagnostics.push({
|
|
1427
|
-
level: "
|
|
1428
|
-
message: `Story IFID not found
|
|
1520
|
+
level: "error",
|
|
1521
|
+
message: `Story IFID not found. Add an IFID to your story: {"ifid":"${ifid}"}`
|
|
1429
1522
|
});
|
|
1430
1523
|
}
|
|
1431
1524
|
}
|
|
@@ -1436,7 +1529,7 @@ import { join as join3, dirname } from "path";
|
|
|
1436
1529
|
var CREATOR_NAME2 = "twee-ts";
|
|
1437
1530
|
function toTwine1Archive(story, _startName) {
|
|
1438
1531
|
const { data, count } = getTwine1PassageChunk(story);
|
|
1439
|
-
return `<div id="storeArea" data-size="${count}"
|
|
1532
|
+
return `<div id="storeArea" data-size="${count}">${data}</div>
|
|
1440
1533
|
`;
|
|
1441
1534
|
}
|
|
1442
1535
|
function toTwine1HTML(story, format, startName, _diagnostics) {
|
|
@@ -1481,12 +1574,13 @@ function toTwine1HTML(story, format, startName, _diagnostics) {
|
|
|
1481
1574
|
return template;
|
|
1482
1575
|
}
|
|
1483
1576
|
function getTwine1PassageChunk(story) {
|
|
1577
|
+
const obfuscateRot13 = story.twine1.settings.get("obfuscate") === "rot13";
|
|
1484
1578
|
let data = "";
|
|
1485
1579
|
let count = 0;
|
|
1486
1580
|
for (const p of story.passages) {
|
|
1487
1581
|
if (hasTag(p, "Twine.private")) continue;
|
|
1488
1582
|
count++;
|
|
1489
|
-
data += passageToTiddler(p, count);
|
|
1583
|
+
data += passageToTiddler(p, count, obfuscateRot13);
|
|
1490
1584
|
}
|
|
1491
1585
|
return { data, count };
|
|
1492
1586
|
}
|
|
@@ -1822,6 +1916,7 @@ function discoverCachedFormats() {
|
|
|
1822
1916
|
}
|
|
1823
1917
|
|
|
1824
1918
|
// src/compiler.ts
|
|
1919
|
+
var CREATOR_NAME3 = "Twee-ts";
|
|
1825
1920
|
var DEFAULT_FORMAT_ID = "sugarcube-2";
|
|
1826
1921
|
var DEFAULT_START_NAME = "Start";
|
|
1827
1922
|
var TweeTsError = class extends Error {
|
|
@@ -1968,28 +2063,49 @@ async function buildOutput(options) {
|
|
|
1968
2063
|
return { output, story, format, diagnostics, stats };
|
|
1969
2064
|
}
|
|
1970
2065
|
function storyToJSON(story) {
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
2066
|
+
const scripts = [];
|
|
2067
|
+
const stylesheets = [];
|
|
2068
|
+
const storyPassages = [];
|
|
2069
|
+
for (const p of story.passages) {
|
|
2070
|
+
if (p.name === "StoryTitle" || p.name === "StoryData") continue;
|
|
2071
|
+
if (hasTag(p, "Twine.private")) continue;
|
|
2072
|
+
if (hasTag(p, "script")) {
|
|
2073
|
+
scripts.push(p.text);
|
|
2074
|
+
} else if (hasTag(p, "stylesheet")) {
|
|
2075
|
+
stylesheets.push(p.text);
|
|
2076
|
+
} else {
|
|
2077
|
+
const entry = {
|
|
1976
2078
|
name: p.name,
|
|
1977
2079
|
tags: p.tags,
|
|
1978
|
-
text: p.text
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
2080
|
+
text: p.text
|
|
2081
|
+
};
|
|
2082
|
+
if (p.metadata) {
|
|
2083
|
+
const meta = {};
|
|
2084
|
+
for (const [key, value] of Object.entries(p.metadata)) {
|
|
2085
|
+
if (typeof value === "string") meta[key] = value;
|
|
2086
|
+
}
|
|
2087
|
+
if (Object.keys(meta).length > 0) {
|
|
2088
|
+
entry.metadata = meta;
|
|
2089
|
+
}
|
|
1988
2090
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2091
|
+
storyPassages.push(entry);
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
const obj = {
|
|
2095
|
+
name: story.name
|
|
2096
|
+
};
|
|
2097
|
+
if (story.ifid) obj.ifid = story.ifid;
|
|
2098
|
+
if (story.twine2.format) obj.format = story.twine2.format;
|
|
2099
|
+
if (story.twine2.formatVersion) obj["format-version"] = story.twine2.formatVersion;
|
|
2100
|
+
if (story.twine2.start) obj.start = story.twine2.start;
|
|
2101
|
+
if (story.twine2.tagColors.size > 0) obj["tag-colors"] = Object.fromEntries(story.twine2.tagColors);
|
|
2102
|
+
if (story.twine2.zoom !== 1) obj.zoom = story.twine2.zoom;
|
|
2103
|
+
obj.creator = CREATOR_NAME3;
|
|
2104
|
+
obj["creator-version"] = VERSION;
|
|
2105
|
+
obj.style = stylesheets.join("\n");
|
|
2106
|
+
obj.script = scripts.join("\n");
|
|
2107
|
+
obj.passages = storyPassages;
|
|
2108
|
+
return JSON.stringify(obj, null, 2);
|
|
1993
2109
|
}
|
|
1994
2110
|
|
|
1995
2111
|
// src/config.ts
|