extwee 2.3.2 → 2.3.4
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/build/extwee.core.min.js +1 -0
- package/build/extwee.twine1html.min.js +1 -0
- package/build/extwee.twine2archive.min.js +1 -0
- package/build/extwee.tws.min.js +1 -0
- package/build/test-modular.html +126 -0
- package/docs/build/extwee.core.min.js +1 -0
- package/docs/build/extwee.twine1html.min.js +1 -0
- package/docs/build/extwee.twine2archive.min.js +1 -0
- package/docs/build/extwee.tws.min.js +1 -0
- package/docs/demos/compiler/extwee.core.min.js +1 -0
- package/docs/demos/compiler/index.css +105 -0
- package/docs/demos/compiler/index.html +359 -0
- package/eslint.config.js +4 -1
- package/package.json +25 -22
- package/src/IFID/generate.js +2 -2
- package/src/Story.js +1 -1
- package/src/Twine1HTML/parse-web.js +255 -0
- package/src/Twine2ArchiveHTML/parse-web.js +134 -0
- package/src/Twine2HTML/parse-web.js +434 -0
- package/src/Web/web-core.js +51 -0
- package/src/Web/web-twine1html.js +35 -0
- package/src/Web/web-twine2archive.js +35 -0
- package/src/Web/web-tws.js +30 -0
- package/test/Config/Config.test.js +1 -1
- package/test/Config/isDirectory.test.js +15 -9
- package/test/Config/isFile.test.js +14 -11
- package/test/Config/loadStoryFormat.test.js +49 -33
- package/test/Config/readDirectories.test.js +25 -15
- package/test/Objects/Story.test.js +1 -0
- package/test/StoryFormat/StoryFormat.Parse.test.js +1 -0
- package/test/Twine1HTML/Twine1HTML.Parse.Web.test.js +484 -0
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.Web.test.js +293 -0
- package/test/Twine2ArchiveHTML/Twine2ArchiveHTML.Parse.test.js +1 -0
- package/test/Twine2HTML/Twine2HTML.Parse.Web.test.js +329 -0
- package/test/Twine2HTML/Twine2HTML.Parse.test.js +1 -0
- package/test/Web/web-core-coverage.test.js +175 -0
- package/test/Web/web-core-global.test.js +93 -0
- package/test/Web/web-core.test.js +156 -0
- package/test/Web/window.Extwee.test.js +25 -13
- package/types/src/Story.d.ts +1 -1
- package/types/src/Twine1HTML/parse-web.d.ts +10 -0
- package/types/src/Twine2ArchiveHTML/parse-web.d.ts +37 -0
- package/types/src/Twine2HTML/parse-web.d.ts +21 -0
- package/types/src/Web/html-entities-lite.d.ts +12 -0
- package/types/src/Web/semver-lite.d.ts +10 -0
- package/types/src/Web/uuid-lite.d.ts +6 -0
- package/types/src/Web/web-core.d.ts +23 -0
- package/types/src/Web/web-index.d.ts +1 -0
- package/types/src/Web/web-twine1html.d.ts +10 -0
- package/types/src/Web/web-twine2archive.d.ts +10 -0
- package/types/src/Web/web-tws.d.ts +7 -0
- package/webpack.config.js +23 -2
- package/build/extwee.web.min.js +0 -2
- package/build/extwee.web.min.js.LICENSE.txt +0 -1
- package/web-index.js +0 -31
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Extwee Story Format Compiler Demo</title>
|
|
7
|
+
|
|
8
|
+
<!-- Bootstrap CSS for styling -->
|
|
9
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
10
|
+
|
|
11
|
+
<!-- Custom CSS -->
|
|
12
|
+
<link href="./index.css" rel="stylesheet">
|
|
13
|
+
</head>
|
|
14
|
+
<body>
|
|
15
|
+
<div class="demo-container">
|
|
16
|
+
<!-- Header -->
|
|
17
|
+
<div class="demo-header">
|
|
18
|
+
<h1 class="mb-3">Example Extwee Story Format Compiler</h1>
|
|
19
|
+
<p class="lead mb-0">Compile Twee code with different Twine story formats</p>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Instructions -->
|
|
23
|
+
<div class="demo-section">
|
|
24
|
+
<h3>📝 How to Use</h3>
|
|
25
|
+
<ol>
|
|
26
|
+
<li><strong>Select a Story Format:</strong> Choose from Harlowe, SugarCube, Snowman, or Chapbook</li>
|
|
27
|
+
<li><strong>Enter Twee Code:</strong> Write or paste your Twee story code in the text area</li>
|
|
28
|
+
<li><strong>Compile:</strong> Click the "Compile Story" button to generate the HTML output</li>
|
|
29
|
+
</ol>
|
|
30
|
+
|
|
31
|
+
<div class="example-twee">
|
|
32
|
+
<strong>Example Twee Code:</strong><br>
|
|
33
|
+
<code>:: Start<br>
|
|
34
|
+
This is the beginning of your story.<br>
|
|
35
|
+
<br>
|
|
36
|
+
[[Continue to the next passage->Next]]<br>
|
|
37
|
+
<br>
|
|
38
|
+
:: Next<br>
|
|
39
|
+
This is the second passage of your story.<br>
|
|
40
|
+
<br>
|
|
41
|
+
The End.
|
|
42
|
+
</code>
|
|
43
|
+
</div>
|
|
44
|
+
<div>
|
|
45
|
+
<p>Similar to Twine, this page will automatically assign an IFID to your story.</p>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- Main Demo Interface -->
|
|
50
|
+
<div class="demo-section">
|
|
51
|
+
<div class="row">
|
|
52
|
+
<div class="col-md-4 mb-3">
|
|
53
|
+
<label for="storyFormat" class="form-label"><strong>Story Format</strong></label>
|
|
54
|
+
<select id="storyFormat" class="form-select">
|
|
55
|
+
<option value="">Select a story format...</option>
|
|
56
|
+
<option value="harlowe" data-version="3.3.9">Harlowe (3.3.9)</option>
|
|
57
|
+
<option value="sugarcube" data-version="2.37.3">SugarCube (2.37.3)</option>
|
|
58
|
+
<option value="snowman" data-version="2.0.2">Snowman (2.0.2)</option>
|
|
59
|
+
<option value="chapbook" data-version="2.3.0">Chapbook (2.3.0)</option>
|
|
60
|
+
</select>
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div class="col-md-8 mb-3">
|
|
64
|
+
<div class="d-flex justify-content-between align-items-center">
|
|
65
|
+
<label for="tweeCode" class="form-label"><strong>Twee Code</strong></label>
|
|
66
|
+
<button id="loadExample" class="btn btn-sm btn-outline-secondary">Load Example</button>
|
|
67
|
+
</div>
|
|
68
|
+
<textarea id="tweeCode" class="form-control" rows="15"
|
|
69
|
+
placeholder="Enter your Twee code here..."></textarea>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<div class="row">
|
|
74
|
+
<div class="col-12 text-center">
|
|
75
|
+
<button id="compileBtn" class="btn btn-primary btn-lg" disabled>
|
|
76
|
+
<span id="compileSpinner" class="spinner-border spinner-border-sm me-2" style="display: none;"></span>
|
|
77
|
+
<span id="compileBtnText">Compile Story</span>
|
|
78
|
+
</button>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<!-- Output Section -->
|
|
84
|
+
<div class="demo-section">
|
|
85
|
+
<h4>📄 Compiled Output</h4>
|
|
86
|
+
<div id="outputContainer" class="output-container">
|
|
87
|
+
<div class="loading">Select a story format and enter Twee code, then click "Compile Story" to see the output here.</div>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div class="row mt-3">
|
|
91
|
+
<div class="col-6">
|
|
92
|
+
<button id="downloadBtn" class="btn btn-success w-100" style="display: none;">
|
|
93
|
+
📥 Download HTML File
|
|
94
|
+
</button>
|
|
95
|
+
</div>
|
|
96
|
+
<div class="col-6">
|
|
97
|
+
<button id="previewBtn" class="btn btn-info w-100" style="display: none;">
|
|
98
|
+
👁️ Preview in New Tab
|
|
99
|
+
</button>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<!-- Footer -->
|
|
105
|
+
<div class="demo-section">
|
|
106
|
+
<div class="row">
|
|
107
|
+
<div class="col-md-12">
|
|
108
|
+
<h5>About This Demo</h5>
|
|
109
|
+
<p>This demo uses the <strong>Extwee</strong> web build to compile Twee code with story formats loaded dynamically from the <a href="https://github.com/videlais/story-formats-archive" target="_blank">Story Formats Archive</a>.</p>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
<!-- Load Dependencies -->
|
|
116
|
+
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
|
|
117
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
|
118
|
+
|
|
119
|
+
<!-- Load Local Extwee build -->
|
|
120
|
+
<script src="./extwee.core.min.js"></script>
|
|
121
|
+
|
|
122
|
+
<script>
|
|
123
|
+
$(document).ready(function() {
|
|
124
|
+
let storyFormats = {};
|
|
125
|
+
let currentCompiledHTML = '';
|
|
126
|
+
|
|
127
|
+
// Load story formats index
|
|
128
|
+
async function loadStoryFormatsIndex() {
|
|
129
|
+
try {
|
|
130
|
+
const response = await fetch('https://raw.githubusercontent.com/videlais/story-formats-archive/docs/official/index.json');
|
|
131
|
+
// Convert to JSON.
|
|
132
|
+
const data = await response.json();
|
|
133
|
+
// Use Twine 2 formats only.
|
|
134
|
+
storyFormats = data.twine2;
|
|
135
|
+
// Show versions on console
|
|
136
|
+
console.log('Loaded story formats index:', storyFormats);
|
|
137
|
+
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error('Failed to load story formats index:', error);
|
|
140
|
+
showError('Failed to load story formats. Please check your internet connection.');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Update format info when selection changes
|
|
145
|
+
$('#storyFormat').on('change', function() {
|
|
146
|
+
const selectedFormat = $(this).val();
|
|
147
|
+
const $compileBtn = $('#compileBtn');
|
|
148
|
+
const $formatInfo = $('#formatInfo');
|
|
149
|
+
|
|
150
|
+
if (selectedFormat) {
|
|
151
|
+
$compileBtn.prop('disabled', false);
|
|
152
|
+
$formatInfo.show();
|
|
153
|
+
} else {
|
|
154
|
+
$compileBtn.prop('disabled', true);
|
|
155
|
+
$formatInfo.hide();
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Load example code
|
|
160
|
+
$('#loadExample').on('click', function() {
|
|
161
|
+
const exampleCode = `:: Start
|
|
162
|
+
Welcome to your interactive story!
|
|
163
|
+
|
|
164
|
+
You find yourself at a crossroads in a mysterious forest.
|
|
165
|
+
|
|
166
|
+
[[Take the left path->LeftPath]]
|
|
167
|
+
[[Take the right path->RightPath]]
|
|
168
|
+
|
|
169
|
+
:: LeftPath
|
|
170
|
+
You venture down the left path and discover a hidden cottage.
|
|
171
|
+
|
|
172
|
+
The door creaks open as you approach...
|
|
173
|
+
|
|
174
|
+
[[Enter the cottage->Cottage]]
|
|
175
|
+
[[Return to the crossroads->Start]]
|
|
176
|
+
|
|
177
|
+
:: RightPath
|
|
178
|
+
The right path leads to a sparkling stream.
|
|
179
|
+
|
|
180
|
+
The water is crystal clear and you can see fish swimming below.
|
|
181
|
+
|
|
182
|
+
[[Follow the stream->Stream]]
|
|
183
|
+
[[Return to the crossroads->Start]]
|
|
184
|
+
|
|
185
|
+
:: Cottage
|
|
186
|
+
Inside the cottage, you find an old book on a dusty table.
|
|
187
|
+
|
|
188
|
+
As you open it, magical words begin to glow on the pages...
|
|
189
|
+
|
|
190
|
+
*The End*
|
|
191
|
+
|
|
192
|
+
:: Stream
|
|
193
|
+
You follow the stream until you reach a beautiful waterfall.
|
|
194
|
+
|
|
195
|
+
Behind the waterfall, you discover a secret cave filled with treasure!
|
|
196
|
+
|
|
197
|
+
*The End*`;
|
|
198
|
+
|
|
199
|
+
$('#tweeCode').val(exampleCode);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Show error message
|
|
203
|
+
|
|
204
|
+
// Escape HTML helper to prevent XSS
|
|
205
|
+
function escapeHtml(str) {
|
|
206
|
+
return String(str)
|
|
207
|
+
.replace(/&/g, "&")
|
|
208
|
+
.replace(/</g, "<")
|
|
209
|
+
.replace(/>/g, ">")
|
|
210
|
+
.replace(/"/g, """)
|
|
211
|
+
.replace(/'/g, "'");
|
|
212
|
+
}
|
|
213
|
+
function showError(message) {
|
|
214
|
+
// Escape the error message to prevent XSS
|
|
215
|
+
$('#outputContainer').html(`<div class="error">❌ Error: ${escapeHtml(message)}</div>`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Show success message
|
|
219
|
+
function showSuccess(message) {
|
|
220
|
+
$('#outputContainer').html(`<div class="success">✅ ${message}</div>`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Compile story
|
|
224
|
+
$('#compileBtn').on('click', async function() {
|
|
225
|
+
const selectedFormat = $('#storyFormat').val();
|
|
226
|
+
const formatVersion = $('#storyFormat option:selected').data('version');
|
|
227
|
+
let tweeCode = $('#tweeCode').val().trim();
|
|
228
|
+
|
|
229
|
+
// Check if the input contains the "StoryData" passage
|
|
230
|
+
const hasStoryData = /::\s*StoryData/i.test(tweeCode);
|
|
231
|
+
// If it doesn't, we will add a default one
|
|
232
|
+
// and generate a new IFID
|
|
233
|
+
if (hasStoryData == false) {
|
|
234
|
+
|
|
235
|
+
const ifid = Extwee.generateIFID();
|
|
236
|
+
const storyDataPassage = `:: StoryData
|
|
237
|
+
{"ifid": "${ifid}"}`;
|
|
238
|
+
// Append to the start of the Twee code
|
|
239
|
+
tweeCode = storyDataPassage + '\n\n' + tweeCode;
|
|
240
|
+
console.log('Added StoryData passage with IFID:', ifid);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (!selectedFormat) {
|
|
244
|
+
showError('Please select a story format.');
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (!tweeCode) {
|
|
249
|
+
showError('Please enter some Twee code.');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Show loading state
|
|
254
|
+
const $btn = $(this);
|
|
255
|
+
const $spinner = $('#compileSpinner');
|
|
256
|
+
const $btnText = $('#compileBtnText');
|
|
257
|
+
|
|
258
|
+
$btn.prop('disabled', true);
|
|
259
|
+
$spinner.show();
|
|
260
|
+
$btnText.text('Compiling...');
|
|
261
|
+
$('#outputContainer').html('<div class="loading">🔄 Loading story format and compiling...</div>');
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
// Fetch the latest version of the selected format
|
|
265
|
+
const formatData = storyFormats[selectedFormat];
|
|
266
|
+
let formatUrl = `https://raw.githubusercontent.com/videlais/story-formats-archive/docs/official/twine2/${selectedFormat}/${formatVersion}/format.js`;
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
console.log('Fetching format from:', formatUrl);
|
|
270
|
+
|
|
271
|
+
// Fetch the story format
|
|
272
|
+
const formatResponse = await fetch(formatUrl);
|
|
273
|
+
if (!formatResponse.ok) {
|
|
274
|
+
throw new Error(`Failed to fetch story format: ${formatResponse.status}`);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const formatCode = await formatResponse.text();
|
|
278
|
+
console.log('Story format loaded, size:', formatCode.length);
|
|
279
|
+
|
|
280
|
+
// Parse the story format
|
|
281
|
+
const storyFormat = Extwee.parseStoryFormat(formatCode);
|
|
282
|
+
console.log('Story format parsed:', storyFormat.name, storyFormat.version);
|
|
283
|
+
|
|
284
|
+
// Parse the Twee code
|
|
285
|
+
const story = Extwee.parseTwee(tweeCode);
|
|
286
|
+
console.log('Story parsed, passages:', story.passages.length);
|
|
287
|
+
|
|
288
|
+
// Set story format info
|
|
289
|
+
story.format = storyFormat.name;
|
|
290
|
+
story.formatVersion = storyFormat.version;
|
|
291
|
+
|
|
292
|
+
// Compile to HTML
|
|
293
|
+
const compiledHTML = Extwee.compileTwine2HTML(story, storyFormat);
|
|
294
|
+
currentCompiledHTML = compiledHTML;
|
|
295
|
+
|
|
296
|
+
// Show the compiled output (truncated for display)
|
|
297
|
+
const displayHTML = compiledHTML.length > 2000
|
|
298
|
+
? compiledHTML.substring(0, 2000) + '\n\n... (output truncated, full HTML available for download) ...'
|
|
299
|
+
: compiledHTML;
|
|
300
|
+
|
|
301
|
+
$('#outputContainer').html(`<div class="success">✅ Story compiled successfully!</div><pre>${escapeHtml(displayHTML)}</pre>`);
|
|
302
|
+
|
|
303
|
+
// Show download and preview buttons
|
|
304
|
+
$('#downloadBtn, #previewBtn').show();
|
|
305
|
+
|
|
306
|
+
} catch (error) {
|
|
307
|
+
console.error('Compilation error:', error);
|
|
308
|
+
showError(error.message || 'An unexpected error occurred during compilation.');
|
|
309
|
+
} finally {
|
|
310
|
+
// Reset button state
|
|
311
|
+
$btn.prop('disabled', false);
|
|
312
|
+
$spinner.hide();
|
|
313
|
+
$btnText.text('Compile Story');
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Download compiled HTML
|
|
318
|
+
$('#downloadBtn').on('click', function() {
|
|
319
|
+
if (!currentCompiledHTML) {
|
|
320
|
+
showError('No compiled HTML available for download.');
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const blob = new Blob([currentCompiledHTML], { type: 'text/html' });
|
|
325
|
+
const url = URL.createObjectURL(blob);
|
|
326
|
+
const a = document.createElement('a');
|
|
327
|
+
a.href = url;
|
|
328
|
+
a.download = 'compiled-story.html';
|
|
329
|
+
document.body.appendChild(a);
|
|
330
|
+
a.click();
|
|
331
|
+
document.body.removeChild(a);
|
|
332
|
+
URL.revokeObjectURL(url);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Preview compiled HTML
|
|
336
|
+
$('#previewBtn').on('click', function() {
|
|
337
|
+
if (!currentCompiledHTML) {
|
|
338
|
+
showError('No compiled HTML available for preview.');
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const previewWindow = window.open('', '_blank');
|
|
343
|
+
previewWindow.document.write(currentCompiledHTML);
|
|
344
|
+
previewWindow.document.close();
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Utility function to escape HTML
|
|
348
|
+
function escapeHtml(text) {
|
|
349
|
+
const div = document.createElement('div');
|
|
350
|
+
div.textContent = text;
|
|
351
|
+
return div.innerHTML;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Initialize
|
|
355
|
+
loadStoryFormatsIndex();
|
|
356
|
+
});
|
|
357
|
+
</script>
|
|
358
|
+
</body>
|
|
359
|
+
</html>
|
package/eslint.config.js
CHANGED
|
@@ -18,7 +18,10 @@ export default [
|
|
|
18
18
|
jsdoc: jsdoc
|
|
19
19
|
},
|
|
20
20
|
rules: {
|
|
21
|
-
'jsdoc/require-description': 'warn'
|
|
21
|
+
'jsdoc/require-description': 'warn',
|
|
22
|
+
'jsdoc/check-tag-names': ['error', {
|
|
23
|
+
definedTags: ['jest-environment']
|
|
24
|
+
}]
|
|
22
25
|
}
|
|
23
26
|
},
|
|
24
27
|
pluginJs.configs.recommended,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "extwee",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.4",
|
|
4
4
|
"description": "A story compiler tool using Twine-compatible formats",
|
|
5
5
|
"author": "Dan Cox",
|
|
6
6
|
"main": "index.js",
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
"extwee": "src/extwee.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"test": "jest --runInBand",
|
|
11
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --runInBand",
|
|
12
12
|
"lint": "eslint ./src/**/*.js --fix",
|
|
13
13
|
"lint:test": "eslint ./test/**/*.test.js --fix",
|
|
14
14
|
"build:web": "webpack",
|
|
15
|
+
"analyze:web": "webpack-bundle-analyzer build/extwee.web.min.js",
|
|
15
16
|
"gen-types": "npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types",
|
|
16
|
-
"
|
|
17
|
+
"copy:build": "cp build/*.js docs/build",
|
|
18
|
+
"all": "npm run lint && npm run lint:test && npm run test && npm run build:web && npm run gen-types && npm run copy:build"
|
|
17
19
|
},
|
|
18
20
|
"keywords": [
|
|
19
21
|
"twine",
|
|
@@ -23,37 +25,38 @@
|
|
|
23
25
|
],
|
|
24
26
|
"license": "MIT",
|
|
25
27
|
"dependencies": {
|
|
26
|
-
"commander": "^14.0.
|
|
28
|
+
"commander": "^14.0.1",
|
|
27
29
|
"graphemer": "^1.4.0",
|
|
28
30
|
"html-entities": "^2.6.0",
|
|
29
31
|
"node-html-parser": "^7.0.1",
|
|
30
32
|
"pickleparser": "^0.2.1",
|
|
31
33
|
"semver": "^7.7.2",
|
|
32
34
|
"shelljs": "^0.10.0",
|
|
33
|
-
"uuid": "^
|
|
35
|
+
"uuid": "^13.0.0"
|
|
34
36
|
},
|
|
35
37
|
"devDependencies": {
|
|
36
|
-
"@babel/cli": "^7.28.
|
|
37
|
-
"@babel/core": "^7.28.
|
|
38
|
-
"@babel/preset-env": "^7.28.
|
|
39
|
-
"@eslint/js": "^9.
|
|
40
|
-
"@inquirer/prompts": "^7.6
|
|
41
|
-
"@types/node": "^24.1
|
|
42
|
-
"@types/semver": "^7.7.
|
|
43
|
-
"@types/uuid": "^
|
|
38
|
+
"@babel/cli": "^7.28.3",
|
|
39
|
+
"@babel/core": "^7.28.4",
|
|
40
|
+
"@babel/preset-env": "^7.28.3",
|
|
41
|
+
"@eslint/js": "^9.36.0",
|
|
42
|
+
"@inquirer/prompts": "^7.8.6",
|
|
43
|
+
"@types/node": "^24.6.1",
|
|
44
|
+
"@types/semver": "^7.7.1",
|
|
45
|
+
"@types/uuid": "^11.0.0",
|
|
44
46
|
"babel-loader": "^10.0.0",
|
|
45
47
|
"clean-jsdoc-theme": "^4.3.0",
|
|
46
|
-
"core-js": "^3.
|
|
47
|
-
"eslint": "^9.
|
|
48
|
+
"core-js": "^3.45.1",
|
|
49
|
+
"eslint": "^9.36.0",
|
|
48
50
|
"eslint-plugin-jest": "^29.0.1",
|
|
49
|
-
"eslint-plugin-jsdoc": "^
|
|
50
|
-
"globals": "^16.
|
|
51
|
-
"jest": "^30.0
|
|
52
|
-
"jest-environment-jsdom": "^30.0
|
|
51
|
+
"eslint-plugin-jsdoc": "^60.7.0",
|
|
52
|
+
"globals": "^16.4.0",
|
|
53
|
+
"jest": "^30.2.0",
|
|
54
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
53
55
|
"regenerator-runtime": "^0.14.1",
|
|
54
|
-
"typescript": "^5.
|
|
55
|
-
"typescript-eslint": "^8.
|
|
56
|
-
"webpack": "^5.
|
|
56
|
+
"typescript": "^5.9.3",
|
|
57
|
+
"typescript-eslint": "^8.45.0",
|
|
58
|
+
"webpack": "^5.102.0",
|
|
59
|
+
"webpack-bundle-analyzer": "^4.10.2",
|
|
57
60
|
"webpack-cli": "^6.0.1"
|
|
58
61
|
},
|
|
59
62
|
"repository": {
|
package/src/IFID/generate.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { v4 } from 'uuid';
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Generates an Interactive Fiction Identification (IFID) based the Treaty of Babel.
|
|
@@ -14,7 +14,7 @@ import { v4 } from 'uuid';
|
|
|
14
14
|
* // => 'A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6'
|
|
15
15
|
*/
|
|
16
16
|
function generate () {
|
|
17
|
-
return
|
|
17
|
+
return uuidv4().toUpperCase();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export { generate };
|