mr-md 2.1.0-beta → 2.1.1-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.
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +16 -5
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +16 -8
- package/dist/cli/generate.js +1 -1
- package/dist/renderer/blocks.js +1 -1
- package/dist/renderer/markdown.js +5 -5
- package/dist/renderer/utils.d.ts.map +1 -1
- package/dist/renderer/utils.js +23 -17
- package/package.json +1 -1
- package/src/builder.ts +16 -5
- package/src/cli/dev.ts +17 -8
- package/src/cli/generate.ts +1 -1
- package/src/renderer/blocks.ts +1 -1
- package/src/renderer/markdown.ts +5 -5
- package/src/renderer/utils.ts +25 -16
package/dist/builder.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEX,gBAAgB,EAEhB,YAAY,EACZ,YAAY,EACZ,OAAO,EAGP,UAAU,EAEV,cAAc,EAId,YAAY,EACZ,MAAM,EACN,UAAU,EAGV,YAAY,EACZ,SAAS,EAIT,iBAAiB,EAEjB,cAAc,EACd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../src/builder.ts"],"names":[],"mappings":"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"}
|
package/dist/builder.js
CHANGED
|
@@ -44,8 +44,17 @@ function copyAssets(outDir) {
|
|
|
44
44
|
const copyDir = (src, dest) => {
|
|
45
45
|
if (!fs.existsSync(src))
|
|
46
46
|
return;
|
|
47
|
+
if (!fs.existsSync(dest))
|
|
48
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
47
49
|
for (const file of fs.readdirSync(src)) {
|
|
48
|
-
|
|
50
|
+
const srcFile = path.join(src, file);
|
|
51
|
+
const destFile = path.join(dest, file);
|
|
52
|
+
if (fs.statSync(srcFile).isDirectory()) {
|
|
53
|
+
copyDir(srcFile, destFile);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
fs.copyFileSync(srcFile, destFile);
|
|
57
|
+
}
|
|
49
58
|
}
|
|
50
59
|
};
|
|
51
60
|
if (fs.existsSync(srcStylesDir))
|
|
@@ -408,9 +417,10 @@ export class LessonBuilder {
|
|
|
408
417
|
const lesson = { meta: this.meta, blocks: this.blocks };
|
|
409
418
|
const html = render(lesson, this.options);
|
|
410
419
|
const outDir = path.resolve(this.options.outDir);
|
|
411
|
-
if (!fs.existsSync(outDir))
|
|
412
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
413
420
|
const outPath = path.join(outDir, `${this.meta.slug}.html`);
|
|
421
|
+
const outPathDir = path.dirname(outPath);
|
|
422
|
+
if (!fs.existsSync(outPathDir))
|
|
423
|
+
fs.mkdirSync(outPathDir, { recursive: true });
|
|
414
424
|
fs.writeFileSync(outPath, html, "utf-8");
|
|
415
425
|
if (this.options.standalone === false) {
|
|
416
426
|
copyAssets(outDir);
|
|
@@ -586,9 +596,10 @@ export class ChapterBuilder {
|
|
|
586
596
|
const chapterData = { meta: this.meta, lessons };
|
|
587
597
|
const html = renderChapter(chapterData, this.options);
|
|
588
598
|
const outDir = path.resolve(this.options.outDir);
|
|
589
|
-
if (!fs.existsSync(outDir))
|
|
590
|
-
fs.mkdirSync(outDir, { recursive: true });
|
|
591
599
|
const outPath = path.join(outDir, `${this.meta.slug}.html`);
|
|
600
|
+
const outPathDir = path.dirname(outPath);
|
|
601
|
+
if (!fs.existsSync(outPathDir))
|
|
602
|
+
fs.mkdirSync(outPathDir, { recursive: true });
|
|
592
603
|
fs.writeFileSync(outPath, html, "utf-8");
|
|
593
604
|
if (this.options.standalone === false) {
|
|
594
605
|
copyAssets(outDir);
|
package/dist/cli/dev.d.ts.map
CHANGED
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAMA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,iBAwG1C"}
|
package/dist/cli/dev.js
CHANGED
|
@@ -12,7 +12,7 @@ export async function runDev(args) {
|
|
|
12
12
|
for (const entry of entryPoints) {
|
|
13
13
|
const entryPath = path.join(dir, entry);
|
|
14
14
|
if (fs.existsSync(entryPath)) {
|
|
15
|
-
exec(`NODE_ENV=development bun ${entryPath}`, (err, stdout, stderr) => {
|
|
15
|
+
exec(`NODE_ENV=development bun "${entryPath}"`, (err, stdout, stderr) => {
|
|
16
16
|
if (err)
|
|
17
17
|
console.error("Build failed:", stderr);
|
|
18
18
|
else {
|
|
@@ -45,8 +45,9 @@ export async function runDev(args) {
|
|
|
45
45
|
if (srv.upgrade(req))
|
|
46
46
|
return;
|
|
47
47
|
const url = new URL(req.url);
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
const decodedPath = decodeURIComponent(url.pathname);
|
|
49
|
+
let filePath = path.resolve(outDir, "." + decodedPath);
|
|
50
|
+
if (filePath.endsWith(path.sep)) {
|
|
50
51
|
const files = fs.existsSync(outDir) ? fs.readdirSync(outDir) : [];
|
|
51
52
|
const htmlFiles = files.filter(f => f.endsWith(".html"));
|
|
52
53
|
if (htmlFiles.includes("index.html")) {
|
|
@@ -61,24 +62,31 @@ export async function runDev(args) {
|
|
|
61
62
|
filePath = path.join(outDir, htmlFiles[0]);
|
|
62
63
|
}
|
|
63
64
|
else {
|
|
64
|
-
filePath
|
|
65
|
+
filePath = path.join(outDir, "index.html");
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
}
|
|
69
|
+
if (!filePath.startsWith(outDir + path.sep) && filePath !== outDir) {
|
|
70
|
+
return new Response("Forbidden", { status: 403 });
|
|
71
|
+
}
|
|
68
72
|
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
|
|
69
73
|
if (filePath.endsWith(".html")) {
|
|
70
74
|
const file = Bun.file(filePath);
|
|
71
75
|
let text = await file.text();
|
|
72
|
-
|
|
76
|
+
const lastBodyIndex = text.lastIndexOf("</body>");
|
|
77
|
+
if (lastBodyIndex !== -1) {
|
|
78
|
+
text = text.slice(0, lastBodyIndex) + `<script>
|
|
73
79
|
const ws = new WebSocket("ws://localhost:3000/");
|
|
74
80
|
ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
|
|
75
|
-
</script></body>`);
|
|
81
|
+
</script></body>` + text.slice(lastBodyIndex + 7);
|
|
82
|
+
}
|
|
76
83
|
return new Response(text, { headers: { "Content-Type": "text/html" } });
|
|
77
84
|
}
|
|
78
85
|
return new Response(Bun.file(filePath));
|
|
79
86
|
}
|
|
80
|
-
const
|
|
81
|
-
|
|
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()) {
|
|
82
90
|
return new Response(Bun.file(srcPath));
|
|
83
91
|
}
|
|
84
92
|
return new Response("Not found", { status: 404 });
|
package/dist/cli/generate.js
CHANGED
|
@@ -26,7 +26,7 @@ export async function runGenerate(args) {
|
|
|
26
26
|
console.error("Usage: md g <ch|le|qu|chapter|lesson|quiz> <name>");
|
|
27
27
|
process.exit(1);
|
|
28
28
|
}
|
|
29
|
-
const name = rawName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
29
|
+
const name = rawName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") || "item";
|
|
30
30
|
const cwd = process.cwd();
|
|
31
31
|
switch (type) {
|
|
32
32
|
case "ch":
|
package/dist/renderer/blocks.js
CHANGED
|
@@ -434,7 +434,7 @@ window.addEventListener("message", (event) => {
|
|
|
434
434
|
window.dispatchEvent(new CustomEvent("bk:props", { detail: window.__simProps }));
|
|
435
435
|
});
|
|
436
436
|
try {
|
|
437
|
-
${js}
|
|
437
|
+
${js.replace(/<\/script>/gi, "<\\/script>")}
|
|
438
438
|
} catch (e) {
|
|
439
439
|
console.error("Simulation Error:", e);
|
|
440
440
|
const errDiv = document.createElement('div');
|
|
@@ -39,7 +39,7 @@ function mdToHtml(md) {
|
|
|
39
39
|
});
|
|
40
40
|
// Restore code blocks
|
|
41
41
|
codeBlocks.forEach((match, id) => {
|
|
42
|
-
processedMd = processedMd.
|
|
42
|
+
processedMd = processedMd.replaceAll(`@@BK_CODE_${id}@@`, () => match);
|
|
43
43
|
});
|
|
44
44
|
const headings = [];
|
|
45
45
|
const idPrefix = Math.random().toString(36).substring(2, 6);
|
|
@@ -61,16 +61,16 @@ function mdToHtml(md) {
|
|
|
61
61
|
displayMode: true,
|
|
62
62
|
});
|
|
63
63
|
// marked might wrap block placeholders in <p>
|
|
64
|
-
html = html.
|
|
64
|
+
html = html.replaceAll(`<p>@@BK_MATH_BLOCK_${id}@@</p>`, () => `<div class="bk-math-block">${rendered}</div>`);
|
|
65
65
|
// Fallback if not wrapped in <p>
|
|
66
|
-
html = html.
|
|
66
|
+
html = html.replaceAll(`@@BK_MATH_BLOCK_${id}@@`, () => `<div class="bk-math-block">${rendered}</div>`);
|
|
67
67
|
});
|
|
68
68
|
mathInlines.forEach((tex, id) => {
|
|
69
69
|
const rendered = katex.renderToString(tex, {
|
|
70
70
|
throwOnError: false,
|
|
71
71
|
displayMode: false,
|
|
72
72
|
});
|
|
73
|
-
html = html.
|
|
73
|
+
html = html.replaceAll(`@@BK_MATH_INLINE_${id}@@`, () => rendered);
|
|
74
74
|
});
|
|
75
75
|
return { html, title, headings };
|
|
76
76
|
}
|
|
@@ -111,7 +111,7 @@ function mdInline(text) {
|
|
|
111
111
|
throwOnError: false,
|
|
112
112
|
displayMode: false,
|
|
113
113
|
});
|
|
114
|
-
html = html.
|
|
114
|
+
html = html.replaceAll(`@@BK_MATH_INLINE_${id}@@`, () => rendered);
|
|
115
115
|
});
|
|
116
116
|
return html;
|
|
117
117
|
}
|
|
@@ -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,
|
|
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"}
|
package/dist/renderer/utils.js
CHANGED
|
@@ -35,18 +35,13 @@ 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
|
-
|
|
39
|
-
|
|
38
|
+
const out = spawnSync("bun", ["build", "--target=browser", filePath]);
|
|
39
|
+
if (out.status === 0) {
|
|
40
|
+
return out.stdout.toString("utf-8");
|
|
40
41
|
}
|
|
41
42
|
else {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return out.stdout.toString("utf-8");
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
console.warn(`\n ⚠ Bun build failed for ${filePath}:\n${out.stderr.toString("utf-8")}`);
|
|
48
|
-
// fallback to reading raw
|
|
49
|
-
}
|
|
43
|
+
console.warn(`\n ⚠ Bun build failed for ${filePath}:\n${out.stderr.toString("utf-8")}`);
|
|
44
|
+
// fallback to reading raw
|
|
50
45
|
}
|
|
51
46
|
}
|
|
52
47
|
return fs.readFileSync(filePath, "utf-8");
|
|
@@ -61,12 +56,23 @@ function resolveContent(src, options, expectedType = "text") {
|
|
|
61
56
|
function resolveAssetSrc(src, options) {
|
|
62
57
|
if (/^(https?:|data:)/.test(src))
|
|
63
58
|
return src;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
const hashIndex = src.indexOf("#");
|
|
60
|
+
const queryIndex = src.indexOf("?");
|
|
61
|
+
const breakIndex = hashIndex !== -1 && queryIndex !== -1
|
|
62
|
+
? Math.min(hashIndex, queryIndex)
|
|
63
|
+
: Math.max(hashIndex, queryIndex);
|
|
64
|
+
let cleanSrc = src;
|
|
65
|
+
let suffix = "";
|
|
66
|
+
if (breakIndex !== -1) {
|
|
67
|
+
cleanSrc = src.substring(0, breakIndex);
|
|
68
|
+
suffix = src.substring(breakIndex);
|
|
69
|
+
}
|
|
70
|
+
let isWebAbsolute = cleanSrc.startsWith("/") && !fs.existsSync(cleanSrc);
|
|
71
|
+
let filePath = path.isAbsolute(cleanSrc)
|
|
72
|
+
? cleanSrc
|
|
73
|
+
: path.resolve(options.contentBase ?? ".", cleanSrc);
|
|
74
|
+
if (cleanSrc.startsWith("/") && !fs.existsSync(filePath)) {
|
|
75
|
+
const fallbackPath = path.resolve(options.contentBase ?? ".", cleanSrc.slice(1));
|
|
70
76
|
if (fs.existsSync(fallbackPath)) {
|
|
71
77
|
filePath = fallbackPath;
|
|
72
78
|
isWebAbsolute = false; // We found it locally, so don't treat it as a web URL
|
|
@@ -93,6 +99,6 @@ function resolveAssetSrc(src, options) {
|
|
|
93
99
|
if (!fs.existsSync(outPath)) {
|
|
94
100
|
fs.copyFileSync(filePath, outPath);
|
|
95
101
|
}
|
|
96
|
-
return `assets/${filename}`;
|
|
102
|
+
return `assets/${filename}${suffix}`;
|
|
97
103
|
}
|
|
98
104
|
export { resolveAssetSrc, resolveContent };
|
package/package.json
CHANGED
package/src/builder.ts
CHANGED
|
@@ -80,8 +80,15 @@ function copyAssets(outDir: string) {
|
|
|
80
80
|
|
|
81
81
|
const copyDir = (src: string, dest: string) => {
|
|
82
82
|
if (!fs.existsSync(src)) return;
|
|
83
|
+
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
|
83
84
|
for (const file of fs.readdirSync(src)) {
|
|
84
|
-
|
|
85
|
+
const srcFile = path.join(src, file);
|
|
86
|
+
const destFile = path.join(dest, file);
|
|
87
|
+
if (fs.statSync(srcFile).isDirectory()) {
|
|
88
|
+
copyDir(srcFile, destFile);
|
|
89
|
+
} else {
|
|
90
|
+
fs.copyFileSync(srcFile, destFile);
|
|
91
|
+
}
|
|
85
92
|
}
|
|
86
93
|
};
|
|
87
94
|
|
|
@@ -525,9 +532,11 @@ export class LessonBuilder {
|
|
|
525
532
|
const html = render(lesson, this.options);
|
|
526
533
|
|
|
527
534
|
const outDir = path.resolve(this.options.outDir as string);
|
|
528
|
-
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
|
529
|
-
|
|
530
535
|
const outPath = path.join(outDir, `${this.meta.slug}.html`);
|
|
536
|
+
const outPathDir = path.dirname(outPath);
|
|
537
|
+
|
|
538
|
+
if (!fs.existsSync(outPathDir)) fs.mkdirSync(outPathDir, { recursive: true });
|
|
539
|
+
|
|
531
540
|
fs.writeFileSync(outPath, html, "utf-8");
|
|
532
541
|
|
|
533
542
|
if (this.options.standalone === false) {
|
|
@@ -750,9 +759,11 @@ export class ChapterBuilder {
|
|
|
750
759
|
const html = renderChapter(chapterData, this.options);
|
|
751
760
|
|
|
752
761
|
const outDir = path.resolve(this.options.outDir as string);
|
|
753
|
-
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
|
754
|
-
|
|
755
762
|
const outPath = path.join(outDir, `${this.meta.slug}.html`);
|
|
763
|
+
const outPathDir = path.dirname(outPath);
|
|
764
|
+
|
|
765
|
+
if (!fs.existsSync(outPathDir)) fs.mkdirSync(outPathDir, { recursive: true });
|
|
766
|
+
|
|
756
767
|
fs.writeFileSync(outPath, html, "utf-8");
|
|
757
768
|
|
|
758
769
|
if (this.options.standalone === false) {
|
package/src/cli/dev.ts
CHANGED
|
@@ -18,7 +18,7 @@ export async function runDev(args: string[]) {
|
|
|
18
18
|
for (const entry of entryPoints) {
|
|
19
19
|
const entryPath = path.join(dir, entry);
|
|
20
20
|
if (fs.existsSync(entryPath)) {
|
|
21
|
-
exec(`NODE_ENV=development bun ${entryPath}`, (err, stdout, stderr) => {
|
|
21
|
+
exec(`NODE_ENV=development bun "${entryPath}"`, (err, stdout, stderr) => {
|
|
22
22
|
if (err) console.error("Build failed:", stderr);
|
|
23
23
|
else {
|
|
24
24
|
console.log("Build successful.");
|
|
@@ -53,9 +53,10 @@ export async function runDev(args: string[]) {
|
|
|
53
53
|
if (srv.upgrade(req)) return;
|
|
54
54
|
|
|
55
55
|
const url = new URL(req.url);
|
|
56
|
-
|
|
56
|
+
const decodedPath = decodeURIComponent(url.pathname);
|
|
57
|
+
let filePath = path.resolve(outDir, "." + decodedPath);
|
|
57
58
|
|
|
58
|
-
if (filePath.endsWith(
|
|
59
|
+
if (filePath.endsWith(path.sep)) {
|
|
59
60
|
const files = fs.existsSync(outDir) ? fs.readdirSync(outDir) : [];
|
|
60
61
|
const htmlFiles = files.filter(f => f.endsWith(".html"));
|
|
61
62
|
if (htmlFiles.includes("index.html")) {
|
|
@@ -67,26 +68,34 @@ export async function runDev(args: string[]) {
|
|
|
67
68
|
} else if (htmlFiles.length > 0) {
|
|
68
69
|
filePath = path.join(outDir, htmlFiles[0]);
|
|
69
70
|
} else {
|
|
70
|
-
filePath
|
|
71
|
+
filePath = path.join(outDir, "index.html");
|
|
71
72
|
}
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
|
|
76
|
+
if (!filePath.startsWith(outDir + path.sep) && filePath !== outDir) {
|
|
77
|
+
return new Response("Forbidden", { status: 403 });
|
|
78
|
+
}
|
|
79
|
+
|
|
75
80
|
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
|
|
76
81
|
if (filePath.endsWith(".html")) {
|
|
77
82
|
const file = Bun.file(filePath);
|
|
78
83
|
let text = await file.text();
|
|
79
|
-
|
|
84
|
+
const lastBodyIndex = text.lastIndexOf("</body>");
|
|
85
|
+
if (lastBodyIndex !== -1) {
|
|
86
|
+
text = text.slice(0, lastBodyIndex) + `<script>
|
|
80
87
|
const ws = new WebSocket("ws://localhost:3000/");
|
|
81
88
|
ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
|
|
82
|
-
</script></body>`);
|
|
89
|
+
</script></body>` + text.slice(lastBodyIndex + 7);
|
|
90
|
+
}
|
|
83
91
|
return new Response(text, { headers: { "Content-Type": "text/html" } });
|
|
84
92
|
}
|
|
85
93
|
return new Response(Bun.file(filePath));
|
|
86
94
|
}
|
|
87
95
|
|
|
88
|
-
const
|
|
89
|
-
|
|
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()) {
|
|
90
99
|
return new Response(Bun.file(srcPath));
|
|
91
100
|
}
|
|
92
101
|
|
package/src/cli/generate.ts
CHANGED
|
@@ -32,7 +32,7 @@ export async function runGenerate(args: string[]) {
|
|
|
32
32
|
process.exit(1);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
const name = rawName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
|
|
35
|
+
const name = rawName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "") || "item";
|
|
36
36
|
const cwd = process.cwd();
|
|
37
37
|
|
|
38
38
|
switch (type) {
|
package/src/renderer/blocks.ts
CHANGED
|
@@ -522,7 +522,7 @@ window.addEventListener("message", (event) => {
|
|
|
522
522
|
window.dispatchEvent(new CustomEvent("bk:props", { detail: window.__simProps }));
|
|
523
523
|
});
|
|
524
524
|
try {
|
|
525
|
-
${js}
|
|
525
|
+
${js.replace(/<\/script>/gi, "<\\/script>")}
|
|
526
526
|
} catch (e) {
|
|
527
527
|
console.error("Simulation Error:", e);
|
|
528
528
|
const errDiv = document.createElement('div');
|
package/src/renderer/markdown.ts
CHANGED
|
@@ -52,7 +52,7 @@ function mdToHtml(md: string): { html: string; title: string; headings: { id: st
|
|
|
52
52
|
|
|
53
53
|
// Restore code blocks
|
|
54
54
|
codeBlocks.forEach((match, id) => {
|
|
55
|
-
processedMd = processedMd.
|
|
55
|
+
processedMd = processedMd.replaceAll(`@@BK_CODE_${id}@@`, () => match);
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
const headings: { id: string; text: string; level: number }[] = [];
|
|
@@ -78,12 +78,12 @@ function mdToHtml(md: string): { html: string; title: string; headings: { id: st
|
|
|
78
78
|
displayMode: true,
|
|
79
79
|
});
|
|
80
80
|
// marked might wrap block placeholders in <p>
|
|
81
|
-
html = html.
|
|
81
|
+
html = html.replaceAll(
|
|
82
82
|
`<p>@@BK_MATH_BLOCK_${id}@@</p>`,
|
|
83
83
|
() => `<div class="bk-math-block">${rendered}</div>`,
|
|
84
84
|
);
|
|
85
85
|
// Fallback if not wrapped in <p>
|
|
86
|
-
html = html.
|
|
86
|
+
html = html.replaceAll(
|
|
87
87
|
`@@BK_MATH_BLOCK_${id}@@`,
|
|
88
88
|
() => `<div class="bk-math-block">${rendered}</div>`,
|
|
89
89
|
);
|
|
@@ -94,7 +94,7 @@ function mdToHtml(md: string): { html: string; title: string; headings: { id: st
|
|
|
94
94
|
throwOnError: false,
|
|
95
95
|
displayMode: false,
|
|
96
96
|
});
|
|
97
|
-
html = html.
|
|
97
|
+
html = html.replaceAll(`@@BK_MATH_INLINE_${id}@@`, () => rendered);
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
return { html, title, headings };
|
|
@@ -150,7 +150,7 @@ function mdInline(text: string): string {
|
|
|
150
150
|
throwOnError: false,
|
|
151
151
|
displayMode: false,
|
|
152
152
|
});
|
|
153
|
-
html = html.
|
|
153
|
+
html = html.replaceAll(`@@BK_MATH_INLINE_${id}@@`, () => rendered);
|
|
154
154
|
});
|
|
155
155
|
|
|
156
156
|
return html;
|
package/src/renderer/utils.ts
CHANGED
|
@@ -54,16 +54,12 @@ 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
|
-
|
|
58
|
-
|
|
57
|
+
const out = spawnSync("bun", ["build", "--target=browser", filePath]);
|
|
58
|
+
if (out.status === 0) {
|
|
59
|
+
return out.stdout.toString("utf-8");
|
|
59
60
|
} else {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return out.stdout.toString("utf-8");
|
|
63
|
-
} else {
|
|
64
|
-
console.warn(`\n ⚠ Bun build failed for ${filePath}:\n${out.stderr.toString("utf-8")}`);
|
|
65
|
-
// fallback to reading raw
|
|
66
|
-
}
|
|
61
|
+
console.warn(`\n ⚠ Bun build failed for ${filePath}:\n${out.stderr.toString("utf-8")}`);
|
|
62
|
+
// fallback to reading raw
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
65
|
return fs.readFileSync(filePath, "utf-8");
|
|
@@ -83,14 +79,27 @@ function resolveContent(
|
|
|
83
79
|
function resolveAssetSrc(src: string, options: BuildOptions): string {
|
|
84
80
|
if (/^(https?:|data:)/.test(src)) return src;
|
|
85
81
|
|
|
86
|
-
|
|
82
|
+
const hashIndex = src.indexOf("#");
|
|
83
|
+
const queryIndex = src.indexOf("?");
|
|
84
|
+
const breakIndex = hashIndex !== -1 && queryIndex !== -1
|
|
85
|
+
? Math.min(hashIndex, queryIndex)
|
|
86
|
+
: Math.max(hashIndex, queryIndex);
|
|
87
|
+
|
|
88
|
+
let cleanSrc = src;
|
|
89
|
+
let suffix = "";
|
|
90
|
+
if (breakIndex !== -1) {
|
|
91
|
+
cleanSrc = src.substring(0, breakIndex);
|
|
92
|
+
suffix = src.substring(breakIndex);
|
|
93
|
+
}
|
|
87
94
|
|
|
88
|
-
let
|
|
89
|
-
? src
|
|
90
|
-
: path.resolve(options.contentBase ?? ".", src);
|
|
95
|
+
let isWebAbsolute = cleanSrc.startsWith("/") && !fs.existsSync(cleanSrc);
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
let filePath = path.isAbsolute(cleanSrc)
|
|
98
|
+
? cleanSrc
|
|
99
|
+
: path.resolve(options.contentBase ?? ".", cleanSrc);
|
|
100
|
+
|
|
101
|
+
if (cleanSrc.startsWith("/") && !fs.existsSync(filePath)) {
|
|
102
|
+
const fallbackPath = path.resolve(options.contentBase ?? ".", cleanSrc.slice(1));
|
|
94
103
|
if (fs.existsSync(fallbackPath)) {
|
|
95
104
|
filePath = fallbackPath;
|
|
96
105
|
isWebAbsolute = false; // We found it locally, so don't treat it as a web URL
|
|
@@ -121,7 +130,7 @@ function resolveAssetSrc(src: string, options: BuildOptions): string {
|
|
|
121
130
|
fs.copyFileSync(filePath, outPath);
|
|
122
131
|
}
|
|
123
132
|
|
|
124
|
-
return `assets/${filename}`;
|
|
133
|
+
return `assets/${filename}${suffix}`;
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
export { resolveAssetSrc, resolveContent };
|