wasm-idle 0.2.5 → 0.3.1

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.
Files changed (54) hide show
  1. package/dist/clang/app.d.ts +44 -0
  2. package/dist/clang/app.js +270 -2
  3. package/dist/clang/index.d.ts +40 -9
  4. package/dist/clang/index.js +603 -15
  5. package/dist/clang/memory/memFs.d.ts +3 -1
  6. package/dist/clang/memory/memFs.js +12 -1
  7. package/dist/clang/memory/memory.d.ts +8 -4
  8. package/dist/clang/memory/memory.js +14 -0
  9. package/dist/clang/memory/tar.d.ts +1 -1
  10. package/dist/clang/memory/tar.js +1 -1
  11. package/dist/clang/wasm.d.ts +1 -1
  12. package/dist/clang/wasm.js +13 -4
  13. package/dist/clangd/config.d.ts +18 -0
  14. package/dist/clangd/config.js +14 -0
  15. package/dist/clangd/jsonStream.d.ts +9 -0
  16. package/dist/clangd/jsonStream.js +48 -0
  17. package/dist/clangd/session.d.ts +14 -0
  18. package/dist/clangd/session.js +94 -0
  19. package/dist/clangd/worker.d.ts +1 -0
  20. package/dist/clangd/worker.js +130 -0
  21. package/dist/debug/editor/index.d.ts +1 -0
  22. package/dist/debug/editor/index.js +1 -0
  23. package/dist/debug/editor/monaco.d.ts +18 -0
  24. package/dist/debug/editor/monaco.js +105 -0
  25. package/dist/debug/expression.d.ts +2 -0
  26. package/dist/debug/expression.js +262 -0
  27. package/dist/debug/index.d.ts +5 -0
  28. package/dist/debug/index.js +4 -0
  29. package/dist/debug/language/cpp.d.ts +2 -0
  30. package/dist/debug/language/cpp.js +7 -0
  31. package/dist/debug/language/index.d.ts +2 -0
  32. package/dist/debug/language/index.js +1 -0
  33. package/dist/debug/language/types.d.ts +6 -0
  34. package/dist/debug/language/types.js +1 -0
  35. package/dist/debug/locals.d.ts +2 -0
  36. package/dist/debug/locals.js +8 -0
  37. package/dist/index.d.ts +3 -0
  38. package/dist/index.js +1 -0
  39. package/dist/playground/clang.d.ts +8 -2
  40. package/dist/playground/clang.js +25 -4
  41. package/dist/playground/options.d.ts +39 -0
  42. package/dist/playground/options.js +1 -0
  43. package/dist/playground/python.d.ts +10 -2
  44. package/dist/playground/python.js +6 -3
  45. package/dist/playground/sandbox.d.ts +15 -2
  46. package/dist/playground/worker/clang.js +21 -4
  47. package/dist/playground/worker/python.js +196 -3
  48. package/dist/terminal/Terminal.svelte +35 -11
  49. package/dist/terminal/Terminal.svelte.d.ts +12 -9
  50. package/dist/terminal/index.d.ts +2 -0
  51. package/dist/terminal/theme.js +2 -2
  52. package/dist/terminal/types.d.ts +13 -0
  53. package/dist/terminal/types.js +1 -0
  54. package/package.json +42 -33
@@ -1,12 +1,25 @@
1
+ import type { DebugCommand, DebugSessionEvent, SandboxExecutionOptions } from './options';
2
+ import type { Writable } from 'svelte/store';
3
+ type ProgressLike = Writable<number> | {
4
+ set?: (value: number) => void;
5
+ };
1
6
  export interface Sandbox {
2
7
  constructor: any;
3
8
  eof: () => void;
4
- load: (path: string, code?: string, log?: boolean) => Promise<void>;
5
- run: (code: string, prepare: boolean, log?: boolean) => Promise<string>;
9
+ load: (path: string, code?: string, log?: boolean, args?: string[], options?: SandboxExecutionOptions) => Promise<void>;
10
+ run: (code: string, prepare: boolean, log?: boolean, prog?: ProgressLike, args?: string[], options?: SandboxExecutionOptions) => Promise<boolean | string>;
6
11
  terminate: () => void;
7
12
  clear: () => Promise<void>;
8
13
  kill?: () => void;
9
14
  write?: (data: string) => void;
10
15
  output?: (data: string) => void;
16
+ ondebug?: (event: DebugSessionEvent) => void;
17
+ debugCommand?: (command: DebugCommand) => void;
18
+ image?: (data: {
19
+ mime: string;
20
+ b64: string;
21
+ ts?: number;
22
+ }) => void;
11
23
  elapse?: number;
12
24
  }
