kawaijs 0.1.1 → 0.1.2

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.
@@ -0,0 +1,5 @@
1
+ export interface BuildOptions {
2
+ outDir?: string;
3
+ }
4
+ export declare function buildProject(projectDir?: string, options?: BuildOptions): boolean;
5
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,UAAU,SAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAmXlF"}
@@ -0,0 +1,384 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { compileScript, formatDiagnostic, KawaError } from '@kawaijs/parser';
4
+ export function buildProject(projectDir = '.', options = {}) {
5
+ const rootDir = path.resolve(process.cwd(), projectDir);
6
+ const scriptPath = path.join(rootDir, 'game', 'script.kawa');
7
+ const stylePath = path.join(rootDir, 'game', 'style.css');
8
+ const assetsDir = path.join(rootDir, 'game', 'assets');
9
+ const outDir = path.resolve(rootDir, options.outDir ?? 'dist');
10
+ console.log(`\nšŸ“¦ Building Kawaijs visual novel...`);
11
+ console.log(` Source: ${rootDir}`);
12
+ console.log(` Output: ${outDir}\n`);
13
+ if (!fs.existsSync(scriptPath)) {
14
+ console.error(`āŒ Error: Cannot find '${scriptPath}'. Make sure you are inside a Kawaijs project directory.`);
15
+ return false;
16
+ }
17
+ // 1. Compile Kawa Script
18
+ let storyPackage;
19
+ try {
20
+ const source = fs.readFileSync(scriptPath, 'utf-8');
21
+ storyPackage = compileScript(source, path.basename(scriptPath));
22
+ console.log(`āœ… Script compiled successfully (${Object.keys(storyPackage.labels).length} labels).`);
23
+ }
24
+ catch (err) {
25
+ if (err instanceof KawaError) {
26
+ const source = fs.readFileSync(scriptPath, 'utf-8');
27
+ console.error(formatDiagnostic(err.diagnostic, source));
28
+ }
29
+ else if (err instanceof Error) {
30
+ console.error(`āŒ Compilation error: ${err.message}`);
31
+ }
32
+ return false;
33
+ }
34
+ // 2. Prepare output directory
35
+ if (fs.existsSync(outDir)) {
36
+ fs.rmSync(outDir, { recursive: true, force: true });
37
+ }
38
+ fs.mkdirSync(outDir, { recursive: true });
39
+ // 3. Copy Assets
40
+ const outAssetsDir = path.join(outDir, 'assets');
41
+ if (fs.existsSync(assetsDir)) {
42
+ copyDirectoryRecursive(assetsDir, outAssetsDir);
43
+ console.log(`āœ… Assets copied to dist/assets/`);
44
+ }
45
+ // 4. Generate Combined style.css
46
+ let combinedCss = `/* Kawaijs Bundled Stylesheet */\n`;
47
+ const themeCssPath = path.resolve(path.dirname(import.meta.url.replace('file:///', '')), '..', '..', '..', 'renderer-dom', 'src', 'theme.css');
48
+ if (fs.existsSync(themeCssPath)) {
49
+ combinedCss += fs.readFileSync(themeCssPath, 'utf-8') + '\n\n';
50
+ }
51
+ if (fs.existsSync(stylePath)) {
52
+ combinedCss += fs.readFileSync(stylePath, 'utf-8') + '\n';
53
+ }
54
+ fs.writeFileSync(path.join(outDir, 'style.css'), combinedCss, 'utf-8');
55
+ console.log(`āœ… Stylesheet bundled to dist/style.css`);
56
+ // 5. Generate Standalone HTML Application
57
+ const htmlContent = `<!DOCTYPE html>
58
+ <html lang="en">
59
+ <head>
60
+ <meta charset="UTF-8">
61
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
62
+ <title>${storyPackage.meta.title ?? 'Kawaijs Visual Novel'}</title>
63
+ <link rel="stylesheet" href="./style.css">
64
+ <style>
65
+ body { margin: 0; padding: 0; background: #000; overflow: hidden; }
66
+ </style>
67
+ </head>
68
+ <body>
69
+ <div id="app"></div>
70
+
71
+ <script type="module">
72
+ const story = ${JSON.stringify(storyPackage, null, 2)};
73
+
74
+ class MemoryStorageAdapter {
75
+ constructor() { this.store = new Map(); }
76
+ getItem(k) { return this.store.get(k) || null; }
77
+ setItem(k, v) { this.store.set(k, v); }
78
+ removeItem(k) { this.store.delete(k); }
79
+ }
80
+ class LocalStorageAdapter {
81
+ getItem(k) { return localStorage.getItem(k); }
82
+ setItem(k, v) { localStorage.setItem(k, v); }
83
+ removeItem(k) { localStorage.removeItem(k); }
84
+ }
85
+ class SaveManager {
86
+ constructor() { this.storage = typeof localStorage !== 'undefined' ? new LocalStorageAdapter() : new MemoryStorageAdapter(); }
87
+ async saveSlot(id, snapshot, previewText) {
88
+ const slot = { id, name: 'Slot ' + id, timestamp: Date.now(), snapshot, previewText };
89
+ this.storage.setItem('kawaijs_save_' + id, JSON.stringify(slot));
90
+ return slot;
91
+ }
92
+ async loadSlot(id) {
93
+ const raw = this.storage.getItem('kawaijs_save_' + id);
94
+ return raw ? JSON.parse(raw) : null;
95
+ }
96
+ }
97
+ function evaluateCondition(cond, vars) {
98
+ const t = (cond || '').trim();
99
+ if (!t || t === 'true') return true;
100
+ if (t === 'false') return false;
101
+ const ops = ['>=', '<=', '!=', '==', '>', '<'];
102
+ for (const op of ops) {
103
+ const idx = t.indexOf(op);
104
+ if (idx !== -1) {
105
+ const l = resolveVal(t.slice(0, idx), vars);
106
+ const r = resolveVal(t.slice(idx + op.length), vars);
107
+ if (op === '>=') return Number(l) >= Number(r);
108
+ if (op === '<=') return Number(l) <= Number(r);
109
+ if (op === '>') return Number(l) > Number(r);
110
+ if (op === '<') return Number(l) < Number(r);
111
+ if (op === '==') return l == r;
112
+ if (op === '!=') return l != r;
113
+ }
114
+ }
115
+ if (t.startsWith('!')) return !Boolean(vars[t.slice(1).trim()]);
116
+ return Boolean(vars[t]);
117
+ }
118
+ function resolveVal(token, vars) {
119
+ const t = token.trim();
120
+ if (t === 'true') return true;
121
+ if (t === 'false') return false;
122
+ if (!isNaN(Number(t)) && t !== '') return Number(t);
123
+ if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) return t.slice(1, -1);
124
+ if (t in vars) return vars[t];
125
+ return t;
126
+ }
127
+ function applySetOp(curr, op, val, vars) {
128
+ const res = (typeof val === 'string' && val in vars) ? vars[val] : val;
129
+ if (op === '+=') return Number(curr || 0) + Number(res);
130
+ if (op === '-=') return Number(curr || 0) - Number(res);
131
+ return res;
132
+ }
133
+ class StoryVM {
134
+ constructor(story) {
135
+ this.story = story;
136
+ this.state = {
137
+ currentLabel: story.meta.startLabel || 'start',
138
+ instructionPointer: 0,
139
+ callStack: [],
140
+ variables: {},
141
+ visual: { background: null, transition: null, characters: {} },
142
+ audio: { music: null, voice: null },
143
+ dialogue: null,
144
+ choices: null,
145
+ isWaitingForInput: false,
146
+ isFinished: false
147
+ };
148
+ this.snapshotStack = [];
149
+ this.listeners = new Set();
150
+ this.saveManager = new SaveManager();
151
+ }
152
+ getState() { return this.state; }
153
+ onStateChange(cb) { this.listeners.add(cb); return () => this.listeners.delete(cb); }
154
+ start() { this.execute(); }
155
+ next() {
156
+ if (this.state.isFinished || (this.state.choices && this.state.choices.length > 0)) return;
157
+ this.state.isWaitingForInput = false;
158
+ this.execute();
159
+ }
160
+ choose(idx) {
161
+ if (!this.state.choices || !this.state.choices[idx]) return;
162
+ const choice = this.state.choices[idx];
163
+ this.state.choices = null;
164
+ this.state.isWaitingForInput = false;
165
+ this.state.currentLabel = choice.targetLabel;
166
+ this.state.instructionPointer = 0;
167
+ this.execute();
168
+ }
169
+ rollback() {
170
+ if (this.snapshotStack.length <= 1) return false;
171
+ this.snapshotStack.pop();
172
+ const prev = this.snapshotStack[this.snapshotStack.length - 1];
173
+ if (prev) {
174
+ this.state = JSON.parse(JSON.stringify(prev));
175
+ this.notify();
176
+ return true;
177
+ }
178
+ return false;
179
+ }
180
+ canRollback() { return this.snapshotStack.length > 1; }
181
+ async save(slot) {
182
+ await this.saveManager.saveSlot(slot, this.state, this.state.dialogue ? this.state.dialogue.text : '');
183
+ }
184
+ async load(slot) {
185
+ const data = await this.saveManager.loadSlot(slot);
186
+ if (data && data.snapshot) {
187
+ this.state = JSON.parse(JSON.stringify(data.snapshot));
188
+ this.snapshotStack = [this.state];
189
+ this.notify();
190
+ return true;
191
+ }
192
+ return false;
193
+ }
194
+ execute() {
195
+ while (!this.state.isWaitingForInput && !this.state.isFinished) {
196
+ const list = this.story.labels[this.state.currentLabel];
197
+ if (!list || this.state.instructionPointer >= list.length) {
198
+ if (this.state.callStack.length > 0) {
199
+ const frame = this.state.callStack.pop();
200
+ this.state.currentLabel = frame.returnLabel;
201
+ this.state.instructionPointer = frame.returnPointer;
202
+ continue;
203
+ }
204
+ this.state.isFinished = true;
205
+ break;
206
+ }
207
+ const inst = list[this.state.instructionPointer++];
208
+ if (inst.type === 'scene') {
209
+ this.state.visual.background = inst.background;
210
+ this.state.visual.characters = {};
211
+ } else if (inst.type === 'show') {
212
+ this.state.visual.characters[inst.character] = {
213
+ expression: inst.expression,
214
+ position: inst.position || 'center'
215
+ };
216
+ } else if (inst.type === 'hide') {
217
+ delete this.state.visual.characters[inst.character];
218
+ } else if (inst.type === 'dialogue') {
219
+ const charDef = inst.speaker ? this.story.characters[inst.speaker] : null;
220
+ this.state.dialogue = {
221
+ speaker: inst.speaker,
222
+ speakerDisplayName: charDef ? charDef.name : inst.speaker,
223
+ speakerColor: charDef ? charDef.color : null,
224
+ text: inst.text
225
+ };
226
+ this.state.isWaitingForInput = true;
227
+ } else if (inst.type === 'choice') {
228
+ this.state.choices = inst.choices;
229
+ this.state.isWaitingForInput = true;
230
+ } else if (inst.type === 'jump') {
231
+ this.state.currentLabel = inst.targetLabel;
232
+ this.state.instructionPointer = 0;
233
+ } else if (inst.type === 'set') {
234
+ const curr = this.state.variables[inst.variable];
235
+ this.state.variables[inst.variable] = applySetOp(curr, inst.operator, inst.value, this.state.variables);
236
+ } else if (inst.type === 'branch') {
237
+ const ok = evaluateCondition(inst.condition, this.state.variables);
238
+ this.state.currentLabel = ok ? inst.thenLabel : (inst.elseLabel || inst.thenLabel);
239
+ this.state.instructionPointer = 0;
240
+ } else if (inst.type === 'return') {
241
+ this.state.isFinished = true;
242
+ }
243
+ }
244
+ if (this.state.isWaitingForInput) {
245
+ this.snapshotStack.push(JSON.parse(JSON.stringify(this.state)));
246
+ }
247
+ this.notify();
248
+ }
249
+ notify() { for (const l of this.listeners) l(this.state); }
250
+ }
251
+ class DOMRenderer {
252
+ constructor(vm, container) {
253
+ this.vm = vm;
254
+ this.container = container;
255
+ this.build();
256
+ vm.onStateChange(s => this.render(s));
257
+ this.render(vm.getState());
258
+ }
259
+ build() {
260
+ this.container.innerHTML = \`
261
+ <div class="kawa-root">
262
+ <div class="kawa-stage">
263
+ <div class="kawa-background"></div>
264
+ <div class="kawa-characters kawa-sprites"></div>
265
+ <div class="kawa-ui-layer">
266
+ <div class="kawa-choice-container kawa-choices" style="display:none"></div>
267
+ <div class="kawa-dialogue-box kawa-dialogue">
268
+ <div class="kawa-speaker-tag kawa-speaker" style="display:none"></div>
269
+ <div class="kawa-dialogue-text kawa-text"></div>
270
+ <div class="kawa-continue-indicator">&#9660;</div>
271
+ </div>
272
+ <nav class="kawa-quick-menu">
273
+ <button class="kawa-btn kawa-back">Back</button>
274
+ <button class="kawa-btn kawa-save">Save</button>
275
+ <button class="kawa-btn kawa-load">Load</button>
276
+ </nav>
277
+ </div>
278
+ </div>
279
+ </div>\`;
280
+ this.bgEl = this.container.querySelector('.kawa-background');
281
+ this.charsEl = this.container.querySelector('.kawa-characters');
282
+ this.boxEl = this.container.querySelector('.kawa-dialogue-box');
283
+ this.spkEl = this.container.querySelector('.kawa-speaker-tag');
284
+ this.txtEl = this.container.querySelector('.kawa-dialogue-text');
285
+ this.choiceEl = this.container.querySelector('.kawa-choice-container');
286
+ this.backBtn = this.container.querySelector('.kawa-back');
287
+ this.saveBtn = this.container.querySelector('.kawa-save');
288
+ this.loadBtn = this.container.querySelector('.kawa-load');
289
+
290
+ this.boxEl.addEventListener('click', () => this.vm.next());
291
+ this.backBtn.addEventListener('click', (e) => { e.stopPropagation(); this.vm.rollback(); });
292
+ this.saveBtn.addEventListener('click', async (e) => { e.stopPropagation(); await this.vm.save('1'); alert('Saved to Slot 1'); });
293
+ this.loadBtn.addEventListener('click', async (e) => { e.stopPropagation(); if (await this.vm.load('1')) alert('Loaded Slot 1'); });
294
+ window.addEventListener('keydown', (e) => {
295
+ if (e.code === 'Space' || e.code === 'Enter') { e.preventDefault(); this.vm.next(); }
296
+ if (e.code === 'Backspace') { e.preventDefault(); this.vm.rollback(); }
297
+ });
298
+ }
299
+ render(state) {
300
+ this.backBtn.disabled = !this.vm.canRollback();
301
+ if (state.visual.background) {
302
+ const bg = state.visual.background.replace(/^bg\\s+/, '');
303
+ this.bgEl.style.backgroundImage = 'url("./assets/backgrounds/' + bg + (bg.includes('.') ? '' : '.png') + '")';
304
+ this.bgEl.style.opacity = '1';
305
+ } else {
306
+ this.bgEl.style.opacity = '0';
307
+ }
308
+
309
+ this.charsEl.innerHTML = '';
310
+ for (const [id, char] of Object.entries(state.visual.characters)) {
311
+ const div = document.createElement('div');
312
+ div.className = 'kawa-sprite kawa-pos-' + (char.position || 'center');
313
+ const img = document.createElement('img');
314
+ const expr = char.expression ? '/' + char.expression : '';
315
+ img.src = './assets/characters/' + id + expr + '.png';
316
+ img.alt = id;
317
+ img.onerror = () => {
318
+ img.style.display = 'none';
319
+ div.style.width = '200px'; div.style.height = '400px';
320
+ div.style.background = 'rgba(244,63,94,0.3)'; div.style.border = '2px dashed #f43f5e';
321
+ div.style.borderRadius = '16px'; div.style.display = 'flex'; div.style.alignItems = 'center';
322
+ div.style.justifyContent = 'center'; div.style.color = '#fff';
323
+ div.textContent = id + (char.expression ? ' (' + char.expression + ')' : '');
324
+ };
325
+ div.appendChild(img);
326
+ this.charsEl.appendChild(div);
327
+ }
328
+
329
+ if (state.dialogue) {
330
+ this.boxEl.style.display = 'block';
331
+ if (state.dialogue.speakerDisplayName) {
332
+ this.spkEl.style.display = 'inline-block';
333
+ this.spkEl.textContent = state.dialogue.speakerDisplayName;
334
+ if (state.dialogue.speakerColor) this.spkEl.style.backgroundColor = state.dialogue.speakerColor;
335
+ } else {
336
+ this.spkEl.style.display = 'none';
337
+ }
338
+ this.txtEl.textContent = state.dialogue.text;
339
+ } else {
340
+ this.boxEl.style.display = 'none';
341
+ }
342
+
343
+ if (state.choices && state.choices.length > 0) {
344
+ this.choiceEl.innerHTML = '';
345
+ this.choiceEl.style.display = 'flex';
346
+ state.choices.forEach((c, idx) => {
347
+ const btn = document.createElement('button');
348
+ btn.className = 'kawa-choice-btn kawa-choice';
349
+ btn.textContent = c.text;
350
+ btn.addEventListener('click', (e) => { e.stopPropagation(); this.vm.choose(idx); });
351
+ this.choiceEl.appendChild(btn);
352
+ });
353
+ } else {
354
+ this.choiceEl.style.display = 'none';
355
+ }
356
+ }
357
+ }
358
+
359
+ const vm = new StoryVM(story);
360
+ new DOMRenderer(vm, document.getElementById('app'));
361
+ vm.start();
362
+ </script>
363
+ </body>
364
+ </html>`;
365
+ fs.writeFileSync(path.join(outDir, 'index.html'), htmlContent, 'utf-8');
366
+ console.log(`āœ… Static web application generated: dist/index.html`);
367
+ console.log(`\nšŸŽ‰ Production build complete! Ready for GitHub Pages, Netlify, itch.io, etc.\n`);
368
+ return true;
369
+ }
370
+ function copyDirectoryRecursive(src, dest) {
371
+ fs.mkdirSync(dest, { recursive: true });
372
+ const entries = fs.readdirSync(src, { withFileTypes: true });
373
+ for (const entry of entries) {
374
+ const srcPath = path.join(src, entry.name);
375
+ const destPath = path.join(dest, entry.name);
376
+ if (entry.isDirectory()) {
377
+ copyDirectoryRecursive(srcPath, destPath);
378
+ }
379
+ else {
380
+ fs.copyFileSync(srcPath, destPath);
381
+ }
382
+ }
383
+ }
384
+ //# sourceMappingURL=build.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface DevServerOptions {
2
+ port?: number;
3
+ open?: boolean;
4
+ }
5
+ export declare function startDevServer(projectDir?: string, options?: DevServerOptions): void;
6
+ //# sourceMappingURL=dev.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,cAAc,CAAC,UAAU,SAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,IAAI,CAkMrF"}
@@ -0,0 +1,485 @@
1
+ import * as http from 'node:http';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { compileScript, formatDiagnostic, KawaError } from '@kawaijs/parser';
5
+ export function startDevServer(projectDir = '.', options = {}) {
6
+ const rootDir = path.resolve(process.cwd(), projectDir);
7
+ const scriptPath = path.join(rootDir, 'game', 'script.kawa');
8
+ const stylePath = path.join(rootDir, 'game', 'style.css');
9
+ const assetsDir = path.join(rootDir, 'game', 'assets');
10
+ let port = options.port ?? 3000;
11
+ if (!fs.existsSync(scriptPath)) {
12
+ console.error(`āŒ Error: Cannot find '${scriptPath}'. Make sure you are inside a Kawaijs project directory.`);
13
+ return;
14
+ }
15
+ const clients = new Set();
16
+ // File watcher for auto-reload
17
+ const gameDir = path.join(rootDir, 'game');
18
+ if (fs.existsSync(gameDir)) {
19
+ fs.watch(gameDir, { recursive: true }, (_eventType, filename) => {
20
+ if (filename && (filename.endsWith('.kawa') || filename.endsWith('.css') || filename.startsWith('assets'))) {
21
+ console.log(`šŸ”„ [Kawa Dev] File changed: ${filename}. Reloading...`);
22
+ for (const client of clients) {
23
+ client.write(`data: reload\n\n`);
24
+ }
25
+ }
26
+ });
27
+ }
28
+ const server = http.createServer((req, res) => {
29
+ const url = req.url ?? '/';
30
+ // 1. SSE Live Reload Endpoint
31
+ if (url === '/__kawa_reload') {
32
+ res.writeHead(200, {
33
+ 'Content-Type': 'text/event-stream',
34
+ 'Cache-Control': 'no-cache',
35
+ 'Connection': 'keep-alive',
36
+ 'Access-Control-Allow-Origin': '*'
37
+ });
38
+ clients.add(res);
39
+ req.on('close', () => clients.delete(res));
40
+ return;
41
+ }
42
+ // 2. Dynamic Story JSON API
43
+ if (url === '/api/story.json') {
44
+ try {
45
+ const source = fs.readFileSync(scriptPath, 'utf-8');
46
+ const story = compileScript(source, path.basename(scriptPath));
47
+ res.writeHead(200, { 'Content-Type': 'application/json' });
48
+ res.end(JSON.stringify(story));
49
+ }
50
+ catch (err) {
51
+ res.writeHead(500, { 'Content-Type': 'application/json' });
52
+ let errMsg = 'Compilation Error';
53
+ if (err instanceof KawaError) {
54
+ const source = fs.readFileSync(scriptPath, 'utf-8');
55
+ errMsg = formatDiagnostic(err.diagnostic, source);
56
+ }
57
+ else if (err instanceof Error) {
58
+ errMsg = err.message;
59
+ }
60
+ res.end(JSON.stringify({ error: errMsg }));
61
+ }
62
+ return;
63
+ }
64
+ // 3. User & Default Stylesheet
65
+ if (url === '/style.css') {
66
+ res.writeHead(200, { 'Content-Type': 'text/css' });
67
+ let combinedCss = `/* Kawaijs Base Theme */\n`;
68
+ // Load default renderer theme CSS
69
+ const themeCssPath = path.resolve(path.dirname(import.meta.url.replace('file:///', '')), '..', '..', '..', 'renderer-dom', 'src', 'theme.css');
70
+ if (fs.existsSync(themeCssPath)) {
71
+ combinedCss += fs.readFileSync(themeCssPath, 'utf-8') + '\n';
72
+ }
73
+ if (fs.existsSync(stylePath)) {
74
+ combinedCss += `/* User Custom Styles */\n` + fs.readFileSync(stylePath, 'utf-8');
75
+ }
76
+ res.end(combinedCss);
77
+ return;
78
+ }
79
+ // 4. Game Assets (/assets/*)
80
+ if (url.startsWith('/assets/')) {
81
+ const relPath = decodeURIComponent(url.replace('/assets/', ''));
82
+ let filePath = path.join(assetsDir, relPath);
83
+ if (!fs.existsSync(filePath)) {
84
+ // Try fallback extensions (.svg, .png, .webp, .jpg, .jpeg, .mp3, .ogg)
85
+ const parsed = path.parse(filePath);
86
+ for (const ext of ['.svg', '.png', '.webp', '.jpg', '.jpeg', '.mp3', '.ogg']) {
87
+ const candidate = path.join(parsed.dir, parsed.name + ext);
88
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
89
+ filePath = candidate;
90
+ break;
91
+ }
92
+ }
93
+ }
94
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
95
+ const ext = path.extname(filePath).toLowerCase();
96
+ const mimeTypes = {
97
+ '.png': 'image/png',
98
+ '.jpg': 'image/jpeg',
99
+ '.jpeg': 'image/jpeg',
100
+ '.webp': 'image/webp',
101
+ '.svg': 'image/svg+xml',
102
+ '.mp3': 'audio/mpeg',
103
+ '.ogg': 'audio/ogg',
104
+ '.wav': 'audio/wav'
105
+ };
106
+ res.writeHead(200, { 'Content-Type': mimeTypes[ext] ?? 'application/octet-stream' });
107
+ fs.createReadStream(filePath).pipe(res);
108
+ return;
109
+ }
110
+ else {
111
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
112
+ res.end('Asset not found');
113
+ return;
114
+ }
115
+ }
116
+ // 5. HTML Shell & Web Runtime
117
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
118
+ res.end(`<!DOCTYPE html>
119
+ <html lang="en">
120
+ <head>
121
+ <meta charset="UTF-8">
122
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
123
+ <title>Kawaijs Visual Novel</title>
124
+ <link rel="stylesheet" href="/style.css">
125
+ <style>
126
+ body { margin: 0; padding: 0; background: #000; overflow: hidden; }
127
+ #error-overlay {
128
+ display: none; position: fixed; inset: 0; background: rgba(15, 23, 42, 0.95);
129
+ color: #f43f5e; font-family: monospace; padding: 32px; z-index: 9999;
130
+ white-space: pre-wrap; font-size: 1.1rem; line-height: 1.5;
131
+ }
132
+ </style>
133
+ </head>
134
+ <body>
135
+ <div id="error-overlay"></div>
136
+ <div id="app"></div>
137
+
138
+ <script type="module">
139
+ // Live Reload Connection
140
+ const sse = new EventSource('/__kawa_reload');
141
+ sse.onmessage = (e) => {
142
+ if (e.data === 'reload') window.location.reload();
143
+ };
144
+
145
+ // Load story and start game
146
+ async function init() {
147
+ const errorEl = document.getElementById('error-overlay');
148
+ try {
149
+ const res = await fetch('/api/story.json');
150
+ const story = await res.json();
151
+ if (story.error) {
152
+ errorEl.style.display = 'block';
153
+ errorEl.textContent = story.error;
154
+ return;
155
+ }
156
+
157
+ // Inline runtime VM + DOM Renderer
158
+ ${getInlineRuntimeScript()}
159
+
160
+ window.__kawa_app = mountKawaApp(story, document.getElementById('app'));
161
+ } catch (err) {
162
+ errorEl.style.display = 'block';
163
+ errorEl.textContent = err.stack || err.message;
164
+ }
165
+ }
166
+
167
+ init();
168
+ </script>
169
+ </body>
170
+ </html>`);
171
+ });
172
+ server.on('error', (e) => {
173
+ if (e.code === 'EADDRINUSE') {
174
+ console.log(`Port ${port} is in use, trying ${port + 1}...`);
175
+ port += 1;
176
+ server.listen(port);
177
+ }
178
+ else {
179
+ console.error('Server error:', e);
180
+ }
181
+ });
182
+ server.listen(port, () => {
183
+ console.log(`\n🌸 Kawaijs Dev Server running at:`);
184
+ console.log(` > Local: \x1b[36mhttp://localhost:${port}\x1b[0m`);
185
+ console.log(` > Project: ${rootDir}`);
186
+ console.log(` > Watching: game/script.kawa, game/style.css, game/assets/\n`);
187
+ });
188
+ }
189
+ function getInlineRuntimeScript() {
190
+ return `
191
+ class MemoryStorageAdapter {
192
+ constructor() { this.store = new Map(); }
193
+ getItem(k) { return this.store.get(k) || null; }
194
+ setItem(k, v) { this.store.set(k, v); }
195
+ removeItem(k) { this.store.delete(k); }
196
+ }
197
+ class LocalStorageAdapter {
198
+ getItem(k) { return localStorage.getItem(k); }
199
+ setItem(k, v) { localStorage.setItem(k, v); }
200
+ removeItem(k) { localStorage.removeItem(k); }
201
+ }
202
+ class SaveManager {
203
+ constructor() { this.storage = typeof localStorage !== 'undefined' ? new LocalStorageAdapter() : new MemoryStorageAdapter(); }
204
+ async saveSlot(id, snapshot, previewText) {
205
+ const slot = { id, name: 'Slot ' + id, timestamp: Date.now(), snapshot, previewText };
206
+ this.storage.setItem('kawaijs_save_' + id, JSON.stringify(slot));
207
+ return slot;
208
+ }
209
+ async loadSlot(id) {
210
+ const raw = this.storage.getItem('kawaijs_save_' + id);
211
+ return raw ? JSON.parse(raw) : null;
212
+ }
213
+ }
214
+ function evaluateCondition(cond, vars) {
215
+ const t = (cond || '').trim();
216
+ if (!t || t === 'true') return true;
217
+ if (t === 'false') return false;
218
+ const ops = ['>=', '<=', '!=', '==', '>', '<'];
219
+ for (const op of ops) {
220
+ const idx = t.indexOf(op);
221
+ if (idx !== -1) {
222
+ const l = resolveVal(t.slice(0, idx), vars);
223
+ const r = resolveVal(t.slice(idx + op.length), vars);
224
+ if (op === '>=') return Number(l) >= Number(r);
225
+ if (op === '<=') return Number(l) <= Number(r);
226
+ if (op === '>') return Number(l) > Number(r);
227
+ if (op === '<') return Number(l) < Number(r);
228
+ if (op === '==') return l == r;
229
+ if (op === '!=') return l != r;
230
+ }
231
+ }
232
+ if (t.startsWith('!')) return !Boolean(vars[t.slice(1).trim()]);
233
+ return Boolean(vars[t]);
234
+ }
235
+ function resolveVal(token, vars) {
236
+ const t = token.trim();
237
+ if (t === 'true') return true;
238
+ if (t === 'false') return false;
239
+ if (!isNaN(Number(t)) && t !== '') return Number(t);
240
+ if ((t.startsWith('"') && t.endsWith('"')) || (t.startsWith("'") && t.endsWith("'"))) return t.slice(1, -1);
241
+ if (t in vars) return vars[t];
242
+ return t;
243
+ }
244
+ function applySetOp(curr, op, val, vars) {
245
+ const res = (typeof val === 'string' && val in vars) ? vars[val] : val;
246
+ if (op === '+=') return Number(curr || 0) + Number(res);
247
+ if (op === '-=') return Number(curr || 0) - Number(res);
248
+ return res;
249
+ }
250
+ class StoryVM {
251
+ constructor(story) {
252
+ this.story = story;
253
+ this.state = {
254
+ currentLabel: story.meta.startLabel || 'start',
255
+ instructionPointer: 0,
256
+ callStack: [],
257
+ variables: {},
258
+ visual: { background: null, transition: null, characters: {} },
259
+ audio: { music: null, voice: null },
260
+ dialogue: null,
261
+ choices: null,
262
+ isWaitingForInput: false,
263
+ isFinished: false
264
+ };
265
+ this.snapshotStack = [];
266
+ this.listeners = new Set();
267
+ this.history = [];
268
+ this.saveManager = new SaveManager();
269
+ }
270
+ getState() { return this.state; }
271
+ onStateChange(cb) { this.listeners.add(cb); return () => this.listeners.delete(cb); }
272
+ start() { this.execute(); }
273
+ next() {
274
+ if (this.state.isFinished || (this.state.choices && this.state.choices.length > 0)) return;
275
+ this.state.isWaitingForInput = false;
276
+ this.execute();
277
+ }
278
+ choose(idx) {
279
+ if (!this.state.choices || !this.state.choices[idx]) return;
280
+ const choice = this.state.choices[idx];
281
+ this.state.choices = null;
282
+ this.state.isWaitingForInput = false;
283
+ this.state.currentLabel = choice.targetLabel;
284
+ this.state.instructionPointer = 0;
285
+ this.execute();
286
+ }
287
+ rollback() {
288
+ if (this.snapshotStack.length <= 1) return false;
289
+ this.snapshotStack.pop();
290
+ const prev = this.snapshotStack[this.snapshotStack.length - 1];
291
+ if (prev) {
292
+ this.state = JSON.parse(JSON.stringify(prev));
293
+ this.notify();
294
+ return true;
295
+ }
296
+ return false;
297
+ }
298
+ canRollback() { return this.snapshotStack.length > 1; }
299
+ async save(slot) {
300
+ await this.saveManager.saveSlot(slot, this.state, this.state.dialogue ? this.state.dialogue.text : '');
301
+ }
302
+ async load(slot) {
303
+ const data = await this.saveManager.loadSlot(slot);
304
+ if (data && data.snapshot) {
305
+ this.state = JSON.parse(JSON.stringify(data.snapshot));
306
+ this.snapshotStack = [this.state];
307
+ this.notify();
308
+ return true;
309
+ }
310
+ return false;
311
+ }
312
+ execute() {
313
+ while (!this.state.isWaitingForInput && !this.state.isFinished) {
314
+ const list = this.story.labels[this.state.currentLabel];
315
+ if (!list || this.state.instructionPointer >= list.length) {
316
+ if (this.state.callStack.length > 0) {
317
+ const frame = this.state.callStack.pop();
318
+ this.state.currentLabel = frame.returnLabel;
319
+ this.state.instructionPointer = frame.returnPointer;
320
+ continue;
321
+ }
322
+ this.state.isFinished = true;
323
+ break;
324
+ }
325
+ const inst = list[this.state.instructionPointer++];
326
+ if (inst.type === 'scene') {
327
+ this.state.visual.background = inst.background;
328
+ this.state.visual.characters = {};
329
+ } else if (inst.type === 'show') {
330
+ this.state.visual.characters[inst.character] = {
331
+ expression: inst.expression,
332
+ position: inst.position || 'center'
333
+ };
334
+ } else if (inst.type === 'hide') {
335
+ delete this.state.visual.characters[inst.character];
336
+ } else if (inst.type === 'dialogue') {
337
+ const charDef = inst.speaker ? this.story.characters[inst.speaker] : null;
338
+ this.state.dialogue = {
339
+ speaker: inst.speaker,
340
+ speakerDisplayName: charDef ? charDef.name : inst.speaker,
341
+ speakerColor: charDef ? charDef.color : null,
342
+ text: inst.text
343
+ };
344
+ this.state.isWaitingForInput = true;
345
+ this.history.push(this.state.dialogue);
346
+ } else if (inst.type === 'choice') {
347
+ this.state.choices = inst.choices;
348
+ this.state.isWaitingForInput = true;
349
+ } else if (inst.type === 'jump') {
350
+ this.state.currentLabel = inst.targetLabel;
351
+ this.state.instructionPointer = 0;
352
+ } else if (inst.type === 'set') {
353
+ const curr = this.state.variables[inst.variable];
354
+ this.state.variables[inst.variable] = applySetOp(curr, inst.operator, inst.value, this.state.variables);
355
+ } else if (inst.type === 'branch') {
356
+ const ok = evaluateCondition(inst.condition, this.state.variables);
357
+ this.state.currentLabel = ok ? inst.thenLabel : (inst.elseLabel || inst.thenLabel);
358
+ this.state.instructionPointer = 0;
359
+ } else if (inst.type === 'return') {
360
+ this.state.isFinished = true;
361
+ }
362
+ }
363
+ if (this.state.isWaitingForInput) {
364
+ this.snapshotStack.push(JSON.parse(JSON.stringify(this.state)));
365
+ }
366
+ this.notify();
367
+ }
368
+ notify() { for (const l of this.listeners) l(this.state); }
369
+ }
370
+ class DOMRenderer {
371
+ constructor(vm, container) {
372
+ this.vm = vm;
373
+ this.container = container;
374
+ this.build();
375
+ vm.onStateChange(s => this.render(s));
376
+ this.render(vm.getState());
377
+ }
378
+ build() {
379
+ this.container.innerHTML = \`
380
+ <div class="kawa-root">
381
+ <div class="kawa-stage">
382
+ <div class="kawa-background"></div>
383
+ <div class="kawa-characters kawa-sprites"></div>
384
+ <div class="kawa-ui-layer">
385
+ <div class="kawa-choice-container kawa-choices" style="display:none"></div>
386
+ <div class="kawa-dialogue-box kawa-dialogue">
387
+ <div class="kawa-speaker-tag kawa-speaker" style="display:none"></div>
388
+ <div class="kawa-dialogue-text kawa-text"></div>
389
+ <div class="kawa-continue-indicator">&#9660;</div>
390
+ </div>
391
+ <nav class="kawa-quick-menu">
392
+ <button class="kawa-btn kawa-back">Back</button>
393
+ <button class="kawa-btn kawa-save">Save</button>
394
+ <button class="kawa-btn kawa-load">Load</button>
395
+ </nav>
396
+ </div>
397
+ </div>
398
+ </div>\`;
399
+ this.bgEl = this.container.querySelector('.kawa-background');
400
+ this.charsEl = this.container.querySelector('.kawa-characters');
401
+ this.boxEl = this.container.querySelector('.kawa-dialogue-box');
402
+ this.spkEl = this.container.querySelector('.kawa-speaker-tag');
403
+ this.txtEl = this.container.querySelector('.kawa-dialogue-text');
404
+ this.choiceEl = this.container.querySelector('.kawa-choice-container');
405
+ this.backBtn = this.container.querySelector('.kawa-back');
406
+ this.saveBtn = this.container.querySelector('.kawa-save');
407
+ this.loadBtn = this.container.querySelector('.kawa-load');
408
+
409
+ this.boxEl.addEventListener('click', () => this.vm.next());
410
+ this.backBtn.addEventListener('click', (e) => { e.stopPropagation(); this.vm.rollback(); });
411
+ this.saveBtn.addEventListener('click', async (e) => { e.stopPropagation(); await this.vm.save('1'); alert('Saved to Slot 1'); });
412
+ this.loadBtn.addEventListener('click', async (e) => { e.stopPropagation(); if (await this.vm.load('1')) alert('Loaded Slot 1'); });
413
+ window.addEventListener('keydown', (e) => {
414
+ if (e.code === 'Space' || e.code === 'Enter') { e.preventDefault(); this.vm.next(); }
415
+ if (e.code === 'Backspace') { e.preventDefault(); this.vm.rollback(); }
416
+ });
417
+ }
418
+ render(state) {
419
+ this.backBtn.disabled = !this.vm.canRollback();
420
+ if (state.visual.background) {
421
+ const bg = state.visual.background.replace(/^bg\\s+/, '');
422
+ this.bgEl.style.backgroundImage = 'url("/assets/backgrounds/' + bg + (bg.includes('.') ? '' : '.png') + '")';
423
+ this.bgEl.style.opacity = '1';
424
+ } else {
425
+ this.bgEl.style.opacity = '0';
426
+ }
427
+
428
+ this.charsEl.innerHTML = '';
429
+ for (const [id, char] of Object.entries(state.visual.characters)) {
430
+ const div = document.createElement('div');
431
+ div.className = 'kawa-sprite kawa-pos-' + (char.position || 'center');
432
+ const img = document.createElement('img');
433
+ const expr = char.expression ? '/' + char.expression : '';
434
+ img.src = '/assets/characters/' + id + expr + '.png';
435
+ img.alt = id;
436
+ img.onerror = () => {
437
+ img.style.display = 'none';
438
+ div.style.width = '200px'; div.style.height = '400px';
439
+ div.style.background = 'rgba(244,63,94,0.3)'; div.style.border = '2px dashed #f43f5e';
440
+ div.style.borderRadius = '16px'; div.style.display = 'flex'; div.style.alignItems = 'center';
441
+ div.style.justifyContent = 'center'; div.style.color = '#fff';
442
+ div.textContent = id + (char.expression ? ' (' + char.expression + ')' : '');
443
+ };
444
+ div.appendChild(img);
445
+ this.charsEl.appendChild(div);
446
+ }
447
+
448
+ if (state.dialogue) {
449
+ this.boxEl.style.display = 'block';
450
+ if (state.dialogue.speakerDisplayName) {
451
+ this.spkEl.style.display = 'inline-block';
452
+ this.spkEl.textContent = state.dialogue.speakerDisplayName;
453
+ if (state.dialogue.speakerColor) this.spkEl.style.backgroundColor = state.dialogue.speakerColor;
454
+ } else {
455
+ this.spkEl.style.display = 'none';
456
+ }
457
+ this.txtEl.textContent = state.dialogue.text;
458
+ } else {
459
+ this.boxEl.style.display = 'none';
460
+ }
461
+
462
+ if (state.choices && state.choices.length > 0) {
463
+ this.choiceEl.innerHTML = '';
464
+ this.choiceEl.style.display = 'flex';
465
+ state.choices.forEach((c, idx) => {
466
+ const btn = document.createElement('button');
467
+ btn.className = 'kawa-choice-btn kawa-choice';
468
+ btn.textContent = c.text;
469
+ btn.addEventListener('click', (e) => { e.stopPropagation(); this.vm.choose(idx); });
470
+ this.choiceEl.appendChild(btn);
471
+ });
472
+ } else {
473
+ this.choiceEl.style.display = 'none';
474
+ }
475
+ }
476
+ }
477
+ function mountKawaApp(story, container) {
478
+ const vm = new StoryVM(story);
479
+ const renderer = new DOMRenderer(vm, container);
480
+ vm.start();
481
+ return { vm, renderer };
482
+ }
483
+ `;
484
+ }
485
+ //# sourceMappingURL=dev.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,8 @@ export * from '@kawaijs/runtime';
4
4
  export * from '@kawaijs/renderer-dom';
