@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.
package/dist/index.d.cts CHANGED
@@ -38,6 +38,8 @@ interface CompileOptions {
38
38
  noRemote?: boolean;
39
39
  /** Map alias tags to canonical special tags (e.g. { library: 'script' }). */
40
40
  tagAliases?: Record<string, string>;
41
+ /** Emit source file and line as data- attributes on passage elements. Default: false. */
42
+ sourceInfo?: boolean;
41
43
  }
42
44
  interface CompileToFileOptions extends CompileOptions {
43
45
  /** Output file path. */
@@ -73,6 +75,10 @@ interface CompileStats {
73
75
  words: number;
74
76
  files: string[];
75
77
  }
78
+ interface SourceLocation {
79
+ readonly file: string;
80
+ readonly line: number;
81
+ }
76
82
  interface PassageMetadata {
77
83
  position?: string;
78
84
  size?: string;
@@ -83,6 +89,7 @@ interface Passage {
83
89
  tags: string[];
84
90
  text: string;
85
91
  metadata?: PassageMetadata;
92
+ source?: SourceLocation;
86
93
  }
87
94
  interface Twine1Metadata {
88
95
  settings: Map<string, string>;
@@ -171,6 +178,7 @@ interface TweeTsConfig {
171
178
  testMode?: boolean;
172
179
  noRemote?: boolean;
173
180
  tagAliases?: Record<string, string>;
181
+ sourceInfo?: boolean;
174
182
  }
175
183
 
176
184
  declare class TweeTsError extends Error {
@@ -365,4 +373,4 @@ declare function resolveRemoteFormat(name: string, version: string, indices?: st
365
373
  /** Discover all cached remote formats. Returns a Map like discoverFormats(). */
366
374
  declare function discoverCachedFormats(): Map<string, StoryFormatInfo>;
367
375
 
368
- export { type BrokenLink, CONFIG_FILENAME, type CompileOptions, type CompileResult, type CompileStats, type CompileToFileOptions, type Diagnostic, type InlineSource, ItemType, type LexerItem, type OutputMode, type Passage, type PassageMetadata, type SFAIndex, type SFAIndexEntry, type SourceInput, type Story, type StoryFormatInfo, type StoryMap, TweeLexer, type TweeTsConfig, TweeTsError, type WatchOptions, applyTagAliases, compile, compileToFile, discoverCachedFormats, discoverFormats, fetchAndCacheFormat, fetchDirectFormat, generateIFID, getCacheDir, getFormatSearchDirs, loadConfig, loadConfigFile, parseFormatJSON, parseSemver, parseTwee, resolveRemoteFormat, scaffoldConfig, semverCompare, storyInspect, tweeLexer, validateConfig, validateIFID, watch };
376
+ export { type BrokenLink, CONFIG_FILENAME, type CompileOptions, type CompileResult, type CompileStats, type CompileToFileOptions, type Diagnostic, type InlineSource, ItemType, type LexerItem, type OutputMode, type Passage, type PassageMetadata, type SFAIndex, type SFAIndexEntry, type SourceInput, type SourceLocation, type Story, type StoryFormatInfo, type StoryMap, TweeLexer, type TweeTsConfig, TweeTsError, type WatchOptions, applyTagAliases, compile, compileToFile, discoverCachedFormats, discoverFormats, fetchAndCacheFormat, fetchDirectFormat, generateIFID, getCacheDir, getFormatSearchDirs, loadConfig, loadConfigFile, parseFormatJSON, parseSemver, parseTwee, resolveRemoteFormat, scaffoldConfig, semverCompare, storyInspect, tweeLexer, validateConfig, validateIFID, watch };
package/dist/index.d.ts CHANGED
@@ -38,6 +38,8 @@ interface CompileOptions {
38
38
  noRemote?: boolean;
39
39
  /** Map alias tags to canonical special tags (e.g. { library: 'script' }). */
40
40
  tagAliases?: Record<string, string>;
41
+ /** Emit source file and line as data- attributes on passage elements. Default: false. */
42
+ sourceInfo?: boolean;
41
43
  }
42
44
  interface CompileToFileOptions extends CompileOptions {
43
45
  /** Output file path. */
@@ -73,6 +75,10 @@ interface CompileStats {
73
75
  words: number;
74
76
  files: string[];
75
77
  }
78
+ interface SourceLocation {
79
+ readonly file: string;
80
+ readonly line: number;
81
+ }
76
82
  interface PassageMetadata {
77
83
  position?: string;
78
84
  size?: string;
@@ -83,6 +89,7 @@ interface Passage {
83
89
  tags: string[];
84
90
  text: string;
85
91
  metadata?: PassageMetadata;
92
+ source?: SourceLocation;
86
93
  }
87
94
  interface Twine1Metadata {
88
95
  settings: Map<string, string>;
@@ -171,6 +178,7 @@ interface TweeTsConfig {
171
178
  testMode?: boolean;
172
179
  noRemote?: boolean;
173
180
  tagAliases?: Record<string, string>;
181
+ sourceInfo?: boolean;
174
182
  }
175
183
 
176
184
  declare class TweeTsError extends Error {
@@ -365,4 +373,4 @@ declare function resolveRemoteFormat(name: string, version: string, indices?: st
365
373
  /** Discover all cached remote formats. Returns a Map like discoverFormats(). */
366
374
  declare function discoverCachedFormats(): Map<string, StoryFormatInfo>;
367
375
 
368
- export { type BrokenLink, CONFIG_FILENAME, type CompileOptions, type CompileResult, type CompileStats, type CompileToFileOptions, type Diagnostic, type InlineSource, ItemType, type LexerItem, type OutputMode, type Passage, type PassageMetadata, type SFAIndex, type SFAIndexEntry, type SourceInput, type Story, type StoryFormatInfo, type StoryMap, TweeLexer, type TweeTsConfig, TweeTsError, type WatchOptions, applyTagAliases, compile, compileToFile, discoverCachedFormats, discoverFormats, fetchAndCacheFormat, fetchDirectFormat, generateIFID, getCacheDir, getFormatSearchDirs, loadConfig, loadConfigFile, parseFormatJSON, parseSemver, parseTwee, resolveRemoteFormat, scaffoldConfig, semverCompare, storyInspect, tweeLexer, validateConfig, validateIFID, watch };
376
+ export { type BrokenLink, CONFIG_FILENAME, type CompileOptions, type CompileResult, type CompileStats, type CompileToFileOptions, type Diagnostic, type InlineSource, ItemType, type LexerItem, type OutputMode, type Passage, type PassageMetadata, type SFAIndex, type SFAIndexEntry, type SourceInput, type SourceLocation, type Story, type StoryFormatInfo, type StoryMap, TweeLexer, type TweeTsConfig, TweeTsError, type WatchOptions, applyTagAliases, compile, compileToFile, discoverCachedFormats, discoverFormats, fetchAndCacheFormat, fetchDirectFormat, generateIFID, getCacheDir, getFormatSearchDirs, loadConfig, loadConfigFile, parseFormatJSON, parseSemver, parseTwee, resolveRemoteFormat, scaffoldConfig, semverCompare, storyInspect, tweeLexer, validateConfig, validateIFID, watch };
package/dist/index.js CHANGED
@@ -190,7 +190,7 @@ function passageToTwee(p, outMode) {
190
190
  output += "\n\n";
191
191
  return output;
192
192
  }
193
- function passageToPassagedata(p, pid) {
193
+ function passageToPassagedata(p, pid, options) {
194
194
  let position;
195
195
  let size;
196
196
  if (hasMetadataPosition(p)) {
@@ -207,7 +207,11 @@ function passageToPassagedata(p, pid) {
207
207
  } else {
208
208
  size = "100,100";
209
209
  }
210
- 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>`;
210
+ 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))}`;
211
+ if (options?.sourceInfo && p.source) {
212
+ attrs += ` data-source-file=${quote(attrEscape(p.source.file))} data-source-line="${p.source.line}"`;
213
+ }
214
+ return `${attrs}>${htmlEscape(p.text)}</tw-passagedata>`;
211
215
  }
212
216
  function passageToTiddler(p, pid, obfuscateRot13 = false) {
213
217
  let position;
@@ -1187,7 +1191,7 @@ function parseTwee(source, options = {}) {
1187
1191
  if (pCount > 1 && current) {
1188
1192
  passages.push(current);
1189
1193
  }
1190
- current = { name: "", tags: [], text: "" };
1194
+ current = { name: "", tags: [], text: "", source: { file: filename, line: item.line } };
1191
1195
  break;
1192
1196
  case 3 /* Name */: {
1193
1197
  if (!current) break;
@@ -1434,20 +1438,20 @@ var VERSION = "1.2.0";
1434
1438
 
1435
1439
  // src/output-twine2.ts
1436
1440
  var CREATOR_NAME = "Twee-ts";
1437
- function toTwine2Archive(story, startName, diagnostics) {
1438
- return getTwine2DataChunk(story, startName, diagnostics) + "\n";
1441
+ function toTwine2Archive(story, startName, diagnostics, options) {
1442
+ return getTwine2DataChunk(story, startName, diagnostics, options) + "\n";
1439
1443
  }
1440
- function toTwine2HTML(story, format, startName, diagnostics) {
1444
+ function toTwine2HTML(story, format, startName, diagnostics, options) {
1441
1445
  let template = readFormatSource(format);
1442
1446
  if (template.includes("{{STORY_NAME}}")) {
1443
1447
  template = template.replaceAll("{{STORY_NAME}}", htmlEscape(story.name));
1444
1448
  }
1445
1449
  if (template.includes("{{STORY_DATA}}")) {
1446
- template = template.replace("{{STORY_DATA}}", getTwine2DataChunk(story, startName, diagnostics));
1450
+ template = template.replace("{{STORY_DATA}}", getTwine2DataChunk(story, startName, diagnostics, options));
1447
1451
  }
1448
1452
  return template;
1449
1453
  }
1450
- function getTwine2DataChunk(story, startName, diagnostics) {
1454
+ function getTwine2DataChunk(story, startName, diagnostics, options) {
1451
1455
  ensureIFID(story, diagnostics);
1452
1456
  const parts = [];
1453
1457
  let startID = "";
@@ -1502,7 +1506,7 @@ function getTwine2DataChunk(story, startName, diagnostics) {
1502
1506
  if (p.name === "StorySettings" && story.twine1.settings.size === 0) {
1503
1507
  continue;
1504
1508
  }
1505
- parts.push(passageToPassagedata(p, pid));
1509
+ parts.push(passageToPassagedata(p, pid, options));
1506
1510
  if (startName === p.name) {
1507
1511
  startID = String(pid);
1508
1512
  }
@@ -1512,9 +1516,9 @@ function getTwine2DataChunk(story, startName, diagnostics) {
1512
1516
  for (const [opt, val] of story.twine2.options) {
1513
1517
  if (val) opts.push(opt);
1514
1518
  }
1515
- const options = opts.join(" ");
1519
+ const optionsStr = opts.join(" ");
1516
1520
  const zoom = String(story.twine2.zoom);
1517
- 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>`;
1521
+ 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>`;
1518
1522
  return wrapper + parts.join("") + "</tw-storydata>";
1519
1523
  }
1520
1524
  function ensureIFID(story, diagnostics) {
@@ -1969,6 +1973,7 @@ async function buildOutput(options) {
1969
1973
  const twee2Compat = options.twee2Compat ?? false;
1970
1974
  const testMode = options.testMode ?? false;
1971
1975
  const noRemote = options.noRemote ?? false;
1976
+ const sourceInfo = options.sourceInfo ?? false;
1972
1977
  clearIndexCache();
1973
1978
  const filePaths = [];
1974
1979
  const inlineSources = [];
@@ -2030,7 +2035,7 @@ async function buildOutput(options) {
2030
2035
  output = toTwee(story, outputMode);
2031
2036
  break;
2032
2037
  case "twine2-archive":
2033
- output = toTwine2Archive(story, startName, diagnostics);
2038
+ output = toTwine2Archive(story, startName, diagnostics, { sourceInfo });
2034
2039
  break;
2035
2040
  case "twine1-archive":
2036
2041
  output = toTwine1Archive(story, startName);
@@ -2049,7 +2054,7 @@ async function buildOutput(options) {
2049
2054
  throw new TweeTsError("No story format available for HTML output.", diagnostics);
2050
2055
  }
2051
2056
  if (format.isTwine2) {
2052
- output = toTwine2HTML(story, format, startName, diagnostics);
2057
+ output = toTwine2HTML(story, format, startName, diagnostics, { sourceInfo });
2053
2058
  } else {
2054
2059
  if (story.name === "" && !storyHas(story, "StoryTitle")) {
2055
2060
  diagnostics.push({
@@ -2282,7 +2287,7 @@ function validateConfig(data) {
2282
2287
  errors.push(`"${key}" must be a string.`);
2283
2288
  }
2284
2289
  }
2285
- for (const key of ["useTweegoPath", "trim", "twee2Compat", "testMode", "noRemote"]) {
2290
+ for (const key of ["useTweegoPath", "trim", "twee2Compat", "testMode", "noRemote", "sourceInfo"]) {
2286
2291
  if (key in obj && typeof obj[key] !== "boolean") {
2287
2292
  errors.push(`"${key}" must be a boolean.`);
2288
2293
  }