mr-md 2.1.2-beta → 2.2.0-beta

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.
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
package/dist/builder.js CHANGED
@@ -5,31 +5,29 @@ import { fileURLToPath } from "url";
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
  function getCallerDir() {
8
+ const originalPrepareStackTrace = Error.prepareStackTrace;
9
+ Error.prepareStackTrace = (_, stack) => stack;
8
10
  const err = new Error();
9
- const stack = err.stack?.split("\n");
10
- if (!stack || stack.length < 2)
11
+ const stack = err.stack;
12
+ Error.prepareStackTrace = originalPrepareStackTrace;
13
+ if (!stack || !Array.isArray(stack))
11
14
  return undefined;
12
- let builderFilePath;
13
- for (let i = 1; i < stack.length; i++) {
14
- const line = stack[i];
15
- const match = line.match(/\((.*?):\d+:\d+\)/) || line.match(/at (.*?):\d+:\d+/);
16
- if (match) {
17
- let p = match[1];
18
- if (p.startsWith("file://")) {
19
- p = fileURLToPath(p);
20
- }
21
- else if (p.startsWith("/") && p[2] === ":") {
22
- p = p.substring(1);
23
- }
24
- if (!builderFilePath) {
25
- builderFilePath = p;
26
- continue;
27
- }
28
- if (p === builderFilePath) {
29
- continue;
30
- }
31
- return path.dirname(p);
15
+ for (let i = 0; i < stack.length; i++) {
16
+ const callSite = stack[i];
17
+ let p = callSite.getFileName();
18
+ if (!p)
19
+ continue;
20
+ if (p.startsWith("file://")) {
21
+ p = fileURLToPath(p);
22
+ }
23
+ else if (p.startsWith("/") && p[2] === ":") {
24
+ p = p.substring(1);
25
+ }
26
+ const basename = path.basename(p);
27
+ if (basename === "builder.ts" || basename === "builder.js" || basename === "index.ts" || basename === "index.js") {
28
+ continue;
32
29
  }
30
+ return path.dirname(p);
33
31
  }
34
32
  return undefined;
35
33
  }
@@ -417,7 +415,7 @@ export class LessonBuilder {
417
415
  const lesson = { meta: this.meta, blocks: this.blocks };
418
416
  const html = render(lesson, this.options);
419
417
  const outDir = path.resolve(this.options.outDir);
420
- const outPath = path.join(outDir, `${this.meta.slug}.html`);
418
+ const outPath = path.join(outDir, "index.html");
421
419
  const outPathDir = path.dirname(outPath);
422
420
  if (!fs.existsSync(outPathDir))
423
421
  fs.mkdirSync(outPathDir, { recursive: true });
@@ -596,7 +594,7 @@ export class ChapterBuilder {
596
594
  const chapterData = { meta: this.meta, lessons };
597
595
  const html = renderChapter(chapterData, this.options);
598
596
  const outDir = path.resolve(this.options.outDir);
599
- const outPath = path.join(outDir, `${this.meta.slug}.html`);
597
+ const outPath = path.join(outDir, "index.html");
600
598
  const outPathDir = path.dirname(outPath);
601
599
  if (!fs.existsSync(outPathDir))
602
600
  fs.mkdirSync(outPathDir, { recursive: true });
package/dist/cli/dev.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare function runDev(args: string[]): Promise<void>;
1
+ export declare function runDev(args: string[]): void;
2
2
  //# sourceMappingURL=dev.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAMA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,iBAwG1C"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAKA,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,QA4HpC"}
package/dist/cli/dev.js CHANGED
@@ -1,23 +1,31 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { exec } from "child_process";
4
- export async function runDev(args) {
3
+ export function runDev(args) {
5
4
  const dir = args[0] || ".";
6
- const outDir = path.resolve(process.cwd(), dir, "out");
5
+ let outDir = path.resolve(process.cwd(), dir, "out");
7
6
  console.log(`Starting dev server for directory: ${dir}`);
8
7
  let server;
8
+ let currentBuild = null;
9
9
  const rebuild = () => {
10
+ if (currentBuild) {
11
+ currentBuild.kill();
12
+ }
10
13
  console.log("Rebuilding...");
11
- const entryPoints = ["chapter.ts", "index.ts", "lesson.ts"];
14
+ const entryPoints = ["chapter.ts", "index.ts", "lesson.ts", "chapters/01-chapter/chapter.ts"];
12
15
  for (const entry of entryPoints) {
13
16
  const entryPath = path.join(dir, entry);
14
17
  if (fs.existsSync(entryPath)) {
15
- exec(`NODE_ENV=development bun "${entryPath}"`, (err, stdout, stderr) => {
16
- if (err)
17
- console.error("Build failed:", stderr);
18
- else {
19
- console.log("Build successful.");
20
- server?.publish("livereload", "reload");
18
+ outDir = path.resolve(process.cwd(), path.dirname(entryPath), "out");
19
+ currentBuild = Bun.spawn([process.execPath, entryPath], {
20
+ env: { ...process.env, NODE_ENV: "development" },
21
+ onExit(proc, exitCode, signalCode, error) {
22
+ if (exitCode === 0) {
23
+ console.log("Build successful.");
24
+ server?.publish("livereload", "reload");
25
+ }
26
+ else if (exitCode !== null) {
27
+ console.error(`Build failed with exit code ${exitCode}`);
28
+ }
21
29
  }
22
30
  });
23
31
  return;
@@ -39,62 +47,69 @@ export async function runDev(args) {
39
47
  });
40
48
  console.log(`Watching ${dir} for changes...`);
41
49
  }
42
- server = Bun.serve({
43
- port: 3000,
44
- async fetch(req, srv) {
45
- if (srv.upgrade(req))
46
- return;
47
- const url = new URL(req.url);
48
- const decodedPath = decodeURIComponent(url.pathname);
49
- let filePath = path.resolve(outDir, "." + decodedPath);
50
- if (decodedPath.endsWith("/")) {
51
- const files = fs.existsSync(outDir) ? fs.readdirSync(outDir) : [];
52
- const htmlFiles = files.filter(f => f.endsWith(".html"));
53
- if (htmlFiles.includes("index.html")) {
54
- filePath = path.join(outDir, "index.html");
50
+ const basePort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
51
+ let port = basePort;
52
+ const maxPort = basePort + 10;
53
+ const fetchHandler = async (req, srv) => {
54
+ if (srv.upgrade(req))
55
+ return;
56
+ const url = new URL(req.url);
57
+ const decodedPath = decodeURIComponent(url.pathname);
58
+ let filePath = path.resolve(outDir, "." + decodedPath);
59
+ if (decodedPath.endsWith("/")) {
60
+ filePath = path.join(outDir, "index.html");
61
+ }
62
+ if (!filePath.startsWith(outDir + path.sep) && filePath !== outDir) {
63
+ return new Response("Forbidden", { status: 403 });
64
+ }
65
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
66
+ if (filePath.endsWith(".html")) {
67
+ const file = Bun.file(filePath);
68
+ let text = await file.text();
69
+ const script = `<script>
70
+ const ws = new WebSocket(\`ws://\${location.host}/\`);
71
+ ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
72
+ </script>`;
73
+ const bodyRegex = /<\/body>/i;
74
+ const match = text.match(bodyRegex);
75
+ if (match && match.index !== undefined) {
76
+ text = text.slice(0, match.index) + script + text.slice(match.index);
55
77
  }
56
78
  else {
57
- const chapterFile = htmlFiles.find(f => f.includes("chapter"));
58
- if (chapterFile) {
59
- filePath = path.join(outDir, chapterFile);
60
- }
61
- else if (htmlFiles.length > 0) {
62
- filePath = path.join(outDir, htmlFiles[0]);
63
- }
64
- else {
65
- filePath = path.join(outDir, "index.html");
66
- }
79
+ text += script;
67
80
  }
81
+ return new Response(text, { headers: { "Content-Type": "text/html" } });
68
82
  }
69
- if (!filePath.startsWith(outDir + path.sep) && filePath !== outDir) {
70
- return new Response("Forbidden", { status: 403 });
71
- }
72
- if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
73
- if (filePath.endsWith(".html")) {
74
- const file = Bun.file(filePath);
75
- let text = await file.text();
76
- const lastBodyIndex = text.lastIndexOf("</body>");
77
- if (lastBodyIndex !== -1) {
78
- text = text.slice(0, lastBodyIndex) + `<script>
79
- const ws = new WebSocket(\`ws://\${location.host}/\`);
80
- ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
81
- </script></body>` + text.slice(lastBodyIndex + 7);
82
- }
83
- return new Response(text, { headers: { "Content-Type": "text/html" } });
84
- }
85
- return new Response(Bun.file(filePath));
83
+ return new Response(Bun.file(filePath));
84
+ }
85
+ return new Response("Not found", { status: 404 });
86
+ };
87
+ const wsHandler = {
88
+ message() { },
89
+ open(ws) { ws.subscribe("livereload"); }
90
+ };
91
+ while (port <= maxPort) {
92
+ try {
93
+ server = Bun.serve({
94
+ port,
95
+ fetch: fetchHandler,
96
+ websocket: wsHandler
97
+ });
98
+ console.log(`Dev server listening on http://localhost:${server.port}`);
99
+ break;
100
+ }
101
+ catch (err) {
102
+ if (err.code === 'EADDRINUSE') {
103
+ console.warn(`Port ${port} is in use, trying ${port + 1}...`);
104
+ port++;
86
105
  }
87
- const baseDir = path.resolve(process.cwd(), dir);
88
- const srcPath = path.resolve(baseDir, "." + decodedPath);
89
- if (srcPath.startsWith(baseDir + path.sep) && fs.existsSync(srcPath) && fs.statSync(srcPath).isFile()) {
90
- return new Response(Bun.file(srcPath));
106
+ else {
107
+ throw err;
91
108
  }
92
- return new Response("Not found", { status: 404 });
93
- },
94
- websocket: {
95
- message() { },
96
- open(ws) { ws.subscribe("livereload"); }
97
109
  }
98
- });
99
- console.log(`Dev server listening on http://localhost:3000`);
110
+ }
111
+ if (!server) {
112
+ console.error(`Could not find an open port between ${basePort} and ${maxPort}.`);
113
+ process.exit(1);
114
+ }
100
115
  }
package/dist/cli.js CHANGED
File without changes
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/renderer/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;CACpD;AAID,iBAAS,cAAc,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,EACrB,YAAY,GAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAe,GAClD,MAAM,CA0DR;AAED,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAuDnE;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/renderer/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,OAAO;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,YAAY,CAAC;CACpD;AAID,iBAAS,cAAc,CACtB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,EACrB,YAAY,GAAE,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,MAAe,GAClD,MAAM,CA0DR;AAED,iBAAS,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAyDnE;AAED,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC"}
@@ -35,7 +35,7 @@ function resolveContent(src, options, expectedType = "text") {
35
35
  const stat = fs.statSync(filePath);
36
36
  if (stat.isFile()) {
37
37
  if (expectedType === "js" && (filePath.endsWith(".js") || filePath.endsWith(".ts") || filePath.endsWith(".jsx") || filePath.endsWith(".tsx"))) {
38
- const out = spawnSync("bun", ["build", "--target=browser", filePath]);
38
+ const out = spawnSync(process.execPath, ["build", "--target=browser", filePath]);
39
39
  if (out.status === 0) {
40
40
  return out.stdout.toString("utf-8");
41
41
  }
@@ -92,7 +92,9 @@ function resolveAssetSrc(src, options) {
92
92
  fs.mkdirSync(assetsDir, { recursive: true });
93
93
  }
94
94
  // Create a safe filename with hash to avoid collisions
95
- const hash = crypto.createHash("md5").update(filePath).digest("hex").substring(0, 8);
95
+ // Use relative path for hashing to ensure deterministic builds across different machines
96
+ const relPathForHash = path.relative(options.contentBase ?? process.cwd(), filePath);
97
+ const hash = crypto.createHash("md5").update(relPathForHash).digest("hex").substring(0, 8);
96
98
  const ext = path.extname(filePath);
97
99
  const filename = `${path.basename(filePath, ext)}-${hash}${ext}`;
98
100
  const outPath = path.join(assetsDir, filename);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-md",
3
- "version": "2.1.2-beta",
3
+ "version": "2.2.0-beta",
4
4
  "description": "Mr Markdown is an opinionated TypeScript SDK for building interactive learning pages.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "src"
21
21
  ],
22
22
  "scripts": {
23
- "build": "tsc -p tsconfig.build.json && mkdir -p dist/styles dist/client && cp -r src/styles/* dist/styles/ && cp -r src/client/* dist/client/",
23
+ "build": "tsc -p tsconfig.build.json && bun -e \"import {mkdirSync, cpSync} from 'fs'; mkdirSync('dist/styles', {recursive:true}); mkdirSync('dist/client', {recursive:true}); cpSync('src/styles', 'dist/styles', {recursive:true}); cpSync('src/client', 'dist/client', {recursive:true})\"",
24
24
  "prepublishOnly": "bun run build",
25
25
  "build:docs": "bun docs-site/build.ts",
26
26
  "serve:docs": "bunx serve docs-site/out",
package/src/builder.ts CHANGED
@@ -36,31 +36,30 @@ const __filename = fileURLToPath(import.meta.url);
36
36
  const __dirname = path.dirname(__filename);
37
37
 
38
38
  function getCallerDir(): string | undefined {
39
+ const originalPrepareStackTrace = Error.prepareStackTrace;
40
+ Error.prepareStackTrace = (_, stack) => stack;
39
41
  const err = new Error();
40
- const stack = err.stack?.split("\n");
41
- if (!stack || stack.length < 2) return undefined;
42
-
43
- let builderFilePath: string | undefined;
44
-
45
- for (let i = 1; i < stack.length; i++) {
46
- const line = stack[i];
47
- const match = line.match(/\((.*?):\d+:\d+\)/) || line.match(/at (.*?):\d+:\d+/);
48
- if (match) {
49
- let p = match[1];
50
- if (p.startsWith("file://")) {
51
- p = fileURLToPath(p);
52
- } else if (p.startsWith("/") && p[2] === ":") {
53
- p = p.substring(1);
54
- }
55
- if (!builderFilePath) {
56
- builderFilePath = p;
57
- continue;
58
- }
59
- if (p === builderFilePath) {
60
- continue;
61
- }
62
- return path.dirname(p);
42
+ const stack = err.stack as any as NodeJS.CallSite[];
43
+ Error.prepareStackTrace = originalPrepareStackTrace;
44
+
45
+ if (!stack || !Array.isArray(stack)) return undefined;
46
+
47
+ for (let i = 0; i < stack.length; i++) {
48
+ const callSite = stack[i];
49
+ let p = callSite.getFileName();
50
+ if (!p) continue;
51
+
52
+ if (p.startsWith("file://")) {
53
+ p = fileURLToPath(p);
54
+ } else if (p.startsWith("/") && p[2] === ":") {
55
+ p = p.substring(1);
56
+ }
57
+
58
+ const basename = path.basename(p);
59
+ if (basename === "builder.ts" || basename === "builder.js" || basename === "index.ts" || basename === "index.js") {
60
+ continue;
63
61
  }
62
+ return path.dirname(p);
64
63
  }
65
64
  return undefined;
66
65
  }
@@ -531,7 +530,7 @@ export class LessonBuilder {
531
530
  const html = render(lesson, this.options);
532
531
 
533
532
  const outDir = path.resolve(this.options.outDir as string);
534
- const outPath = path.join(outDir, `${this.meta.slug}.html`);
533
+ const outPath = path.join(outDir, "index.html");
535
534
  const outPathDir = path.dirname(outPath);
536
535
 
537
536
  if (!fs.existsSync(outPathDir)) fs.mkdirSync(outPathDir, { recursive: true });
@@ -758,7 +757,7 @@ export class ChapterBuilder {
758
757
  const html = renderChapter(chapterData, this.options);
759
758
 
760
759
  const outDir = path.resolve(this.options.outDir as string);
761
- const outPath = path.join(outDir, `${this.meta.slug}.html`);
760
+ const outPath = path.join(outDir, "index.html");
762
761
  const outPathDir = path.dirname(outPath);
763
762
 
764
763
  if (!fs.existsSync(outPathDir)) fs.mkdirSync(outPathDir, { recursive: true });
package/src/cli/dev.ts CHANGED
@@ -1,28 +1,36 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { exec } from "child_process";
4
3
 
5
4
  declare const Bun: any;
6
5
 
7
- export async function runDev(args: string[]) {
6
+ export function runDev(args: string[]) {
8
7
  const dir = args[0] || ".";
9
- const outDir = path.resolve(process.cwd(), dir, "out");
8
+ let outDir = path.resolve(process.cwd(), dir, "out");
10
9
 
11
10
  console.log(`Starting dev server for directory: ${dir}`);
12
11
 
13
12
  let server: any;
13
+ let currentBuild: any = null;
14
14
 
15
15
  const rebuild = () => {
16
+ if (currentBuild) {
17
+ currentBuild.kill();
18
+ }
16
19
  console.log("Rebuilding...");
17
- const entryPoints = ["chapter.ts", "index.ts", "lesson.ts"];
20
+ const entryPoints = ["chapter.ts", "index.ts", "lesson.ts", "chapters/01-chapter/chapter.ts"];
18
21
  for (const entry of entryPoints) {
19
22
  const entryPath = path.join(dir, entry);
20
23
  if (fs.existsSync(entryPath)) {
21
- exec(`NODE_ENV=development bun "${entryPath}"`, (err, stdout, stderr) => {
22
- if (err) console.error("Build failed:", stderr);
23
- else {
24
- console.log("Build successful.");
25
- server?.publish("livereload", "reload");
24
+ outDir = path.resolve(process.cwd(), path.dirname(entryPath), "out");
25
+ currentBuild = Bun.spawn([process.execPath, entryPath], {
26
+ env: { ...process.env, NODE_ENV: "development" },
27
+ onExit(proc: any, exitCode: number, signalCode: number, error: string) {
28
+ if (exitCode === 0) {
29
+ console.log("Build successful.");
30
+ server?.publish("livereload", "reload");
31
+ } else if (exitCode !== null) {
32
+ console.error(`Build failed with exit code ${exitCode}`);
33
+ }
26
34
  }
27
35
  });
28
36
  return;
@@ -47,65 +55,76 @@ export async function runDev(args: string[]) {
47
55
  console.log(`Watching ${dir} for changes...`);
48
56
  }
49
57
 
50
- server = Bun.serve({
51
- port: 3000,
52
- async fetch(req: any, srv: any) {
53
- if (srv.upgrade(req)) return;
58
+ const basePort = process.env.PORT ? parseInt(process.env.PORT) : 3000;
59
+ let port = basePort;
60
+ const maxPort = basePort + 10;
61
+
62
+ const fetchHandler = async (req: any, srv: any) => {
63
+ if (srv.upgrade(req)) return;
54
64
 
55
- const url = new URL(req.url);
56
- const decodedPath = decodeURIComponent(url.pathname);
57
- let filePath = path.resolve(outDir, "." + decodedPath);
58
-
59
- if (decodedPath.endsWith("/")) {
60
- const files = fs.existsSync(outDir) ? fs.readdirSync(outDir) : [];
61
- const htmlFiles = files.filter(f => f.endsWith(".html"));
62
- if (htmlFiles.includes("index.html")) {
63
- filePath = path.join(outDir, "index.html");
65
+ const url = new URL(req.url);
66
+ const decodedPath = decodeURIComponent(url.pathname);
67
+ let filePath = path.resolve(outDir, "." + decodedPath);
68
+
69
+ if (decodedPath.endsWith("/")) {
70
+ filePath = path.join(outDir, "index.html");
71
+ }
72
+
73
+ if (!filePath.startsWith(outDir + path.sep) && filePath !== outDir) {
74
+ return new Response("Forbidden", { status: 403 });
75
+ }
76
+
77
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
78
+ if (filePath.endsWith(".html")) {
79
+ const file = Bun.file(filePath);
80
+ let text = await file.text();
81
+
82
+ const script = `<script>
83
+ const ws = new WebSocket(\`ws://\${location.host}/\`);
84
+ ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
85
+ </script>`;
86
+
87
+ const bodyRegex = /<\/body>/i;
88
+ const match = text.match(bodyRegex);
89
+ if (match && match.index !== undefined) {
90
+ text = text.slice(0, match.index) + script + text.slice(match.index);
64
91
  } else {
65
- const chapterFile = htmlFiles.find(f => f.includes("chapter"));
66
- if (chapterFile) {
67
- filePath = path.join(outDir, chapterFile);
68
- } else if (htmlFiles.length > 0) {
69
- filePath = path.join(outDir, htmlFiles[0]);
70
- } else {
71
- filePath = path.join(outDir, "index.html");
72
- }
92
+ text += script;
73
93
  }
94
+ return new Response(text, { headers: { "Content-Type": "text/html" } });
74
95
  }
96
+ return new Response(Bun.file(filePath));
97
+ }
75
98
 
76
- if (!filePath.startsWith(outDir + path.sep) && filePath !== outDir) {
77
- return new Response("Forbidden", { status: 403 });
78
- }
99
+ return new Response("Not found", { status: 404 });
100
+ };
79
101
 
80
- if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
81
- if (filePath.endsWith(".html")) {
82
- const file = Bun.file(filePath);
83
- let text = await file.text();
84
- const lastBodyIndex = text.lastIndexOf("</body>");
85
- if (lastBodyIndex !== -1) {
86
- text = text.slice(0, lastBodyIndex) + `<script>
87
- const ws = new WebSocket(\`ws://\${location.host}/\`);
88
- ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
89
- </script></body>` + text.slice(lastBodyIndex + 7);
90
- }
91
- return new Response(text, { headers: { "Content-Type": "text/html" } });
92
- }
93
- return new Response(Bun.file(filePath));
94
- }
102
+ const wsHandler = {
103
+ message() {},
104
+ open(ws: any) { ws.subscribe("livereload"); }
105
+ };
95
106
 
96
- const baseDir = path.resolve(process.cwd(), dir);
97
- const srcPath = path.resolve(baseDir, "." + decodedPath);
98
- if (srcPath.startsWith(baseDir + path.sep) && fs.existsSync(srcPath) && fs.statSync(srcPath).isFile()) {
99
- return new Response(Bun.file(srcPath));
107
+ while (port <= maxPort) {
108
+ try {
109
+ server = Bun.serve({
110
+ port,
111
+ fetch: fetchHandler,
112
+ websocket: wsHandler
113
+ });
114
+ console.log(`Dev server listening on http://localhost:${server.port}`);
115
+ break;
116
+ } catch (err: any) {
117
+ if (err.code === 'EADDRINUSE') {
118
+ console.warn(`Port ${port} is in use, trying ${port + 1}...`);
119
+ port++;
120
+ } else {
121
+ throw err;
100
122
  }
101
-
102
- return new Response("Not found", { status: 404 });
103
- },
104
- websocket: {
105
- message() {},
106
- open(ws: any) { ws.subscribe("livereload"); }
107
123
  }
108
- });
109
-
110
- console.log(`Dev server listening on http://localhost:3000`);
124
+ }
125
+
126
+ if (!server) {
127
+ console.error(`Could not find an open port between ${basePort} and ${maxPort}.`);
128
+ process.exit(1);
129
+ }
111
130
  }
@@ -54,7 +54,7 @@ function resolveContent(
54
54
  const stat = fs.statSync(filePath);
55
55
  if (stat.isFile()) {
56
56
  if (expectedType === "js" && (filePath.endsWith(".js") || filePath.endsWith(".ts") || filePath.endsWith(".jsx") || filePath.endsWith(".tsx"))) {
57
- const out = spawnSync("bun", ["build", "--target=browser", filePath]);
57
+ const out = spawnSync(process.execPath, ["build", "--target=browser", filePath]);
58
58
  if (out.status === 0) {
59
59
  return out.stdout.toString("utf-8");
60
60
  } else {
@@ -121,7 +121,9 @@ function resolveAssetSrc(src: string, options: BuildOptions): string {
121
121
  }
122
122
 
123
123
  // Create a safe filename with hash to avoid collisions
124
- const hash = crypto.createHash("md5").update(filePath).digest("hex").substring(0, 8);
124
+ // Use relative path for hashing to ensure deterministic builds across different machines
125
+ const relPathForHash = path.relative(options.contentBase ?? process.cwd(), filePath);
126
+ const hash = crypto.createHash("md5").update(relPathForHash).digest("hex").substring(0, 8);
125
127
  const ext = path.extname(filePath);
126
128
  const filename = `${path.basename(filePath, ext)}-${hash}${ext}`;
127
129
  const outPath = path.join(assetsDir, filename);