wgsl-edit 0.0.25 → 0.0.26

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/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "wgsl-edit",
3
3
  "description": "Web component for editing WGSL/WESL with CodeMirror",
4
- "version": "0.0.25",
4
+ "version": "0.0.26",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
8
8
  "src"
9
9
  ],
10
- "repository": "github:wgsl-tooling-wg/wesl-js",
10
+ "repository": "github:webgpu-tools/wesl-js",
11
11
  "exports": {
12
12
  ".": {
13
13
  "types": "./dist/index.d.ts",
@@ -21,9 +21,17 @@
21
21
  "types": "./dist/Language.d.ts",
22
22
  "import": "./dist/Language.js"
23
23
  },
24
+ "./autosave": {
25
+ "types": "./dist/autosave.d.ts",
26
+ "import": "./dist/autosave.js"
27
+ },
24
28
  "./bundle": {
25
29
  "types": "./dist/WgslEdit.d.ts",
26
30
  "import": "./dist/wgsl-edit.js"
31
+ },
32
+ "./jsx-preact": {
33
+ "types": "./dist/jsx-preact.d.ts",
34
+ "import": "./dist/jsx-preact.js"
27
35
  }
28
36
  },
29
37
  "dependencies": {
@@ -36,22 +44,32 @@
36
44
  "@codemirror/view": "^6.0.0",
37
45
  "@lezer/highlight": "^1.2.1",
38
46
  "codemirror": "^6.0.0",
39
- "lezer-wesl": "0.6.47",
40
- "wesl": "0.7.26",
41
- "wesl-fetch": "0.0.14"
47
+ "wesl-fetch": "0.0.15",
48
+ "lezer-wesl": "0.6.48",
49
+ "wesl": "0.7.27"
42
50
  },
43
51
  "devDependencies": {
44
52
  "@playwright/test": "^1.53.2",
45
53
  "open": "^10.0.0",
54
+ "preact": "^10.27.2",
46
55
  "vite": "^8.0.1",
56
+ "wesl-plugin": "x",
47
57
  "wgsl-play": "x",
48
58
  "yargs": "^18.0.0"
49
59
  },
60
+ "peerDependencies": {
61
+ "vite": "^8.0.1"
62
+ },
63
+ "peerDependenciesMeta": {
64
+ "vite": {
65
+ "optional": true
66
+ }
67
+ },
50
68
  "scripts": {
51
69
  "build": "tsdown",
52
70
  "build:demo": "vite build --config vite.config.ts demo",
53
71
  "deploy": "pnpm build:demo && pnpx wrangler pages deploy --project-name wgsl-edit --branch main site",
54
- "dev": "vite demo",
72
+ "dev": "vite demo --config vite.config.ts",
55
73
  "dev:test": "vite test-page --config vite.config.ts",
56
74
  "test:e2e": "playwright test",
57
75
  "typecheck": "tsgo"
@@ -0,0 +1,2 @@
1
+ /** Shared between client (WgslEdit) and server (SaveMiddleware) so they can't drift. */
2
+ export const saveEndpoint = "/__wgsl-edit/save";
@@ -0,0 +1,71 @@
1
+ import fs from "node:fs/promises";
2
+ import type { IncomingMessage, ServerResponse } from "node:http";
3
+ import path from "node:path";
4
+ import { saveEndpoint } from "./SaveEndpoint.ts";
5
+
6
+ /** Paths recently written by autosave; consumed by hotUpdate to suppress reloads. */
7
+ export const pendingSaves = new Set<string>();
8
+
9
+ /** Connect-style middleware that handles POST <saveEndpoint> to write files to disk. */
10
+ export function weslSaveMiddleware(
11
+ projectRoot: string,
12
+ ): (req: IncomingMessage, res: ServerResponse, next: () => void) => void {
13
+ return (req, res, next) => {
14
+ if (req.url !== saveEndpoint) return next();
15
+ if (req.method !== "POST") return next();
16
+ readBody(req).then(body => handleSave(body, projectRoot, res), next);
17
+ };
18
+ }
19
+
20
+ interface SaveRequest {
21
+ root: string;
22
+ file: string;
23
+ content: string;
24
+ }
25
+
26
+ async function handleSave(
27
+ raw: string,
28
+ projectRoot: string,
29
+ res: ServerResponse,
30
+ ): Promise<void> {
31
+ let body: SaveRequest;
32
+ try {
33
+ body = JSON.parse(raw);
34
+ } catch {
35
+ return respond(res, 400, "invalid JSON");
36
+ }
37
+
38
+ const { root, file, content } = body;
39
+ if (!file || typeof content !== "string") {
40
+ return respond(res, 400, "missing file or content");
41
+ }
42
+
43
+ const resolved = path.resolve(projectRoot, root ?? ".", file);
44
+ if (!resolved.startsWith(projectRoot + path.sep)) {
45
+ return respond(res, 403, "path outside project root");
46
+ }
47
+
48
+ try {
49
+ await fs.mkdir(path.dirname(resolved), { recursive: true });
50
+ await fs.writeFile(resolved, content);
51
+ pendingSaves.add(resolved);
52
+ respond(res, 200, "ok");
53
+ } catch (e: any) {
54
+ console.error("[wgsl-edit] save failed:", e.message);
55
+ respond(res, 500, e.message);
56
+ }
57
+ }
58
+
59
+ function readBody(req: IncomingMessage): Promise<string> {
60
+ return new Promise((resolve, reject) => {
61
+ const chunks: Buffer[] = [];
62
+ req.on("data", (c: Buffer) => chunks.push(c));
63
+ req.on("end", () => resolve(Buffer.concat(chunks).toString()));
64
+ req.on("error", reject);
65
+ });
66
+ }
67
+
68
+ function respond(res: ServerResponse, status: number, msg: string): void {
69
+ res.writeHead(status, { "Content-Type": "text/plain" });
70
+ res.end(msg);
71
+ }