5
5
  import { createProject } from './commands/create.js';
6
6
  import { validateProject } from './commands/validate.js';
7
- export { createProject, validateProject };
7
+ import { startDevServer } from './commands/dev.js';
8
+ import { buildProject } from './commands/build.js';
9
+ export { createProject, validateProject, startDevServer, buildProject };
8
10
  export declare function runCLI(args: string[]): void;
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC;AAE1C,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAqD3C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAExE,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAoE3C"}
package/dist/index.js CHANGED
@@ -4,7 +4,9 @@ export * from '@kawaijs/runtime';
4
4
  export * from '@kawaijs/renderer-dom';
5
5
  import { createProject } from './commands/create.js';
6
6
  import { validateProject } from './commands/validate.js';
7
- export { createProject, validateProject };
7
+ import { startDevServer } from './commands/dev.js';
8
+ import { buildProject } from './commands/build.js';
9
+ export { createProject, validateProject, startDevServer, buildProject };
8
10
  export function runCLI(args) {
9
11
  const command = args[0];
10
12
  switch (command) {
@@ -13,6 +15,19 @@ export function runCLI(args) {
13
15
  createProject(projectName);
14
16
  break;
15
17
  }
18
+ case 'dev': {
19
+ const targetPath = args[1] ?? '.';
20
+ startDevServer(targetPath);
21
+ break;
22
+ }
23
+ case 'build': {
24
+ const targetPath = args[1] ?? '.';
25
+ const ok = buildProject(targetPath);
26
+ if (!ok) {
27
+ process.exitCode = 1;
28
+ }
29
+ break;
30
+ }
16
31
  case 'validate': {
17
32
  const targetPath = args[1] ?? '.';
18
33
  const ok = validateProject(targetPath);
@@ -24,7 +39,7 @@ export function runCLI(args) {
24
39
  case 'version':
25
40
  case '-v':
26
41
  case '--version': {
27
- console.log('Kawaijs v0.1.0');
42
+ console.log('Kawaijs v0.1.1');
28
43
  break;
29
44
  }
30
45
  case 'help':
@@ -40,16 +55,16 @@ Usage:
40
55
 
41
56
  Commands:
42
57
  create <name> Scaffold a new visual novel project
58
+ dev [path] Start the local development server (with live reload)
59
+ build [path] Build a static production web bundle (dist/)
43
60
  validate [path] Validate Kawa Script syntax, labels, and links
44
- dev Start the local development server (with HMR)
45
- build Build a static production web bundle
46
61
  help Show this help message
47
62
  version Show version information
48
63
 
49
64
  Example:
50
65
  kawa create my-novel
51
66
  cd my-novel
52
- kawa validate
67
+ kawa dev
53
68
  `);
54
69
  break;
55
70
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,CAAC;AAE1C,MAAM,UAAU,MAAM,CAAC,IAAc;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;YAC1C,aAAa,CAAC,WAAW,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;QAED,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAClC,MAAM,EAAE,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACvC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,MAAM;QACR,CAAC;QAED,KAAK,SAAS,CAAC;QACf,KAAK,IAAI,CAAC;QACV,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC9B,MAAM;QACR,CAAC;QAED,KAAK,MAAM,CAAC;QACZ,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ,CAAC;QACd,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;CAmBjB,CAAC,CAAC;YACG,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AAEtC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC;AAExE,MAAM,UAAU,MAAM,CAAC,IAAc;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC;YAC1C,aAAa,CAAC,WAAW,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;QAED,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAClC,cAAc,CAAC,UAAU,CAAC,CAAC;YAC3B,MAAM;QACR,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAClC,MAAM,EAAE,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;YACpC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,MAAM;QACR,CAAC;QAED,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAClC,MAAM,EAAE,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YACvC,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvB,CAAC;YACD,MAAM;QACR,CAAC;QAED,KAAK,SAAS,CAAC;QACf,KAAK,IAAI,CAAC;QACV,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC9B,MAAM;QACR,CAAC;QAED,KAAK,MAAM,CAAC;QACZ,KAAK,IAAI,CAAC;QACV,KAAK,QAAQ,CAAC;QACd,OAAO,CAAC,CAAC,CAAC;YACR,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;CAmBjB,CAAC,CAAC;YACG,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kawaijs",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Web-native visual novel engine and toolchain inspired by Ren'Py",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -31,10 +31,10 @@
31
31
  "typecheck": "tsc --noEmit"
32
32
  },
33
33
  "dependencies": {
34
- "@kawaijs/ast": "^0.1.0",
35
- "@kawaijs/parser": "^0.1.0",
36
- "@kawaijs/runtime": "^0.1.0",
37
- "@kawaijs/renderer-dom": "^0.1.0"
34
+ "@kawaijs/ast": "^0.1.2",
35
+ "@kawaijs/parser": "^0.1.2",
36
+ "@kawaijs/runtime": "^0.1.2",
37
+ "@kawaijs/renderer-dom": "^0.1.2"
38
38
  },
39
39
  "keywords": [
40
40
  "kawaijs",