extwee 2.3.7 → 2.3.9
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 -1
- package/build/extwee.twine1html.min.js +1 -1
- package/build/extwee.twine2archive.min.js +1 -1
- package/build/extwee.tws.min.js +1 -1
- package/docs/build/extwee.core.min.js +1 -1
- package/docs/build/extwee.twine1html.min.js +1 -1
- package/docs/build/extwee.twine2archive.min.js +1 -1
- package/docs/build/extwee.tws.min.js +1 -1
- package/docs/demos/decompile/index.html +15 -9
- package/package.json +10 -11
- package/src/IFID/generate-web.js +20 -0
- package/src/IFID/generate.js +5 -4
- package/src/Passage.js +9 -2
- package/src/Story.js +1 -1
- package/test/Objects/Passage.test.js +36 -15
- package/test/Objects/SnowmanCompatibility.test.js +125 -0
- package/types/src/IFID/generate-web.d.ts +14 -0
- package/types/src/IFID/generate.d.ts +2 -2
- package/types/src/Story.d.ts +1 -1
- package/webpack.config.js +14 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import Passage from '../../src/Passage.js';
|
|
2
|
+
import { Story } from '../../src/Story.js';
|
|
3
|
+
|
|
4
|
+
describe('Snowman Compatibility Tests', function () {
|
|
5
|
+
describe('JavaScript Code in Passages', function () {
|
|
6
|
+
it('Should not HTML-encode JavaScript with quotes', function () {
|
|
7
|
+
const p = new Passage('External', '<%\n$.getScript("https://code.jquery.com/jquery-3.6.0.min.js");\n%>');
|
|
8
|
+
const html = p.toTwine2HTML();
|
|
9
|
+
|
|
10
|
+
// Should preserve quotes in JavaScript
|
|
11
|
+
expect(html.includes('$.getScript("https://code.jquery.com/jquery-3.6.0.min.js");')).toBe(true);
|
|
12
|
+
// Should NOT have HTML entities
|
|
13
|
+
expect(html.includes('"')).toBe(false);
|
|
14
|
+
expect(html.includes('<')).toBe(false);
|
|
15
|
+
expect(html.includes('>')).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('Should preserve complex JavaScript code', function () {
|
|
19
|
+
const code = `<%
|
|
20
|
+
var data = {"key": "value", "test": true};
|
|
21
|
+
if (data.test) {
|
|
22
|
+
console.log("This is a test");
|
|
23
|
+
}
|
|
24
|
+
%>`;
|
|
25
|
+
const p = new Passage('Test', code);
|
|
26
|
+
const html = p.toTwine2HTML();
|
|
27
|
+
|
|
28
|
+
// Verify the exact code is preserved
|
|
29
|
+
expect(html.includes(code)).toBe(true);
|
|
30
|
+
expect(html.includes('"')).toBe(false);
|
|
31
|
+
expect(html.includes('<')).toBe(false);
|
|
32
|
+
expect(html.includes('>')).toBe(false);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('HTML Content in Passages', function () {
|
|
37
|
+
it('Should not HTML-encode HTML tags', function () {
|
|
38
|
+
const p = new Passage('HUD', '<h1>This is the HUD!</h1>\n<p>Status: <strong>Active</strong></p>');
|
|
39
|
+
const html = p.toTwine2HTML();
|
|
40
|
+
|
|
41
|
+
// Should preserve HTML tags
|
|
42
|
+
expect(html.includes('<h1>This is the HUD!</h1>')).toBe(true);
|
|
43
|
+
expect(html.includes('<strong>Active</strong>')).toBe(true);
|
|
44
|
+
// Should NOT have HTML entities
|
|
45
|
+
expect(html.includes('<h1>')).toBe(false);
|
|
46
|
+
expect(html.includes('<strong>')).toBe(false);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('Should preserve nested HTML structures', function () {
|
|
50
|
+
const htmlContent = `<div class="container">
|
|
51
|
+
<h2>Title</h2>
|
|
52
|
+
<ul>
|
|
53
|
+
<li>Item 1</li>
|
|
54
|
+
<li>Item 2</li>
|
|
55
|
+
</ul>
|
|
56
|
+
</div>`;
|
|
57
|
+
const p = new Passage('Container', htmlContent);
|
|
58
|
+
const html = p.toTwine2HTML();
|
|
59
|
+
|
|
60
|
+
// Verify exact HTML is preserved
|
|
61
|
+
expect(html.includes(htmlContent)).toBe(true);
|
|
62
|
+
expect(html.includes('<')).toBe(false);
|
|
63
|
+
expect(html.includes('>')).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('Round-trip Compatibility', function () {
|
|
68
|
+
it('Should round-trip JavaScript code correctly', function () {
|
|
69
|
+
const code = '$.getScript("test.js");';
|
|
70
|
+
const p1 = new Passage('Test', code);
|
|
71
|
+
const html = p1.toTwine2HTML();
|
|
72
|
+
|
|
73
|
+
// Parser should be able to read it back
|
|
74
|
+
// (This would be tested in parse tests, but we verify the HTML is correct)
|
|
75
|
+
expect(html.includes(code)).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('Should generate valid Story HTML with unencoded content', function () {
|
|
79
|
+
const story = new Story();
|
|
80
|
+
story.name = 'Test Story';
|
|
81
|
+
story.IFID = 'TEST-IFID-1234';
|
|
82
|
+
|
|
83
|
+
const p1 = new Passage('Start', '<%\nconsole.log("test");\n%>');
|
|
84
|
+
const p2 = new Passage('HUD', '<h1>Header</h1>');
|
|
85
|
+
|
|
86
|
+
story.passages = [p1, p2];
|
|
87
|
+
|
|
88
|
+
const html = story.toTwine2HTML();
|
|
89
|
+
|
|
90
|
+
// Verify both passages have unencoded content
|
|
91
|
+
expect(html.includes('console.log("test");')).toBe(true);
|
|
92
|
+
expect(html.includes('<h1>Header</h1>')).toBe(true);
|
|
93
|
+
expect(html.includes('"')).toBe(false);
|
|
94
|
+
expect(html.includes('<h1>')).toBe(false);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe('Edge Cases', function () {
|
|
99
|
+
it('Should handle CDATA-like content', function () {
|
|
100
|
+
const content = '<![CDATA[Some data]]>';
|
|
101
|
+
const p = new Passage('Test', content);
|
|
102
|
+
const html = p.toTwine2HTML();
|
|
103
|
+
|
|
104
|
+
expect(html.includes(content)).toBe(true);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('Should handle mixed quotes', function () {
|
|
108
|
+
const content = `var str = "She said 'hello' to me";`;
|
|
109
|
+
const p = new Passage('Test', content);
|
|
110
|
+
const html = p.toTwine2HTML();
|
|
111
|
+
|
|
112
|
+
expect(html.includes(content)).toBe(true);
|
|
113
|
+
expect(html.includes('"')).toBe(false);
|
|
114
|
+
expect(html.includes(''')).toBe(false);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('Should handle template literals', function () {
|
|
118
|
+
const content = 'const msg = `Hello ${name}`;';
|
|
119
|
+
const p = new Passage('Test', content);
|
|
120
|
+
const html = p.toTwine2HTML();
|
|
121
|
+
|
|
122
|
+
expect(html.includes(content)).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates an Interactive Fiction Identification (IFID) based the Treaty of Babel.
|
|
3
|
+
*
|
|
4
|
+
* For Twine works, the IFID is a UUID (v4) in uppercase.
|
|
5
|
+
* @see Treaty of Babel ({@link https://babel.ifarchive.org/babel_rev11.html#the-ifid-for-an-html-story-file})
|
|
6
|
+
* @function generate
|
|
7
|
+
* @description Generates a new IFID using UUIDv4 (RFC 4122). Browser version using Web Crypto API.
|
|
8
|
+
* @returns {string} IFID - A UUIDv4 string in uppercase format
|
|
9
|
+
* @example
|
|
10
|
+
* const ifid = generate();
|
|
11
|
+
* console.log(ifid);
|
|
12
|
+
* // => 'A1B2C3D4-E5F6-G7H8-I9J0-K1L2M3N4O5P6'
|
|
13
|
+
*/
|
|
14
|
+
export function generate(): string;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* For Twine works, the IFID is a UUID (v4) in uppercase.
|
|
5
5
|
* @see Treaty of Babel ({@link https://babel.ifarchive.org/babel_rev11.html#the-ifid-for-an-html-story-file})
|
|
6
6
|
* @function generate
|
|
7
|
-
* @description Generates a new IFID.
|
|
8
|
-
* @returns {string} IFID
|
|
7
|
+
* @description Generates a new IFID using UUIDv4 (RFC 4122).
|
|
8
|
+
* @returns {string} IFID - A UUIDv4 string in uppercase format
|
|
9
9
|
* @example
|
|
10
10
|
* const ifid = generate();
|
|
11
11
|
* console.log(ifid);
|
package/types/src/Story.d.ts
CHANGED
package/webpack.config.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
+
import webpack from 'webpack';
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
mode: 'production',
|
|
@@ -20,6 +21,19 @@ export default {
|
|
|
20
21
|
},
|
|
21
22
|
globalObject: 'this'
|
|
22
23
|
},
|
|
24
|
+
plugins: [
|
|
25
|
+
// Replace Node.js IFID generator with browser version for web builds
|
|
26
|
+
new webpack.NormalModuleReplacementPlugin(
|
|
27
|
+
/src[\\/]IFID[\\/]generate\.js$/,
|
|
28
|
+
'./generate-web.js'
|
|
29
|
+
)
|
|
30
|
+
],
|
|
31
|
+
resolve: {
|
|
32
|
+
fallback: {
|
|
33
|
+
// Exclude Node.js core modules from browser builds
|
|
34
|
+
'crypto': false
|
|
35
|
+
}
|
|
36
|
+
},
|
|
23
37
|
optimization: {
|
|
24
38
|
usedExports: true,
|
|
25
39
|
sideEffects: false,
|