@rohal12/twee-ts 1.4.0 → 1.5.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.
@@ -194,7 +194,7 @@ function passageToTwee(p, outMode) {
194
194
  output += "\n\n";
195
195
  return output;
196
196
  }
197
- function passageToPassagedata(p, pid) {
197
+ function passageToPassagedata(p, pid, options) {
198
198
  let position;
199
199
  let size;
200
200
  if (hasMetadataPosition(p)) {
@@ -211,7 +211,11 @@ function passageToPassagedata(p, pid) {
211
211
  } else {
212
212
  size = "100,100";
213
213
  }
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>`;
214
+ let attrs = `<tw-passagedata pid="${pid}" name=${quote(fullAttrEscape(p.name))} tags=${quote(attrEscape(p.tags.join(" ")))} position=${quote(attrEscape(position))} size=${quote(attrEscape(size))}`;
215
+ if (options?.sourceInfo && p.source) {
216
+ attrs += ` data-source-file=${quote(attrEscape(p.source.file))} data-source-line="${p.source.line}"`;
217
+ }
218
+ return `${attrs}>${htmlEscape(p.text)}</tw-passagedata>`;
215
219
  }
216
220
  function passageToTiddler(p, pid, obfuscateRot13 = false) {
217
221
  let position;
@@ -1175,7 +1179,7 @@ function parseTwee(source, options = {}) {
1175
1179
  if (pCount > 1 && current) {
1176
1180
  passages.push(current);
1177
1181
  }
1178
- current = { name: "", tags: [], text: "" };
1182
+ current = { name: "", tags: [], text: "", source: { file: filename, line: item.line } };
1179
1183
  break;
1180
1184
  case 3 /* Name */: {
1181
1185
  if (!current) break;
@@ -1422,20 +1426,20 @@ var VERSION = "1.2.0";
1422
1426
 
1423
1427
  // src/output-twine2.ts
1424
1428
  var CREATOR_NAME = "Twee-ts";
1425
- function toTwine2Archive(story, startName, diagnostics) {
1426
- return getTwine2DataChunk(story, startName, diagnostics) + "\n";
1429
+ function toTwine2Archive(story, startName, diagnostics, options) {
1430
+ return getTwine2DataChunk(story, startName, diagnostics, options) + "\n";
1427
1431
  }
1428
- function toTwine2HTML(story, format, startName, diagnostics) {
1432
+ function toTwine2HTML(story, format, startName, diagnostics, options) {
1429
1433
  let template = readFormatSource(format);
1430
1434
  if (template.includes("{{STORY_NAME}}")) {
1431
1435
  template = template.replaceAll("{{STORY_NAME}}", htmlEscape(story.name));
1432
1436
  }
1433
1437
  if (template.includes("{{STORY_DATA}}")) {
1434
- template = template.replace("{{STORY_DATA}}", getTwine2DataChunk(story, startName, diagnostics));
1438
+ template = template.replace("{{STORY_DATA}}", getTwine2DataChunk(story, startName, diagnostics, options));
1435
1439
  }
1436
1440
  return template;
1437
1441
  }
1438
- function getTwine2DataChunk(story, startName, diagnostics) {
1442
+ function getTwine2DataChunk(story, startName, diagnostics, options) {
1439
1443
  ensureIFID(story, diagnostics);
1440
1444
  const parts = [];
1441
1445
  let startID = "";
@@ -1490,7 +1494,7 @@ function getTwine2DataChunk(story, startName, diagnostics) {
1490
1494
  if (p.name === "StorySettings" && story.twine1.settings.size === 0) {
1491
1495
  continue;
1492
1496
  }
1493
- parts.push(passageToPassagedata(p, pid));
1497
+ parts.push(passageToPassagedata(p, pid, options));
1494
1498
  if (startName === p.name) {
1495
1499
  startID = String(pid);
1496
1500
  }
@@ -1500,9 +1504,9 @@ function getTwine2DataChunk(story, startName, diagnostics) {
1500
1504
  for (const [opt, val] of story.twine2.options) {
1501
1505
  if (val) opts.push(opt);
1502
1506
  }
1503
- const options = opts.join(" ");
1507
+ const optionsStr = opts.join(" ");
1504
1508
  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>`;
1509
+ 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(optionsStr)}" tags="${attrEscape(story.twine2.tags)}" hidden>`;
1506
1510
  return wrapper + parts.join("") + "</tw-storydata>";
1507
1511
  }
1508
1512
  function ensureIFID(story, diagnostics) {
@@ -1957,6 +1961,7 @@ async function buildOutput(options) {
1957
1961
  const twee2Compat = options.twee2Compat ?? false;
1958
1962
  const testMode = options.testMode ?? false;
1959
1963
  const noRemote = options.noRemote ?? false;
1964
+ const sourceInfo = options.sourceInfo ?? false;
1960
1965
  clearIndexCache();
1961
1966
  const filePaths = [];
1962
1967
  const inlineSources = [];
@@ -2018,7 +2023,7 @@ async function buildOutput(options) {
2018
2023
  output = toTwee(story, outputMode);
2019
2024
  break;
2020
2025
  case "twine2-archive":
2021
- output = toTwine2Archive(story, startName, diagnostics);
2026
+ output = toTwine2Archive(story, startName, diagnostics, { sourceInfo });
2022
2027
  break;
2023
2028
  case "twine1-archive":
2024
2029
  output = toTwine1Archive(story, startName);
@@ -2037,7 +2042,7 @@ async function buildOutput(options) {
2037
2042
  throw new TweeTsError("No story format available for HTML output.", diagnostics);
2038
2043
  }
2039
2044
  if (format.isTwine2) {
2040
- output = toTwine2HTML(story, format, startName, diagnostics);
2045
+ output = toTwine2HTML(story, format, startName, diagnostics, { sourceInfo });
2041
2046
  } else {
2042
2047
  if (story.name === "" && !storyHas(story, "StoryTitle")) {
2043
2048
  diagnostics.push({
@@ -2168,7 +2173,7 @@ function validateConfig(data) {
2168
2173
  errors.push(`"${key}" must be a string.`);
2169
2174
  }
2170
2175
  }
2171
- for (const key of ["useTweegoPath", "trim", "twee2Compat", "testMode", "noRemote"]) {
2176
+ for (const key of ["useTweegoPath", "trim", "twee2Compat", "testMode", "noRemote", "sourceInfo"]) {
2172
2177
  if (key in obj && typeof obj[key] !== "boolean") {
2173
2178
  errors.push(`"${key}" must be a boolean.`);
2174
2179
  }
@@ -2238,6 +2243,7 @@ var { values, positionals } = parseArgs({
2238
2243
  "format-url": { type: "string", multiple: true },
2239
2244
  "no-remote": { type: "boolean" },
2240
2245
  "tag-alias": { type: "string", multiple: true },
2246
+ "source-info": { type: "boolean" },
2241
2247
  config: { type: "string", short: "c" },
2242
2248
  "no-config": { type: "boolean" }
2243
2249
  }
@@ -2306,7 +2312,8 @@ async function main() {
2306
2312
  formatIndices: values["format-index"] ?? config?.formatIndices,
2307
2313
  formatUrls: values["format-url"] ?? config?.formatUrls,
2308
2314
  noRemote: values["no-remote"] ?? config?.noRemote ?? false,
2309
- tagAliases
2315
+ tagAliases,
2316
+ sourceInfo: values["source-info"] ?? config?.sourceInfo ?? false
2310
2317
  };
2311
2318
  const outFile = values.output ?? config?.output ?? "-";
2312
2319
  if (values.watch) {
@@ -2432,6 +2439,7 @@ Options:
2432
2439
  --format-index <url> SFA-compatible format index URL (repeatable)
2433
2440
  --format-url <url> Direct format.js URL (repeatable)
2434
2441
  --tag-alias <alias=target> Map a tag to a special tag (repeatable)
2442
+ --source-info Emit source file/line as data- attributes on passages
2435
2443
  --no-remote Disable remote format fetching
2436
2444
  -c, --config <file> Config file path (default: ${CONFIG_FILENAME})
2437
2445
  --no-config Skip config file loading