squiffy-compiler 6.0.0-alpha.2 → 6.0.0-alpha.20

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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014-2024 Alex Warren, textadventures.co.uk and contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -1,4 +1,3 @@
1
- export declare const SQUIFFY_VERSION = "6.0.0-alpha.2";
2
1
  export interface Output {
3
2
  story: OutputStory;
4
3
  js: string[][];
@@ -6,6 +5,7 @@ export interface Output {
6
5
  interface OutputStory {
7
6
  start: string;
8
7
  id: string | null;
8
+ uiJsIndex?: number;
9
9
  sections: Record<string, OutputSection>;
10
10
  }
11
11
  interface OutputSection {
@@ -23,10 +23,11 @@ interface OutputPassage {
23
23
  jsIndex?: number;
24
24
  }
25
25
  interface CompilerSettings {
26
- scriptBaseFilename: string;
26
+ scriptBaseFilename?: string;
27
27
  script: string;
28
28
  onWarning?: (message: string) => void;
29
29
  externalFiles?: ExternalFiles;
30
+ globalJs?: boolean;
30
31
  }
31
32
  interface ExternalFiles {
32
33
  getMatchingFilenames(pattern: string): Promise<string[]>;
package/dist/compiler.js CHANGED
@@ -1,24 +1,33 @@
1
- import * as marked from 'marked';
2
- export const SQUIFFY_VERSION = '6.0.0-alpha.2';
1
+ import pkg from "../package.json" with { type: "json" };
2
+ const version = pkg.version;
3
3
  export async function compile(settings) {
4
4
  const story = new Story(settings.scriptBaseFilename);
5
5
  const errors = [];
6
+ let autoSectionCount = 0;
6
7
  async function getJs(storyData, excludeHeader) {
7
8
  const outputJs = [];
8
9
  if (!excludeHeader) {
9
- outputJs.push(`// Created with Squiffy ${SQUIFFY_VERSION}`);
10
- outputJs.push('// https://github.com/textadventures/squiffy');
10
+ outputJs.push(`// Created with Squiffy ${version}`);
11
+ outputJs.push("// https://github.com/textadventures/squiffy");
12
+ }
13
+ if (settings.globalJs) {
14
+ outputJs.push("var story = {};");
15
+ }
16
+ else {
17
+ outputJs.push("export const story = {};");
11
18
  }
12
- outputJs.push('export const story = {};');
13
19
  outputJs.push(`story.id = ${JSON.stringify(storyData.story.id, null, 4)};`);
20
+ if (storyData.story.uiJsIndex !== undefined) {
21
+ outputJs.push(`story.uiJsIndex = ${storyData.story.uiJsIndex};`);
22
+ }
14
23
  outputJs.push(`story.start = ${JSON.stringify(storyData.story.start, null, 4)};`);
15
24
  outputJs.push(`story.sections = ${JSON.stringify(storyData.story.sections, null, 4)};`);
16
- outputJs.push('story.js = [');
25
+ outputJs.push("story.js = [");
17
26
  for (const js of storyData.js) {
18
27
  writeJs(outputJs, 1, js);
19
28
  }
20
- outputJs.push('];');
21
- return outputJs.join('\n');
29
+ outputJs.push("];");
30
+ return outputJs.join("\n");
22
31
  }
23
32
  async function getStoryData() {
24
33
  if (!story.start) {
@@ -32,6 +41,10 @@ export async function compile(settings) {
32
41
  },
33
42
  js: [],
34
43
  };
44
+ if (story.uiJs.length > 0) {
45
+ output.js.push(story.uiJs);
46
+ output.story.uiJsIndex = output.js.length - 1;
47
+ }
35
48
  for (const sectionName of Object.keys(story.sections)) {
36
49
  const section = story.sections[sectionName];
37
50
  const outputSection = {};
@@ -39,7 +52,7 @@ export async function compile(settings) {
39
52
  if (section.clear) {
40
53
  outputSection.clear = true;
41
54
  }
42
- outputSection.text = await processText(section.text.join('\n'), section, null);
55
+ outputSection.text = await processText(section.text.join("\n"), section, null);
43
56
  if (section.attributes.length > 0) {
44
57
  outputSection.attributes = section.attributes;
45
58
  }
@@ -47,10 +60,10 @@ export async function compile(settings) {
47
60
  output.js.push(section.js);
48
61
  outputSection.jsIndex = output.js.length - 1;
49
62
  }
50
- if ('@last' in section.passages) {
51
- var passageCount = 0;
63
+ if ("@last" in section.passages) {
64
+ let passageCount = 0;
52
65
  for (const passageName of Object.keys(section.passages)) {
53
- if (passageName.length > 0 && passageName?.substring(0, 1) !== '@') {
66
+ if (passageName.length > 0 && passageName?.substring(0, 1) !== "@") {
54
67
  passageCount++;
55
68
  }
56
69
  }
@@ -66,7 +79,7 @@ export async function compile(settings) {
66
79
  if (passage.clear) {
67
80
  outputPassage.clear = true;
68
81
  }
69
- outputPassage.text = await processText(passage.text.join('\n'), section, passage);
82
+ outputPassage.text = await processText(passage.text.join("\n"), section, passage);
70
83
  if (passage.attributes.length > 0) {
71
84
  outputPassage.attributes = passage.attributes;
72
85
  }
@@ -78,7 +91,6 @@ export async function compile(settings) {
78
91
  }
79
92
  return output;
80
93
  }
81
- ;
82
94
  const regexes = {
83
95
  section: /^\[\[(.*)\]\]:$/,
84
96
  passage: /^\[(.*)\]:$/,
@@ -89,28 +101,38 @@ export async function compile(settings) {
89
101
  unset: /^@unset (.*)$/,
90
102
  inc: /^@inc (\S+)(?: (\d+))?$/,
91
103
  dec: /^@dec (\S+)(?: (\d+))?$/,
92
- replace: /^@replace (.*$)/,
93
104
  js: /^(\t| {4})(.*)$/,
94
105
  continue: /^\+\+\+(.*)$/,
106
+ ui: /^@ui (.*)$/,
95
107
  };
96
108
  async function processFileText(inputText, inputFilename, isFirst) {
97
- var inputLines = inputText.replace(/\r/g, '').split('\n');
98
- var lineCount = 0;
99
- var autoSectionCount = 0;
100
- var section = null;
101
- var passage = null; // annotated differently to section, as a workaround for TypeScript "Property does not exist on type never"
102
- var textStarted = false;
103
- var ensureThisSectionExists = () => {
109
+ const inputLines = inputText.replace(/\r/g, "").split("\n");
110
+ let lineCount = 0;
111
+ let section = null;
112
+ let passage = null; // annotated differently to section, as a workaround for TypeScript "Property does not exist on type never"
113
+ let textStarted = false;
114
+ let inUiBlock = false;
115
+ const ensureThisSectionExists = () => {
104
116
  return ensureSectionExists(section, isFirst, inputFilename, lineCount);
105
117
  };
106
- const secondPass = [];
118
+ const addAutoSection = () => {
119
+ autoSectionCount++;
120
+ const autoSectionName = `_continue${autoSectionCount}`;
121
+ section = story.addSection(autoSectionName, inputFilename, lineCount);
122
+ passage = null;
123
+ textStarted = false;
124
+ return autoSectionName;
125
+ };
107
126
  for (const line of inputLines) {
108
- var stripLine = line.trim();
127
+ const stripLine = line.trim();
109
128
  lineCount++;
110
- var match = {};
129
+ const match = {};
111
130
  for (const key of Object.keys(regexes)) {
112
131
  const regex = regexes[key];
113
- match[key] = key == 'js' ? regex.exec(line) : regex.exec(stripLine);
132
+ const result = key == "js" ? regex.exec(line) : regex.exec(stripLine);
133
+ if (result) {
134
+ match[key] = result;
135
+ }
114
136
  }
115
137
  if (match.section) {
116
138
  section = story.addSection(match.section[1], inputFilename, lineCount);
@@ -119,7 +141,7 @@ export async function compile(settings) {
119
141
  }
120
142
  else if (match.passage) {
121
143
  if (!section) {
122
- errors.push(`ERROR: ${inputFilename} line ${lineCount}: Can\'t add passage "${match.passage[1]}" as no section has been created.`);
144
+ errors.push(`ERROR: ${inputFilename} line ${lineCount}: Can't add passage "${match.passage[1]}" as no section has been created.`);
123
145
  return false;
124
146
  }
125
147
  section = ensureThisSectionExists();
@@ -128,14 +150,29 @@ export async function compile(settings) {
128
150
  }
129
151
  else if (match.continue) {
130
152
  section = ensureThisSectionExists();
131
- autoSectionCount++;
132
- var autoSectionName = `_continue${autoSectionCount}`;
133
- section.addText(`[[${match.continue[1]}]](${autoSectionName})`);
134
- section = story.addSection(autoSectionName, inputFilename, lineCount);
135
- passage = null;
136
- textStarted = false;
153
+ const previousSection = section;
154
+ const autoSectionName = addAutoSection();
155
+ const text = match.continue[1] || "Continue...";
156
+ previousSection.addText(`[[${text}]](${autoSectionName})`);
157
+ }
158
+ else if (stripLine == "---") {
159
+ inUiBlock = false;
160
+ if (!section) {
161
+ // Just add the _default section if we haven't started yet
162
+ ensureThisSectionExists();
163
+ }
164
+ else {
165
+ addAutoSection();
166
+ }
167
+ }
168
+ else if (stripLine == "@ui") {
169
+ inUiBlock = true;
137
170
  }
138
- else if (stripLine == '@clear') {
171
+ else if (match.ui && settings.externalFiles) {
172
+ const content = await settings.externalFiles.getContent(match.ui[1]);
173
+ story.addUiJs(content);
174
+ }
175
+ else if (stripLine == "@clear") {
139
176
  if (!passage) {
140
177
  section = ensureThisSectionExists();
141
178
  section.clear = true;
@@ -151,18 +188,18 @@ export async function compile(settings) {
151
188
  story.start = match.start[1];
152
189
  }
153
190
  else if (match.import && settings.externalFiles) {
154
- var importFilenames = await settings.externalFiles.getMatchingFilenames(match.import[1]);
191
+ const importFilenames = await settings.externalFiles.getMatchingFilenames(match.import[1]);
155
192
  for (const importFilename of importFilenames) {
156
- if (importFilename.endsWith('.squiffy')) {
193
+ if (importFilename.endsWith(".squiffy")) {
157
194
  const content = await settings.externalFiles.getContent(importFilename);
158
- var success = await processFileText(content, importFilename, false);
195
+ const success = await processFileText(content, importFilename, false);
159
196
  if (!success)
160
197
  return false;
161
198
  }
162
- else if (importFilename.endsWith('.js')) {
199
+ else if (importFilename.endsWith(".js")) {
163
200
  story.scripts.push(settings.externalFiles.getLocalFilename(importFilename));
164
201
  }
165
- else if (importFilename.endsWith('.css')) {
202
+ else if (importFilename.endsWith(".css")) {
166
203
  story.stylesheets.push(settings.externalFiles.getLocalFilename(importFilename));
167
204
  }
168
205
  }
@@ -173,31 +210,21 @@ export async function compile(settings) {
173
210
  }
174
211
  else if (match.unset) {
175
212
  section = ensureThisSectionExists();
176
- section = addAttribute('not ' + match.unset[1], section, passage, isFirst, inputFilename, lineCount);
213
+ section = addAttribute("not " + match.unset[1], section, passage, isFirst, inputFilename, lineCount);
177
214
  }
178
215
  else if (match.inc) {
179
216
  section = ensureThisSectionExists();
180
- section = addAttribute(match.inc[1] + '+=' + (match.inc[2] === undefined ? '1' : match.inc[2]), section, passage, isFirst, inputFilename, lineCount);
217
+ section = addAttribute(match.inc[1] + "+=" + (match.inc[2] === undefined ? "1" : match.inc[2]), section, passage, isFirst, inputFilename, lineCount);
181
218
  }
182
219
  else if (match.dec) {
183
220
  section = ensureThisSectionExists();
184
- section = addAttribute(match.dec[1] + '-=' + (match.dec[2] === undefined ? '1' : match.dec[2]), section, passage, isFirst, inputFilename, lineCount);
185
- }
186
- else if (match.replace) {
187
- const thisSection = ensureThisSectionExists();
188
- const thisPassage = passage;
189
- var replaceAttribute = match.replace[1];
190
- var attributeMatch = /^(.*?)=(.*)$/.exec(replaceAttribute);
191
- secondPass.push(async () => {
192
- // add this to secondPass functions, because processText might result in links to passages which have not been created yet
193
- if (attributeMatch) {
194
- replaceAttribute = attributeMatch[1] + '=' + await processText(attributeMatch[2], thisSection, null);
195
- }
196
- addAttribute('@replace ' + replaceAttribute, section, thisPassage, isFirst, inputFilename, lineCount);
197
- });
221
+ section = addAttribute(match.dec[1] + "-=" + (match.dec[2] === undefined ? "1" : match.dec[2]), section, passage, isFirst, inputFilename, lineCount);
198
222
  }
199
223
  else if (!textStarted && match.js) {
200
- if (!passage) {
224
+ if (inUiBlock) {
225
+ story.addUiJs(match.js[2]);
226
+ }
227
+ else if (!passage) {
201
228
  section = ensureThisSectionExists();
202
229
  section.addJS(match.js[2]);
203
230
  }
@@ -206,7 +233,10 @@ export async function compile(settings) {
206
233
  }
207
234
  }
208
235
  else if (textStarted || stripLine.length > 0) {
209
- if (!passage) {
236
+ if (inUiBlock) {
237
+ errors.push(`ERROR: ${inputFilename} line ${lineCount}: Unexpected text in @ui block.`);
238
+ }
239
+ else if (!passage) {
210
240
  section = ensureThisSectionExists();
211
241
  if (section) {
212
242
  section.addText(line);
@@ -219,19 +249,14 @@ export async function compile(settings) {
219
249
  }
220
250
  }
221
251
  }
222
- for (const fn of secondPass) {
223
- await fn();
224
- }
225
252
  return true;
226
253
  }
227
- ;
228
254
  function ensureSectionExists(section, isFirst, inputFilename, lineCount) {
229
255
  if (!section && isFirst) {
230
- section = story.addSection('_default', inputFilename, lineCount);
256
+ section = story.addSection("_default", inputFilename, lineCount);
231
257
  }
232
258
  return section;
233
259
  }
234
- ;
235
260
  function addAttribute(attribute, section, passage, isFirst, inputFilename, lineCount) {
236
261
  if (!passage) {
237
262
  section = ensureSectionExists(section, isFirst, inputFilename, lineCount);
@@ -242,7 +267,24 @@ export async function compile(settings) {
242
267
  }
243
268
  return section;
244
269
  }
245
- ;
270
+ function extractLinkFunctions(link) {
271
+ const fragments = link.split(",");
272
+ return {
273
+ target: fragments[0].trim(),
274
+ setters: fragments.slice(1).join(", ")
275
+ };
276
+ }
277
+ function getAdditionalLinkParameters(link) {
278
+ const functions = extractLinkFunctions(link);
279
+ let additionalParameters = "";
280
+ if (functions.setters.length > 0) {
281
+ additionalParameters += ` set="${functions.setters}"`;
282
+ }
283
+ return {
284
+ target: functions.target,
285
+ additionalParameters
286
+ };
287
+ }
246
288
  async function processText(input, section, passage) {
247
289
  // namedSectionLinkRegex matches:
248
290
  // open [[
@@ -251,10 +293,13 @@ export async function compile(settings) {
251
293
  // open bracket
252
294
  // any text - the name of the section
253
295
  // closing bracket
254
- var namedSectionLinkRegex = /\[\[([^\]]*?)\]\]\((.*?)\)/g;
255
- var links = allMatchesForGroup(input, namedSectionLinkRegex, 2);
296
+ const namedSectionLinkRegex = /\[\[([^\]]*?)\]\]\((.*?)\)/g;
297
+ let links = allMatchesForGroup(input, namedSectionLinkRegex, 2);
256
298
  checkSectionLinks(links, section, passage);
257
- input = input.replace(namedSectionLinkRegex, '<a class="squiffy-link link-section" data-section="$2" role="link" tabindex="0">$1</a>');
299
+ input = input.replace(namedSectionLinkRegex, (_match, text /* $1 */, name /* $2 */) => {
300
+ const parsedName = getAdditionalLinkParameters(name);
301
+ return `{{section "${parsedName.target}" text="${text}"${parsedName.additionalParameters}}}`;
302
+ });
258
303
  // namedPassageLinkRegex matches:
259
304
  // open [
260
305
  // any text - the link text
@@ -262,68 +307,61 @@ export async function compile(settings) {
262
307
  // open bracket, but not http(s):// after it
263
308
  // any text - the name of the passage
264
309
  // closing bracket
265
- var namedPassageLinkRegex = /\[([^\]]*?)\]\(((?!https?:\/\/).*?)\)/g;
310
+ const namedPassageLinkRegex = /\[([^\]]*?)\]\(((?!https?:\/\/).*?)\)/g;
266
311
  links = allMatchesForGroup(input, namedPassageLinkRegex, 2);
267
312
  checkPassageLinks(links, section, passage);
268
- input = input.replace(namedPassageLinkRegex, '<a class="squiffy-link link-passage" data-passage="$2" role="link" tabindex="0">$1</a>');
313
+ input = input.replace(namedPassageLinkRegex, (_match, text /* $1 */, name /* $2 */) => {
314
+ const parsedName = getAdditionalLinkParameters(name);
315
+ return `{{passage "${parsedName.target}" text="${text}"${parsedName.additionalParameters}}}`;
316
+ });
269
317
  // unnamedSectionLinkRegex matches:
270
318
  // open [[
271
319
  // any text - the link text
272
320
  // closing ]]
273
- var unnamedSectionLinkRegex = /\[\[(.*?)\]\]/g;
321
+ const unnamedSectionLinkRegex = /\[\[(.*?)\]\]/g;
274
322
  links = allMatchesForGroup(input, unnamedSectionLinkRegex, 1);
275
323
  checkSectionLinks(links, section, passage);
276
- input = input.replace(unnamedSectionLinkRegex, '<a class="squiffy-link link-section" data-section="$1" role="link" tabindex="0">$1</a>');
324
+ input = input.replace(unnamedSectionLinkRegex, '{{section "$1"}}');
277
325
  // unnamedPassageLinkRegex matches:
278
326
  // open [
279
327
  // any text - the link text
280
328
  // closing ]
281
329
  // no bracket after
282
- var unnamedPassageLinkRegex = /\[(.*?)\]([^\(]|$)/g;
330
+ const unnamedPassageLinkRegex = /\[(.*?)\]([^(]|$)/g;
283
331
  links = allMatchesForGroup(input, unnamedPassageLinkRegex, 1);
284
332
  checkPassageLinks(links, section, passage);
285
- input = input.replace(unnamedPassageLinkRegex, '<a class="squiffy-link link-passage" data-passage="$1" role="link" tabindex="0">$1</a>$2');
286
- return (await marked.parse(input)).trim();
333
+ input = input.replace(unnamedPassageLinkRegex, '{{passage "$1"}}$2');
334
+ return input;
287
335
  }
288
- ;
289
336
  function allMatchesForGroup(input, regex, groupNumber) {
290
- var result = [];
291
- var match;
292
- while (!!(match = regex.exec(input))) {
337
+ const result = [];
338
+ let match;
339
+ while ((match = regex.exec(input))) {
293
340
  result.push(match[groupNumber]);
294
341
  }
295
342
  return result;
296
343
  }
297
- ;
298
344
  function checkSectionLinks(links, section, passage) {
299
- var badLinks = links.filter(m => !linkDestinationExists(m, story.sections));
300
- showBadLinksWarning(badLinks, 'section', '[[', ']]', section, passage);
345
+ const badLinks = links.filter(m => !linkDestinationExists(m, story.sections));
346
+ showBadLinksWarning(badLinks, "section", "[[", "]]", section, passage);
301
347
  }
302
- ;
303
348
  function checkPassageLinks(links, section, passage) {
304
- var badLinks = links.filter(m => !linkDestinationExists(m, section.passages));
305
- showBadLinksWarning(badLinks, 'passage', '[', ']', section, passage);
349
+ const badLinks = links.filter(m => !linkDestinationExists(m, section.passages));
350
+ showBadLinksWarning(badLinks, "passage", "[", "]", section, passage);
306
351
  }
307
- ;
308
352
  function linkDestinationExists(link, keys) {
309
353
  // Link destination data may look like:
310
354
  // passageName
311
355
  // passageName, my_attribute=2
312
- // passageName, @replace 1=new text, some_attribute=5
313
- // @replace 2=some words
314
356
  // We're only interested in checking if the named passage or section exists.
315
- var linkDestination = link.split(',')[0];
316
- if (linkDestination.substring(0, 1) == '@') {
317
- return true;
318
- }
357
+ const linkDestination = link.split(",")[0];
319
358
  return Object.keys(keys).includes(linkDestination);
320
359
  }
321
- ;
322
360
  function showBadLinksWarning(badLinks, linkTo, before, after, section, passage) {
323
361
  if (!settings.onWarning)
324
362
  return;
325
363
  for (const badLink of badLinks) {
326
- var warning;
364
+ let warning;
327
365
  if (!passage) {
328
366
  warning = `${section.filename} line ${section.line}: In section '${section.name}'`;
329
367
  }
@@ -333,18 +371,19 @@ export async function compile(settings) {
333
371
  settings.onWarning(`WARNING: ${warning} there is a link to a ${linkTo} called ${before}${badLink}${after}, which doesn't exist`);
334
372
  }
335
373
  }
336
- ;
337
374
  function writeJs(outputJsFile, tabCount, js) {
338
- var tabs = new Array(tabCount + 1).join('\t');
375
+ const tabs = new Array(tabCount + 1).join("\t");
339
376
  outputJsFile.push(`${tabs}(squiffy, get, set) => {`);
340
377
  for (const jsLine of js) {
341
378
  outputJsFile.push(`${tabs}\t${jsLine}`);
342
379
  }
343
380
  outputJsFile.push(`${tabs}},`);
344
381
  }
345
- ;
346
382
  const success = await processFileText(settings.script, settings.scriptBaseFilename, true);
347
383
  if (success) {
384
+ if (!Object.keys(story.sections).length) {
385
+ ensureSectionExists(null, true, settings.scriptBaseFilename, 0);
386
+ }
348
387
  const storyData = await getStoryData();
349
388
  return {
350
389
  success: true,
@@ -380,7 +419,7 @@ class Story {
380
419
  enumerable: true,
381
420
  configurable: true,
382
421
  writable: true,
383
- value: ''
422
+ value: ""
384
423
  });
385
424
  Object.defineProperty(this, "scripts", {
386
425
  enumerable: true,
@@ -398,7 +437,7 @@ class Story {
398
437
  enumerable: true,
399
438
  configurable: true,
400
439
  writable: true,
401
- value: ''
440
+ value: ""
402
441
  });
403
442
  Object.defineProperty(this, "id", {
404
443
  enumerable: true,
@@ -406,6 +445,12 @@ class Story {
406
445
  writable: true,
407
446
  value: null
408
447
  });
448
+ Object.defineProperty(this, "uiJs", {
449
+ enumerable: true,
450
+ configurable: true,
451
+ writable: true,
452
+ value: []
453
+ });
409
454
  this.id = inputFilename || null;
410
455
  }
411
456
  addSection(name, filename, line) {
@@ -413,7 +458,9 @@ class Story {
413
458
  this.sections[name] = section;
414
459
  return section;
415
460
  }
416
- ;
461
+ addUiJs(text) {
462
+ this.uiJs.push(text);
463
+ }
417
464
  }
418
465
  class Section {
419
466
  constructor(name, filename, line) {
@@ -470,23 +517,19 @@ class Section {
470
517
  this.line = line;
471
518
  }
472
519
  addPassage(name, line) {
473
- var passage = new Passage(name, line);
520
+ const passage = new Passage(name, line);
474
521
  this.passages[name] = passage;
475
522
  return passage;
476
523
  }
477
- ;
478
524
  addText(text) {
479
525
  this.text.push(text);
480
526
  }
481
- ;
482
527
  addJS(text) {
483
528
  this.js.push(text);
484
529
  }
485
- ;
486
530
  addAttribute(text) {
487
531
  this.attributes.push(text);
488
532
  }
489
- ;
490
533
  }
491
534
  class Passage {
492
535
  constructor(name, line) {
@@ -532,13 +575,10 @@ class Passage {
532
575
  addText(text) {
533
576
  this.text.push(text);
534
577
  }
535
- ;
536
578
  addJS(text) {
537
579
  this.js.push(text);
538
580
  }
539
- ;
540
581
  addAttribute(text) {
541
582
  this.attributes.push(text);
542
583
  }
543
- ;
544
584
  }
package/package.json CHANGED
@@ -1,10 +1,7 @@
1
1
  {
2
2
  "name": "squiffy-compiler",
3
- "version": "6.0.0-alpha.2",
3
+ "version": "6.0.0-alpha.20",
4
4
  "description": "A tool for creating multiple-choice interactive stories",
5
- "dependencies": {
6
- "marked": "^13.0.2"
7
- },
8
5
  "author": "Alex Warren",
9
6
  "contributors": [
10
7
  "CrisisSDK",
@@ -18,19 +15,21 @@
18
15
  "license": "MIT",
19
16
  "preferGlobal": true,
20
17
  "devDependencies": {
21
- "@types/node": "^22.5.5",
22
- "glob": "^11.0.0",
23
- "typescript": "^5.6.2",
24
- "vitest": "^2.1.1"
18
+ "@types/node": "^24.3.0",
19
+ "glob": "^11.0.3",
20
+ "typescript": "^5.9.2",
21
+ "vitest": "^3.2.4"
25
22
  },
26
23
  "scripts": {
27
- "test": "vitest",
28
- "build": "tsc"
24
+ "test": "vitest --run",
25
+ "build": "tsc",
26
+ "prepublishOnly": "npm run build && npm run test"
29
27
  },
30
28
  "main": "dist/compiler.js",
31
29
  "types": "dist/compiler.d.ts",
32
30
  "files": [
33
31
  "dist"
34
32
  ],
35
- "type": "module"
33
+ "type": "module",
34
+ "gitHead": "eee4b8836ed791b68d8d56b0d5071129e6214d2b"
36
35
  }