squiffy-compiler 6.0.0-alpha.1 → 6.0.0-alpha.17

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.0";
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[]>;
@@ -41,7 +42,7 @@ interface UiInfo {
41
42
  export interface CompileSuccess {
42
43
  success: true;
43
44
  output: Output;
44
- getJs: () => Promise<string>;
45
+ getJs: (excludeHeader?: boolean) => Promise<string>;
45
46
  getUiInfo: () => UiInfo;
46
47
  }
47
48
  export interface CompileError {
package/dist/compiler.js CHANGED
@@ -1,22 +1,33 @@
1
- import * as marked from 'marked';
2
- export const SQUIFFY_VERSION = '6.0.0-alpha.0';
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
- async function getJs(storyData) {
6
+ let autoSectionCount = 0;
7
+ async function getJs(storyData, excludeHeader) {
7
8
  const outputJs = [];
8
- outputJs.push(`// Created with Squiffy ${SQUIFFY_VERSION}`);
9
- outputJs.push('// https://github.com/textadventures/squiffy');
10
- outputJs.push('export const story = {};');
9
+ if (!excludeHeader) {
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 = {};");
18
+ }
11
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
+ }
12
23
  outputJs.push(`story.start = ${JSON.stringify(storyData.story.start, null, 4)};`);
13
24
  outputJs.push(`story.sections = ${JSON.stringify(storyData.story.sections, null, 4)};`);
14
- outputJs.push('story.js = [');
25
+ outputJs.push("story.js = [");
15
26
  for (const js of storyData.js) {
16
27
  writeJs(outputJs, 1, js);
17
28
  }
18
- outputJs.push('];');
19
- return outputJs.join('\n');
29
+ outputJs.push("];");
30
+ return outputJs.join("\n");
20
31
  }
21
32
  async function getStoryData() {
22
33
  if (!story.start) {
@@ -30,6 +41,10 @@ export async function compile(settings) {
30
41
  },
31
42
  js: [],
32
43
  };
44
+ if (story.uiJs.length > 0) {
45
+ output.js.push(story.uiJs);
46
+ output.story.uiJsIndex = output.js.length - 1;
47
+ }
33
48
  for (const sectionName of Object.keys(story.sections)) {
34
49
  const section = story.sections[sectionName];
35
50
  const outputSection = {};
@@ -37,7 +52,7 @@ export async function compile(settings) {
37
52
  if (section.clear) {
38
53
  outputSection.clear = true;
39
54
  }
40
- outputSection.text = await processText(section.text.join('\n'), section, null);
55
+ outputSection.text = await processText(section.text.join("\n"), section, null);
41
56
  if (section.attributes.length > 0) {
42
57
  outputSection.attributes = section.attributes;
43
58
  }
@@ -45,10 +60,10 @@ export async function compile(settings) {
45
60
  output.js.push(section.js);
46
61
  outputSection.jsIndex = output.js.length - 1;
47
62
  }
48
- if ('@last' in section.passages) {
49
- var passageCount = 0;
63
+ if ("@last" in section.passages) {
64
+ let passageCount = 0;
50
65
  for (const passageName of Object.keys(section.passages)) {
51
- if (passageName.length > 0 && passageName?.substring(0, 1) !== '@') {
66
+ if (passageName.length > 0 && passageName?.substring(0, 1) !== "@") {
52
67
  passageCount++;
53
68
  }
54
69
  }
@@ -64,7 +79,7 @@ export async function compile(settings) {
64
79
  if (passage.clear) {
65
80
  outputPassage.clear = true;
66
81
  }
67
- outputPassage.text = await processText(passage.text.join('\n'), section, passage);
82
+ outputPassage.text = await processText(passage.text.join("\n"), section, passage);
68
83
  if (passage.attributes.length > 0) {
69
84
  outputPassage.attributes = passage.attributes;
70
85
  }
@@ -76,7 +91,6 @@ export async function compile(settings) {
76
91
  }
77
92
  return output;
78
93
  }
79
- ;
80
94
  const regexes = {
81
95
  section: /^\[\[(.*)\]\]:$/,
82
96
  passage: /^\[(.*)\]:$/,
@@ -87,28 +101,38 @@ export async function compile(settings) {
87
101
  unset: /^@unset (.*)$/,
88
102
  inc: /^@inc (\S+)(?: (\d+))?$/,
89
103
  dec: /^@dec (\S+)(?: (\d+))?$/,
90
- replace: /^@replace (.*$)/,
91
104
  js: /^(\t| {4})(.*)$/,
92
105
  continue: /^\+\+\+(.*)$/,
106
+ ui: /^@ui (.*)$/,
93
107
  };
94
108
  async function processFileText(inputText, inputFilename, isFirst) {
95
- var inputLines = inputText.replace(/\r/g, '').split('\n');
96
- var lineCount = 0;
97
- var autoSectionCount = 0;
98
- var section = null;
99
- var passage = null; // annotated differently to section, as a workaround for TypeScript "Property does not exist on type never"
100
- var textStarted = false;
101
- 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 = () => {
102
116
  return ensureSectionExists(section, isFirst, inputFilename, lineCount);
103
117
  };
104
- 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
+ };
105
126
  for (const line of inputLines) {
106
- var stripLine = line.trim();
127
+ const stripLine = line.trim();
107
128
  lineCount++;
108
- var match = {};
129
+ const match = {};
109
130
  for (const key of Object.keys(regexes)) {
110
131
  const regex = regexes[key];
111
- 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
+ }
112
136
  }
113
137
  if (match.section) {
114
138
  section = story.addSection(match.section[1], inputFilename, lineCount);
@@ -117,7 +141,7 @@ export async function compile(settings) {
117
141
  }
118
142
  else if (match.passage) {
119
143
  if (!section) {
120
- 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.`);
121
145
  return false;
122
146
  }
123
147
  section = ensureThisSectionExists();
@@ -126,14 +150,29 @@ export async function compile(settings) {
126
150
  }
127
151
  else if (match.continue) {
128
152
  section = ensureThisSectionExists();
129
- autoSectionCount++;
130
- var autoSectionName = `_continue${autoSectionCount}`;
131
- section.addText(`[[${match.continue[1]}]](${autoSectionName})`);
132
- section = story.addSection(autoSectionName, inputFilename, lineCount);
133
- passage = null;
134
- textStarted = false;
153
+ const previousSection = section;
154
+ const autoSectionName = addAutoSection();
155
+ const text = match.continue[1] || "Continue...";
156
+ previousSection.addText(`[[${text}]](${autoSectionName})`);
135
157
  }
136
- else if (stripLine == '@clear') {
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;
170
+ }
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") {
137
176
  if (!passage) {
138
177
  section = ensureThisSectionExists();
139
178
  section.clear = true;
@@ -149,18 +188,18 @@ export async function compile(settings) {
149
188
  story.start = match.start[1];
150
189
  }
151
190
  else if (match.import && settings.externalFiles) {
152
- var importFilenames = await settings.externalFiles.getMatchingFilenames(match.import[1]);
191
+ const importFilenames = await settings.externalFiles.getMatchingFilenames(match.import[1]);
153
192
  for (const importFilename of importFilenames) {
154
- if (importFilename.endsWith('.squiffy')) {
193
+ if (importFilename.endsWith(".squiffy")) {
155
194
  const content = await settings.externalFiles.getContent(importFilename);
156
- var success = await processFileText(content, importFilename, false);
195
+ const success = await processFileText(content, importFilename, false);
157
196
  if (!success)
158
197
  return false;
159
198
  }
160
- else if (importFilename.endsWith('.js')) {
199
+ else if (importFilename.endsWith(".js")) {
161
200
  story.scripts.push(settings.externalFiles.getLocalFilename(importFilename));
162
201
  }
163
- else if (importFilename.endsWith('.css')) {
202
+ else if (importFilename.endsWith(".css")) {
164
203
  story.stylesheets.push(settings.externalFiles.getLocalFilename(importFilename));
165
204
  }
166
205
  }
@@ -171,31 +210,21 @@ export async function compile(settings) {
171
210
  }
172
211
  else if (match.unset) {
173
212
  section = ensureThisSectionExists();
174
- section = addAttribute('not ' + match.unset[1], section, passage, isFirst, inputFilename, lineCount);
213
+ section = addAttribute("not " + match.unset[1], section, passage, isFirst, inputFilename, lineCount);
175
214
  }
176
215
  else if (match.inc) {
177
216
  section = ensureThisSectionExists();
178
- 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);
179
218
  }
180
219
  else if (match.dec) {
181
220
  section = ensureThisSectionExists();
182
- section = addAttribute(match.dec[1] + '-=' + (match.dec[2] === undefined ? '1' : match.dec[2]), section, passage, isFirst, inputFilename, lineCount);
183
- }
184
- else if (match.replace) {
185
- const thisSection = ensureThisSectionExists();
186
- const thisPassage = passage;
187
- var replaceAttribute = match.replace[1];
188
- var attributeMatch = /^(.*?)=(.*)$/.exec(replaceAttribute);
189
- secondPass.push(async () => {
190
- // add this to secondPass functions, because processText might result in links to passages which have not been created yet
191
- if (attributeMatch) {
192
- replaceAttribute = attributeMatch[1] + '=' + await processText(attributeMatch[2], thisSection, null);
193
- }
194
- addAttribute('@replace ' + replaceAttribute, section, thisPassage, isFirst, inputFilename, lineCount);
195
- });
221
+ section = addAttribute(match.dec[1] + "-=" + (match.dec[2] === undefined ? "1" : match.dec[2]), section, passage, isFirst, inputFilename, lineCount);
196
222
  }
197
223
  else if (!textStarted && match.js) {
198
- if (!passage) {
224
+ if (inUiBlock) {
225
+ story.addUiJs(match.js[2]);
226
+ }
227
+ else if (!passage) {
199
228
  section = ensureThisSectionExists();
200
229
  section.addJS(match.js[2]);
201
230
  }
@@ -204,7 +233,10 @@ export async function compile(settings) {
204
233
  }
205
234
  }
206
235
  else if (textStarted || stripLine.length > 0) {
207
- if (!passage) {
236
+ if (inUiBlock) {
237
+ errors.push(`ERROR: ${inputFilename} line ${lineCount}: Unexpected text in @ui block.`);
238
+ }
239
+ else if (!passage) {
208
240
  section = ensureThisSectionExists();
209
241
  if (section) {
210
242
  section.addText(line);
@@ -217,19 +249,14 @@ export async function compile(settings) {
217
249
  }
218
250
  }
219
251
  }
220
- for (const fn of secondPass) {
221
- await fn();
222
- }
223
252
  return true;
224
253
  }
225
- ;
226
254
  function ensureSectionExists(section, isFirst, inputFilename, lineCount) {
227
255
  if (!section && isFirst) {
228
- section = story.addSection('_default', inputFilename, lineCount);
256
+ section = story.addSection("_default", inputFilename, lineCount);
229
257
  }
230
258
  return section;
231
259
  }
232
- ;
233
260
  function addAttribute(attribute, section, passage, isFirst, inputFilename, lineCount) {
234
261
  if (!passage) {
235
262
  section = ensureSectionExists(section, isFirst, inputFilename, lineCount);
@@ -240,7 +267,24 @@ export async function compile(settings) {
240
267
  }
241
268
  return section;
242
269
  }
243
- ;
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
+ }
244
288
  async function processText(input, section, passage) {
245
289
  // namedSectionLinkRegex matches:
246
290
  // open [[
@@ -249,10 +293,13 @@ export async function compile(settings) {
249
293
  // open bracket
250
294
  // any text - the name of the section
251
295
  // closing bracket
252
- var namedSectionLinkRegex = /\[\[([^\]]*?)\]\]\((.*?)\)/g;
253
- var links = allMatchesForGroup(input, namedSectionLinkRegex, 2);
296
+ const namedSectionLinkRegex = /\[\[([^\]]*?)\]\]\((.*?)\)/g;
297
+ let links = allMatchesForGroup(input, namedSectionLinkRegex, 2);
254
298
  checkSectionLinks(links, section, passage);
255
- 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
+ });
256
303
  // namedPassageLinkRegex matches:
257
304
  // open [
258
305
  // any text - the link text
@@ -260,68 +307,61 @@ export async function compile(settings) {
260
307
  // open bracket, but not http(s):// after it
261
308
  // any text - the name of the passage
262
309
  // closing bracket
263
- var namedPassageLinkRegex = /\[([^\]]*?)\]\(((?!https?:\/\/).*?)\)/g;
310
+ const namedPassageLinkRegex = /\[([^\]]*?)\]\(((?!https?:\/\/).*?)\)/g;
264
311
  links = allMatchesForGroup(input, namedPassageLinkRegex, 2);
265
312
  checkPassageLinks(links, section, passage);
266
- 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
+ });
267
317
  // unnamedSectionLinkRegex matches:
268
318
  // open [[
269
319
  // any text - the link text
270
320
  // closing ]]
271
- var unnamedSectionLinkRegex = /\[\[(.*?)\]\]/g;
321
+ const unnamedSectionLinkRegex = /\[\[(.*?)\]\]/g;
272
322
  links = allMatchesForGroup(input, unnamedSectionLinkRegex, 1);
273
323
  checkSectionLinks(links, section, passage);
274
- 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"}}');
275
325
  // unnamedPassageLinkRegex matches:
276
326
  // open [
277
327
  // any text - the link text
278
328
  // closing ]
279
329
  // no bracket after
280
- var unnamedPassageLinkRegex = /\[(.*?)\]([^\(]|$)/g;
330
+ const unnamedPassageLinkRegex = /\[(.*?)\]([^(]|$)/g;
281
331
  links = allMatchesForGroup(input, unnamedPassageLinkRegex, 1);
282
332
  checkPassageLinks(links, section, passage);
283
- input = input.replace(unnamedPassageLinkRegex, '<a class="squiffy-link link-passage" data-passage="$1" role="link" tabindex="0">$1</a>$2');
284
- return (await marked.parse(input)).trim();
333
+ input = input.replace(unnamedPassageLinkRegex, '{{passage "$1"}}$2');
334
+ return input;
285
335
  }
286
- ;
287
336
  function allMatchesForGroup(input, regex, groupNumber) {
288
- var result = [];
289
- var match;
290
- while (!!(match = regex.exec(input))) {
337
+ const result = [];
338
+ let match;
339
+ while ((match = regex.exec(input))) {
291
340
  result.push(match[groupNumber]);
292
341
  }
293
342
  return result;
294
343
  }
295
- ;
296
344
  function checkSectionLinks(links, section, passage) {
297
- var badLinks = links.filter(m => !linkDestinationExists(m, story.sections));
298
- showBadLinksWarning(badLinks, 'section', '[[', ']]', section, passage);
345
+ const badLinks = links.filter(m => !linkDestinationExists(m, story.sections));
346
+ showBadLinksWarning(badLinks, "section", "[[", "]]", section, passage);
299
347
  }
300
- ;
301
348
  function checkPassageLinks(links, section, passage) {
302
- var badLinks = links.filter(m => !linkDestinationExists(m, section.passages));
303
- showBadLinksWarning(badLinks, 'passage', '[', ']', section, passage);
349
+ const badLinks = links.filter(m => !linkDestinationExists(m, section.passages));
350
+ showBadLinksWarning(badLinks, "passage", "[", "]", section, passage);
304
351
  }
305
- ;
306
352
  function linkDestinationExists(link, keys) {
307
353
  // Link destination data may look like:
308
354
  // passageName
309
355
  // passageName, my_attribute=2
310
- // passageName, @replace 1=new text, some_attribute=5
311
- // @replace 2=some words
312
356
  // We're only interested in checking if the named passage or section exists.
313
- var linkDestination = link.split(',')[0];
314
- if (linkDestination.substring(0, 1) == '@') {
315
- return true;
316
- }
357
+ const linkDestination = link.split(",")[0];
317
358
  return Object.keys(keys).includes(linkDestination);
318
359
  }
319
- ;
320
360
  function showBadLinksWarning(badLinks, linkTo, before, after, section, passage) {
321
361
  if (!settings.onWarning)
322
362
  return;
323
363
  for (const badLink of badLinks) {
324
- var warning;
364
+ let warning;
325
365
  if (!passage) {
326
366
  warning = `${section.filename} line ${section.line}: In section '${section.name}'`;
327
367
  }
@@ -331,24 +371,25 @@ export async function compile(settings) {
331
371
  settings.onWarning(`WARNING: ${warning} there is a link to a ${linkTo} called ${before}${badLink}${after}, which doesn't exist`);
332
372
  }
333
373
  }
334
- ;
335
374
  function writeJs(outputJsFile, tabCount, js) {
336
- var tabs = new Array(tabCount + 1).join('\t');
337
- outputJsFile.push(`${tabs}function() {\n`);
375
+ const tabs = new Array(tabCount + 1).join("\t");
376
+ outputJsFile.push(`${tabs}(squiffy, get, set) => {`);
338
377
  for (const jsLine of js) {
339
- outputJsFile.push(`${tabs}\t${jsLine}\n`);
378
+ outputJsFile.push(`${tabs}\t${jsLine}`);
340
379
  }
341
- outputJsFile.push(`${tabs}},\n`);
380
+ outputJsFile.push(`${tabs}},`);
342
381
  }
343
- ;
344
382
  const success = await processFileText(settings.script, settings.scriptBaseFilename, true);
345
383
  if (success) {
384
+ if (!Object.keys(story.sections).length) {
385
+ ensureSectionExists(null, true, settings.scriptBaseFilename, 0);
386
+ }
346
387
  const storyData = await getStoryData();
347
388
  return {
348
389
  success: true,
349
390
  output: storyData,
350
- getJs: () => {
351
- return getJs(storyData);
391
+ getJs: (excludeHeader) => {
392
+ return getJs(storyData, excludeHeader || false);
352
393
  },
353
394
  getUiInfo: () => {
354
395
  return {
@@ -378,7 +419,7 @@ class Story {
378
419
  enumerable: true,
379
420
  configurable: true,
380
421
  writable: true,
381
- value: ''
422
+ value: ""
382
423
  });
383
424
  Object.defineProperty(this, "scripts", {
384
425
  enumerable: true,
@@ -396,7 +437,7 @@ class Story {
396
437
  enumerable: true,
397
438
  configurable: true,
398
439
  writable: true,
399
- value: ''
440
+ value: ""
400
441
  });
401
442
  Object.defineProperty(this, "id", {
402
443
  enumerable: true,
@@ -404,6 +445,12 @@ class Story {
404
445
  writable: true,
405
446
  value: null
406
447
  });
448
+ Object.defineProperty(this, "uiJs", {
449
+ enumerable: true,
450
+ configurable: true,
451
+ writable: true,
452
+ value: []
453
+ });
407
454
  this.id = inputFilename || null;
408
455
  }
409
456
  addSection(name, filename, line) {
@@ -411,7 +458,9 @@ class Story {
411
458
  this.sections[name] = section;
412
459
  return section;
413
460
  }
414
- ;
461
+ addUiJs(text) {
462
+ this.uiJs.push(text);
463
+ }
415
464
  }
416
465
  class Section {
417
466
  constructor(name, filename, line) {
@@ -468,23 +517,19 @@ class Section {
468
517
  this.line = line;
469
518
  }
470
519
  addPassage(name, line) {
471
- var passage = new Passage(name, line);
520
+ const passage = new Passage(name, line);
472
521
  this.passages[name] = passage;
473
522
  return passage;
474
523
  }
475
- ;
476
524
  addText(text) {
477
525
  this.text.push(text);
478
526
  }
479
- ;
480
527
  addJS(text) {
481
528
  this.js.push(text);
482
529
  }
483
- ;
484
530
  addAttribute(text) {
485
531
  this.attributes.push(text);
486
532
  }
487
- ;
488
533
  }
489
534
  class Passage {
490
535
  constructor(name, line) {
@@ -530,13 +575,10 @@ class Passage {
530
575
  addText(text) {
531
576
  this.text.push(text);
532
577
  }
533
- ;
534
578
  addJS(text) {
535
579
  this.js.push(text);
536
580
  }
537
- ;
538
581
  addAttribute(text) {
539
582
  this.attributes.push(text);
540
583
  }
541
- ;
542
584
  }
package/package.json CHANGED
@@ -1,10 +1,7 @@
1
1
  {
2
2
  "name": "squiffy-compiler",
3
- "version": "6.0.0-alpha.1",
3
+ "version": "6.0.0-alpha.17",
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": "59e410271573c741dbc7c6031b7aab5619d9d1c7"
36
35
  }