25
+ export {};
@@ -3,11 +3,12 @@ self.document = {
3
3
  return [];
4
4
  }
5
5
  };
6
- let stdinBufferClang, interruptBufferClang, clang;
6
+ let stdinBufferClang, debugBufferClang, interruptBufferClang, clang;
7
7
  async function loadClang(path, log) {
8
8
  const { default: Clang } = await import('../../clang');
9
9
  clang = new Clang({
10
10
  stdout: (output) => postMessage({ output }),
11
+ onDebugEvent: (debugEvent) => postMessage({ debugEvent }),
11
12
  stdin: () => {
12
13
  while (true) {
13
14
  postMessage({ buffer: true });
@@ -33,16 +34,24 @@ async function loadClang(path, log) {
33
34
  });
34
35
  }
35
36
  self.onmessage = async (event) => {
36
- const { code, buffer, load, interrupt, log, path, prepare, args } = event.data;
37
+ const { code, buffer, debugBuffer, load, interrupt, log, path, prepare, args, debug, breakpoints, pauseOnEntry } = event.data;
37
38
  if (load) {
38
39
  await loadClang(path, log);
39
40
  postMessage({ load: true });
40
41
  }
41
42
  else if (prepare) {
42
43
  stdinBufferClang = new Int32Array(buffer);
44
+ debugBufferClang = new Int32Array(debugBuffer);
43
45
  interruptBufferClang = new Uint8Array(interrupt);
44
46
  try {
45
- await clang.compileLink(code, { args });
47
+ await clang.compileLink(code, {
48
+ args,
49
+ debug,
50
+ breakpoints,
51
+ pauseOnEntry,
52
+ debugBuffer: debugBufferClang,
53
+ interruptBuffer: interruptBufferClang
54
+ });
46
55
  self.postMessage({ results: true });
47
56
  }
48
57
  catch (error) {
@@ -52,9 +61,17 @@ self.onmessage = async (event) => {
52
61
  else if (code) {
53
62
  clang.log = log;
54
63
  stdinBufferClang = new Int32Array(buffer);
64
+ debugBufferClang = new Int32Array(debugBuffer);
55
65
  interruptBufferClang = new Uint8Array(interrupt);
56
66
  try {
57
- await clang.compileLinkRun(code, { args });
67
+ await clang.compileLinkRun(code, {
68
+ args,
69
+ debug,
70
+ breakpoints,
71
+ pauseOnEntry,
72
+ debugBuffer: debugBufferClang,
73
+ interruptBuffer: interruptBufferClang
74
+ });
58
75
  self.postMessage({ results: true });
59
76
  }
60
77
  catch (error) {
@@ -6,12 +6,200 @@ self.document = {
6
6
  return [];
7
7
  }
8
8
  };
9
- let stdinBufferPyodide, interruptBufferPyodide, pyodide, path = '';
9
+ let stdinBufferPyodide, interruptBufferPyodide, pyodide, path = '', packageBaseUrl = '';
10
+ let jungolRobotReady = false;
11
+ const imageHook = `
12
+ if not globals().get("__wasm_idle_img_inited__", False):
13
+ globals()["__wasm_idle_img_inited__"] = True
14
+ import base64, io, time
15
+ try:
16
+ from js import postMessage
17
+ except Exception:
18
+ postMessage = None
19
+ _MAX_WIDTH = 1280
20
+ _MAX_HEIGHT = 720
21
+ _WEBP_QUALITY = 85
22
+ try:
23
+ from PIL import Image
24
+ _RESAMPLE = Image.Resampling.LANCZOS if hasattr(Image, "Resampling") else Image.LANCZOS
25
+ except Exception:
26
+ Image = None
27
+ _RESAMPLE = None
28
+
29
+ def __wasm_idle_rasterize_svg(raw):
30
+ try:
31
+ import cairosvg
32
+ return cairosvg.svg2png(bytestring=raw)
33
+ except Exception:
34
+ return None
35
+
36
+ def __wasm_idle_to_webp(raw):
37
+ if Image is None or _RESAMPLE is None:
38
+ return None
39
+ try:
40
+ img = Image.open(io.BytesIO(raw))
41
+ img.load()
42
+ if _MAX_WIDTH > 0 and _MAX_HEIGHT > 0:
43
+ img.thumbnail((_MAX_WIDTH, _MAX_HEIGHT), _RESAMPLE)
44
+ if img.mode not in ("RGB", "RGBA"):
45
+ img = img.convert("RGBA" if "A" in img.mode else "RGB")
46
+ buf = io.BytesIO()
47
+ img.save(buf, format="WEBP", quality=_WEBP_QUALITY, method=6)
48
+ return buf.getvalue()
49
+ except Exception:
50
+ return None
51
+
52
+ def __wasm_idle_send_img(mime, raw):
53
+ try:
54
+ if postMessage is None:
55
+ return
56
+ if raw is None:
57
+ return
58
+ if isinstance(raw, str):
59
+ raw_bytes = raw.encode("utf-8")
60
+ else:
61
+ raw_bytes = raw
62
+ if mime == "image/svg+xml":
63
+ raster = __wasm_idle_rasterize_svg(raw_bytes)
64
+ if raster:
65
+ raw_bytes = raster
66
+ mime = "image/png"
67
+ webp = __wasm_idle_to_webp(raw_bytes)
68
+ if webp:
69
+ raw_bytes = webp
70
+ mime = "image/webp"
71
+ b64 = base64.b64encode(raw_bytes).decode("ascii")
72
+ ts = int(time.time() * 1000)
73
+ postMessage({"type": "img", "data": {"mime": mime, "b64": b64, "ts": ts}})
74
+ except Exception:
75
+ pass
76
+
77
+ def __wasm_idle_capture_fig(fig):
78
+ try:
79
+ buf = io.BytesIO()
80
+ fig.savefig(buf, format="png", bbox_inches="tight")
81
+ __wasm_idle_send_img("image/png", buf.getvalue())
82
+ buf.close()
83
+ except Exception:
84
+ pass
85
+
86
+ try:
87
+ import matplotlib
88
+ matplotlib.use("Agg")
89
+ import matplotlib.pyplot as plt
90
+ from matplotlib.figure import Figure
91
+ _orig_show = plt.show
92
+
93
+ def _show(*args, **kwargs):
94
+ try:
95
+ figs = [plt.figure(num) for num in plt.get_fignums()]
96
+ if not figs:
97
+ figs = [plt.gcf()]
98
+ for fig in figs:
99
+ __wasm_idle_capture_fig(fig)
100
+ plt.close("all")
101
+ except Exception:
102
+ pass
103
+ try:
104
+ return _orig_show(*args, **kwargs)
105
+ except Exception:
106
+ return None
107
+
108
+ plt.show = _show
109
+
110
+ _orig_fig_show = Figure.show
111
+
112
+ def _fig_show(self, *args, **kwargs):
113
+ try:
114
+ __wasm_idle_capture_fig(self)
115
+ except Exception:
116
+ pass
117
+ try:
118
+ return _orig_fig_show(self, *args, **kwargs)
119
+ except Exception:
120
+ return None
121
+
122
+ Figure.show = _fig_show
123
+ except Exception:
124
+ pass
125
+
126
+ try:
127
+ from IPython import display as _ip_display
128
+ _orig_display = _ip_display.display
129
+
130
+ def _display(*objs, **kwargs):
131
+ for obj in objs:
132
+ try:
133
+ if hasattr(obj, "_repr_png_"):
134
+ data = obj._repr_png_()
135
+ if data:
136
+ __wasm_idle_send_img("image/png", data)
137
+ continue
138
+ if hasattr(obj, "_repr_svg_"):
139
+ data = obj._repr_svg_()
140
+ if data:
141
+ __wasm_idle_send_img("image/svg+xml", data)
142
+ continue
143
+ except Exception:
144
+ pass
145
+ try:
146
+ return _orig_display(*objs, **kwargs)
147
+ except Exception:
148
+ return None
149
+
150
+ _ip_display.display = _display
151
+ except Exception:
152
+ pass
153
+ `;
154
+ const cdnFallbackUrl = (version) => version ? `https://cdn.jsdelivr.net/pyodide/v${version}/full/` : '';
10
155
  async function loadPyodide(path) {
11
156
  if (pyodide)
12
157
  return;
13
158
  const { loadPyodide } = await import('pyodide');
14
159
  pyodide = await loadPyodide({ indexURL: path + '/pyodide' });
160
+ packageBaseUrl = path + '/pyodide';
161
+ const setCdnUrl = pyodide?.setCdnUrl;
162
+ if (typeof setCdnUrl === 'function')
163
+ setCdnUrl(packageBaseUrl);
164
+ }
165
+ async function ensureRobotJungol() {
166
+ if (jungolRobotReady || !pyodide)
167
+ return;
168
+ try {
169
+ const res = await fetch(path + '/jungol-robot/jungol_robot.zip');
170
+ if (!res.ok)
171
+ throw new Error('jungol-robot zip not found');
172
+ const data = await res.arrayBuffer();
173
+ const siteRaw = pyodide.runPython('import site; site.getsitepackages()[0]');
174
+ const sitePath = typeof siteRaw === 'string' ? siteRaw : siteRaw.toString();
175
+ const unpackArchive = pyodide?.unpackArchive;
176
+ if (typeof unpackArchive !== 'function')
177
+ throw new Error('pyodide.unpackArchive unavailable');
178
+ unpackArchive(data, 'zip', sitePath);
179
+ pyodide.runPython('import importlib; importlib.invalidate_caches()');
180
+ jungolRobotReady = true;
181
+ }
182
+ catch (e) {
183
+ console.warn('jungol-robot preload failed', e);
184
+ }
185
+ }
186
+ async function loadPackages(code) {
187
+ if (!code)
188
+ return;
189
+ try {
190
+ await pyodide.loadPackagesFromImports(code);
191
+ }
192
+ catch (e) {
193
+ const fallback = cdnFallbackUrl(pyodide?.version || '');
194
+ const setCdnUrl = pyodide?.setCdnUrl;
195
+ if (fallback && fallback !== packageBaseUrl && typeof setCdnUrl === 'function') {
196
+ setCdnUrl(fallback);
197
+ packageBaseUrl = fallback;
198
+ await pyodide.loadPackagesFromImports(code);
199
+ return;
200
+ }
201
+ throw e;
202
+ }
15
203
  }
16
204
  self.onmessage = async (event) => {
17
205
  const { code, buffer, load, interrupt, path: _p, prepare } = event.data;
@@ -19,6 +207,7 @@ self.onmessage = async (event) => {
19
207
  path = _p;
20
208
  postMessage({ output: 'Loading Pyodide...' });
21
209
  await loadPyodide(path);
210
+ await ensureRobotJungol();
22
211
  postMessage({ output: ' Done.\n\r' });
23
212
  postMessage({ load: true });
24
213
  }
@@ -26,7 +215,8 @@ self.onmessage = async (event) => {
26
215
  postMessage({ output: 'Loading packages...' });
27
216
  try {
28
217
  await loadPyodide(path);
29
- await pyodide.loadPackagesFromImports(code);
218
+ await ensureRobotJungol();
219
+ await loadPackages(code);
30
220
  postMessage({ output: ' Done.\n\r' });
31
221
  self.postMessage({ results: true });
32
222
  }
@@ -36,7 +226,8 @@ self.onmessage = async (event) => {
36
226
  }
37
227
  else if (code) {
38
228
  await loadPyodide(path);
39
- await pyodide.loadPackagesFromImports(code);
229
+ await ensureRobotJungol();
230
+ await loadPackages(code);
40
231
  const ts = Date.now();
41
232
  stdinBufferPyodide = new Int32Array(buffer);
42
233
  interruptBufferPyodide = new Uint8Array(interrupt);
@@ -103,6 +294,8 @@ print = __pyodide__output_${ts}
103
294
  __builtins__.input = __pyodide__input_${ts}
104
295
  __builtins__.print = __pyodide__output_${ts}
105
296
 
297
+ ${imageHook}
298
+
106
299
  ${code}`);
107
300
  self.postMessage({ results: true });
108
301
  }
@@ -1,12 +1,13 @@
1
1
  <script lang="ts">
2
+ import type { DebugCommand, DebugSessionEvent, SandboxExecutionOptions } from '../playground/options';
2
3
  import type { Sandbox } from '../playground/sandbox';
4
+ import type { TerminalControl } from './types';
3
5
  import { Theme, registerAllPlugins } from './';
4
6
  import load from '../playground';
5
7
  import { onMount } from 'svelte';
6
8
  import '@xterm/xterm/css/xterm.css';
7
9
  import type { Terminal as TerminalType } from '@xterm/xterm';
8
10
 
9
- type TerminalControl = typeof terminalControl;
10
11
  interface Props {
11
12
  dark?: boolean;
12
13
  path?: string;
@@ -15,6 +16,8 @@
15
16
  onload?: () => void;
16
17
  onfinish?: () => void;
17
18
  onkey?: (e: KeyboardEvent) => void;
19
+ ondebug?: (event: DebugSessionEvent) => void;
20
+ onimage?: (payload: { mime: string; b64: string; ts?: number }) => void;
18
21
  terminal?: TerminalControl;
19
22
  }
20
23
 
@@ -25,6 +28,8 @@
25
28
  onload,
26
29
  onfinish,
27
30
  onkey,
31
+ ondebug,
32
+ onimage,
28
33
  terminal = $bindable()
29
34
  }: Props = $props();
30
35
 
@@ -62,11 +67,13 @@
62
67
  await sandbox.clear();
63
68
  ll = language;
64
69
  }
70
+ sandbox.image = onimage;
71
+ sandbox.ondebug = ondebug;
65
72
  sandbox.output = (output: string) =>
66
73
  _tc === tc && term && term.write(output.replaceAll('\n', '\r\n'));
67
74
  }
68
75
 
69
- function runSandbox(pr: Promise<boolean>) {
76
+ function runSandbox<T>(pr: Promise<T>) {
70
77
  return pr
71
78
  .then((x) => {
72
79
  term?.write(`\r\nProcess finished after ${sandbox.elapse}ms\u001B[?25l`);
@@ -76,11 +83,10 @@
76
83
  term?.write(`\r\n\x1B[1;3;31m${msg}\u001B[?25l`);
77
84
  return false;
78
85
  })
79
- .finally((ret) => {
86
+ .finally(() => {
80
87
  onfinish?.();
81
88
  finish = true;
82
89
  if (term) term.options.cursorBlink = false;
83
- return ret;
84
90
  });
85
91
  }
86
92
 
@@ -94,7 +100,7 @@
94
100
  first = false;
95
101
  }
96
102
 
97
- const terminalControl = {
103
+ const terminalControl: TerminalControl = {
98
104
  async clear() {
99
105
  await wait();
100
106
  term?.reset();
@@ -103,25 +109,43 @@
103
109
  first = true;
104
110
  await new Promise((r) => setTimeout(r, 100));
105
111
  },
106
- async prepare(language: string, code: string, log = true, prog, args) {
112
+ async prepare(
113
+ language: string,
114
+ code: string,
115
+ log = true,
116
+ prog?: { set?: (value: number) => void },
117
+ args: string[] = [],
118
+ options: SandboxExecutionOptions = {}
119
+ ) {
107
120
  await Promise.all([
108
- initSandbox(language).then(() => sandbox.load(path, code, log)),
121
+ initSandbox(language).then(() => sandbox.load(path, code, log, args, options)),
109
122
  initTerm(false)
110
123
  ]);
111
- return await runSandbox(sandbox.run(code, true, log, prog, args));
124
+ return !!(await runSandbox(sandbox.run(code, true, log, prog, args, options)));
112
125
  },
113
- async run(language: string, code: string, log = true, prog, args) {
126
+ async run(
127
+ language: string,
128
+ code: string,
129
+ log = true,
130
+ prog?: { set?: (value: number) => void },
131
+ args: string[] = [],
132
+ options: SandboxExecutionOptions = {}
133
+ ) {
114
134
  await Promise.all([
115
- initSandbox(language).then(() => sandbox.load(path, code, log)),
135
+ initSandbox(language).then(() => sandbox.load(path, code, log, args, options)),
116
136
  initTerm()
117
137
  ]);
118
- return await runSandbox(sandbox.run(code, false, log, prog, args));
138
+ return await runSandbox(sandbox.run(code, false, log, prog, args, options));
119
139
  },
120
140
  async destroy() {
121
141
  await wait();
122
142
  term?.dispose();
123
143
  if (sandbox) await sandbox.clear();
124
144
  },
145
+ async debugCommand(command: DebugCommand) {
146
+ await wait();
147
+ sandbox.debugCommand?.(command);
148
+ },
125
149
  async write(input: string) {
126
150
  await wait();
127
151
  term?.write(input + '\r\n');
@@ -1,18 +1,21 @@
1
+ import type { DebugSessionEvent } from '../playground/options';
2
+ import type { TerminalControl } from './types';
1
3
  import '@xterm/xterm/css/xterm.css';
2
- declare const Terminal: import("svelte").Component<{
4
+ interface Props {
3
5
  dark?: boolean;
4
6
  path?: string;
5
7
  font?: string;
6
8
  onload?: () => void;
7
9
  onfinish?: () => void;
8
10
  onkey?: (e: KeyboardEvent) => void;
9
- terminal?: {
10
- clear(): Promise<void>;
11
- prepare(language: string, code: string, log: boolean | undefined, prog: any, args: any): Promise<boolean>;
12
- run(language: string, code: string, log: boolean | undefined, prog: any, args: any): Promise<boolean>;
13
- destroy(): Promise<void>;
14
- write(input: string): Promise<void>;
15
- };
16
- }, {}, "terminal">;
11
+ ondebug?: (event: DebugSessionEvent) => void;
12
+ onimage?: (payload: {
13
+ mime: string;
14
+ b64: string;
15
+ ts?: number;
16
+ }) => void;
17
+ terminal?: TerminalControl;
18
+ }
19
+ declare const Terminal: import("svelte").Component<Props, {}, "terminal">;
17
20
  type Terminal = ReturnType<typeof Terminal>;
18
21
  export default Terminal;
@@ -1,5 +1,7 @@
1
1
  import Theme from './theme';
2
2
  import registerAllPlugins from './plugin';
3
3
  import Terminal from './Terminal.svelte';
4
+ import type { DebugCommand, DebugFrame, DebugSessionEvent, DebugVariable, SandboxExecutionOptions, TerminalControl } from './types';
4
5
  export { Theme, registerAllPlugins };
6
+ export type { DebugCommand, DebugFrame, DebugSessionEvent, DebugVariable, SandboxExecutionOptions, TerminalControl };
5
7
  export default Terminal;
@@ -1,7 +1,7 @@
1
1
  const theme = {
2
2
  Tango_Dark: {
3
3
  foreground: '#eee',
4
- background: '#00000000',
4
+ background: '#111827',
5
5
  cursor: '#FFFFFF',
6
6
  cursorAccent: '#ffffff',
7
7
  selection: '#ffffff44',
@@ -24,7 +24,7 @@ const theme = {
24
24
  },
25
25
  Tango_Light: {
26
26
  foreground: '#111',
27
- background: '#FFFFFF00',
27
+ background: '#FFFFFF',
28
28
  cursor: '#000000',
29
29
  cursorAccent: '#000000',
30
30
  selection: '#00000044',
@@ -0,0 +1,13 @@
1
+ import type { DebugCommand, DebugFrame, DebugSessionEvent, DebugVariable, SandboxExecutionOptions } from '../playground/options';
2
+ export interface ProgressLike {
3
+ set?: (value: number) => void;
4
+ }
5
+ export interface TerminalControl {
6
+ clear: () => Promise<void>;
7
+ prepare: (language: string, code: string, log?: boolean, prog?: ProgressLike, args?: string[], options?: SandboxExecutionOptions) => Promise<boolean>;
8
+ run: (language: string, code: string, log?: boolean, prog?: ProgressLike, args?: string[], options?: SandboxExecutionOptions) => Promise<boolean | string>;
9
+ destroy: () => Promise<void>;
10
+ debugCommand: (command: DebugCommand) => Promise<void>;
11
+ write: (input: string) => Promise<void>;
12
+ }
13
+ export type { DebugCommand, DebugFrame, DebugSessionEvent, DebugVariable, SandboxExecutionOptions };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wasm-idle",
3
- "version": "0.2.5",
3
+ "version": "0.3.1",
4
4
  "description": "A simple web app to run C++/Python code in the browser",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -10,49 +10,58 @@
10
10
  "preview": "vite preview",
11
11
  "package": "svelte-kit sync && svelte-package && publint",
12
12
  "prepublishOnly": "npm run package",
13
+ "test": "vitest run",
14
+ "test:watch": "vitest",
13
15
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
14
16
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
15
17
  "lint": "prettier --check . && eslint .",
16
- "format": "prettier --write ."
18
+ "format": "prettier --write .",
19
+ "page": "npm run build && node gh-pages.js"
17
20
  },
18
21
  "devDependencies": {
19
- "@eslint/js": "^9.19.0",
20
- "@sveltejs/adapter-auto": "^4.0.0",
21
- "@sveltejs/adapter-static": "^3.0.8",
22
- "@sveltejs/kit": "^2.17.1",
23
- "@sveltejs/package": "^2.3.10",
24
- "@sveltejs/vite-plugin-svelte": "^5.0.3",
25
- "@typescript-eslint/eslint-plugin": "^8.23.0",
26
- "@typescript-eslint/parser": "^8.23.0",
27
- "eslint": "^9.19.0",
28
- "eslint-config-prettier": "^10.0.1",
29
- "eslint-plugin-svelte": "^2.46.1",
22
+ "@eslint/js": "^10.0.1",
23
+ "@sveltejs/adapter-auto": "^7.0.1",
24
+ "@sveltejs/adapter-static": "^3.0.10",
25
+ "@sveltejs/kit": "^2.53.4",
26
+ "@sveltejs/package": "^2.5.7",
27
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
28
+ "@testing-library/svelte": "^5.3.1",
29
+ "@testing-library/user-event": "^14.6.1",
30
+ "@typescript-eslint/eslint-plugin": "^8.57.0",
31
+ "@typescript-eslint/parser": "^8.57.0",
32
+ "eslint": "^10.0.3",
33
+ "eslint-config-prettier": "^10.1.8",
34
+ "eslint-plugin-svelte": "^3.15.2",
30
35
  "eslint-plugin-svelte3": "^4.0.0",
31
36
  "gh-pages": "^6.3.0",
32
- "globals": "^15.14.0",
33
- "monaco-editor": "^0.52.2",
34
- "prettier": "^3.4.2",
35
- "prettier-plugin-svelte": "^3.3.3",
36
- "svelte": "^5.19.7",
37
- "svelte-check": "^4.1.4",
37
+ "globals": "^17.4.0",
38
+ "jsdom": "^28.1.0",
39
+ "monaco-editor": "^0.55.1",
40
+ "prettier": "^3.8.1",
41
+ "prettier-plugin-svelte": "^3.5.1",
42
+ "svelte": "^5.53.10",
43
+ "svelte-check": "^4.4.5",
38
44
  "tslib": "^2.8.1",
39
- "typescript": "^5.7.3",
40
- "typescript-eslint": "^8.23.0",
41
- "vite": "^6.0.11"
45
+ "typescript": "^5.9.3",
46
+ "typescript-eslint": "^8.57.0",
47
+ "vite": "^7.3.1",
48
+ "vitest": "^4.0.18"
42
49
  },
43
50
  "dependencies": {
51
+ "@hancomac/monaco-languageclient": "^1.1.0",
44
52
  "@xterm/addon-canvas": "^0.7.0",
45
- "@xterm/addon-fit": "^0.10.0",
46
- "@xterm/addon-ligatures": "^0.9.0",
47
- "@xterm/addon-search": "^0.15.0",
48
- "@xterm/addon-serialize": "^0.13.0",
49
- "@xterm/addon-unicode11": "^0.8.0",
50
- "@xterm/addon-web-links": "^0.11.0",
51
- "@xterm/addon-webgl": "^0.18.0",
52
- "@xterm/xterm": "^5.5.0",
53
- "@zip.js/zip.js": "^2.7.57",
54
- "publint": "^0.3.3",
55
- "pyodide": "0.26.2"
53
+ "@xterm/addon-fit": "^0.11.0",
54
+ "@xterm/addon-ligatures": "^0.10.0",
55
+ "@xterm/addon-search": "^0.16.0",
56
+ "@xterm/addon-serialize": "^0.14.0",
57
+ "@xterm/addon-unicode11": "^0.9.0",
58
+ "@xterm/addon-web-links": "^0.12.0",
59
+ "@xterm/addon-webgl": "^0.19.0",
60
+ "@xterm/xterm": "^6.0.0",
61
+ "@zip.js/zip.js": "^2.8.23",
62
+ "publint": "^0.3.18",
63
+ "pyodide": "0.26.2",
64
+ "vscode-jsonrpc": "^8.2.1"
56
65
  },
57
66
  "files": [
58
67
  "dist",