mr-md 1.1.0-alpha.0 → 2.1.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.
Files changed (40) hide show
  1. package/README.md +1 -1
  2. package/dist/builder.d.ts +1 -1
  3. package/dist/builder.d.ts.map +1 -1
  4. package/dist/builder.js +57 -33
  5. package/dist/cli/init.d.ts.map +1 -1
  6. package/dist/cli/init.js +42 -1
  7. package/dist/cli.js +0 -0
  8. package/dist/client/app.js +182 -33
  9. package/dist/renderer/blocks.d.ts.map +1 -1
  10. package/dist/renderer/blocks.js +53 -11
  11. package/dist/renderer/html-neo.d.ts +7 -0
  12. package/dist/renderer/html-neo.d.ts.map +1 -0
  13. package/dist/renderer/html-neo.js +173 -0
  14. package/dist/renderer/html.d.ts +4 -2
  15. package/dist/renderer/html.d.ts.map +1 -1
  16. package/dist/renderer/html.js +62 -34
  17. package/dist/renderer/index-neo.d.ts +4 -0
  18. package/dist/renderer/index-neo.d.ts.map +1 -0
  19. package/dist/renderer/index-neo.js +469 -0
  20. package/dist/renderer/index.d.ts.map +1 -1
  21. package/dist/renderer/index.js +170 -324
  22. package/dist/renderer/markdown.d.ts.map +1 -1
  23. package/dist/renderer/markdown.js +44 -7
  24. package/dist/renderer/utils.d.ts.map +1 -1
  25. package/dist/renderer/utils.js +14 -5
  26. package/dist/styles/theme-neo.css +1369 -0
  27. package/dist/styles/theme.css +559 -170
  28. package/dist/types.d.ts +11 -1
  29. package/dist/types.d.ts.map +1 -1
  30. package/package.json +6 -5
  31. package/src/builder.ts +68 -44
  32. package/src/cli/init.ts +44 -1
  33. package/src/client/app.js +182 -33
  34. package/src/renderer/blocks.ts +53 -11
  35. package/src/renderer/html.ts +86 -36
  36. package/src/renderer/index.ts +178 -324
  37. package/src/renderer/markdown.ts +49 -9
  38. package/src/renderer/utils.ts +14 -5
  39. package/src/styles/theme.css +559 -170
  40. package/src/types.ts +11 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mr Markdown
2
2
 
3
- Mr Markdown is an opinionated TypeScript SDK for building interactive, single-file learning pages. It is designed for lessons that mix prose, LaTeX, simulations, media, video, and quizzes without making every author build layout and interaction chrome from scratch.
3
+ Mr Markdown is an opinionated TypeScript SDK for building interactive learning pages. It is designed for lessons that mix prose, LaTeX, simulations, media, video, and quizzes without making every author build layout and interaction chrome from scratch.
4
4
 
5
5
  ## Documentation
6
6
 
package/dist/builder.d.ts CHANGED
@@ -44,7 +44,7 @@ export declare class LessonBuilder {
44
44
  add(src: `${string}.mp4` | `${string}.webm` | `${string}.mov`, opts?: Omit<MediaOptions, "kind">): this;
45
45
  add(src: `${string}.mp3` | `${string}.wav` | `${string}.ogg` | `${string}.m4a`, opts?: Omit<MediaOptions, "kind">): this;
46
46
  add(src: `${string}.png` | `${string}.jpg` | `${string}.jpeg` | `${string}.gif` | `${string}.svg` | `${string}.webp` | `${string}.avif`, opts?: Omit<MediaOptions, "kind">): this;
47
- add(src: string, opts?: any): this;
47
+ add(src: string, opts?: unknown): this;
48
48
  /**
49
49
  * Creates a major chapter heading (H1) and a top-level sidebar navigation entry.
50
50
  * @param src Path to a markdown file or raw markdown string.
@@ -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
@@ -1,7 +1,9 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
3
  import { render, renderChapter } from "./renderer/index.js";
4
- import { copyCoreAssets } from "./renderer/html.js";
4
+ import { fileURLToPath } from "url";
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
5
7
  function getCallerDir() {
6
8
  const err = new Error();
7
9
  const stack = err.stack?.split("\n");
@@ -17,7 +19,7 @@ function getCallerDir() {
17
19
  p = p.replace(/^file:\/\//, "");
18
20
  }
19
21
  if (p.startsWith("/") && p[2] === ":") {
20
- p = p.substring(1); // Handle Windows paths like /C:/
22
+ p = p.substring(1);
21
23
  }
22
24
  if (!builderFilePath) {
23
25
  builderFilePath = p;
@@ -31,6 +33,51 @@ function getCallerDir() {
31
33
  }
32
34
  return undefined;
33
35
  }
36
+ function copyAssets(outDir) {
37
+ const assetsDir = path.join(outDir, "assets");
38
+ if (!fs.existsSync(assetsDir))
39
+ fs.mkdirSync(assetsDir, { recursive: true });
40
+ const srcStylesDir = path.join(__dirname, "styles");
41
+ const srcClientDir = path.join(__dirname, "client");
42
+ const fallbackStylesDir = path.join(__dirname, "../src/styles");
43
+ const fallbackClientDir = path.join(__dirname, "../src/client");
44
+ const copyDir = (src, dest) => {
45
+ if (!fs.existsSync(src))
46
+ return;
47
+ for (const file of fs.readdirSync(src)) {
48
+ fs.copyFileSync(path.join(src, file), path.join(dest, file));
49
+ }
50
+ };
51
+ if (fs.existsSync(srcStylesDir))
52
+ copyDir(srcStylesDir, assetsDir);
53
+ else
54
+ copyDir(fallbackStylesDir, assetsDir);
55
+ if (fs.existsSync(srcClientDir))
56
+ copyDir(srcClientDir, assetsDir);
57
+ else
58
+ copyDir(fallbackClientDir, assetsDir);
59
+ }
60
+ function mergeOptions(options, callerDir) {
61
+ const merged = {
62
+ outDir: options.outDir ?? (callerDir ? path.join(callerDir, "out") : path.join(process.cwd(), "out")),
63
+ contentBase: options.contentBase ?? callerDir ?? process.cwd(),
64
+ theme: options.theme ?? "auto",
65
+ palette: options.palette ?? "ink",
66
+ strict: options.strict ?? process.env.NODE_ENV !== "development",
67
+ standalone: options.standalone ?? true,
68
+ };
69
+ for (const [k, v] of Object.entries(options)) {
70
+ if (v !== undefined && k !== "preset") {
71
+ merged[k] = v;
72
+ }
73
+ }
74
+ merged.preset = {
75
+ layout: options.preset?.layout ?? "lesson",
76
+ density: options.preset?.density ?? "comfortable",
77
+ tone: options.preset?.tone ?? "scholarly",
78
+ };
79
+ return merged;
80
+ }
34
81
  // ─── LessonBuilder ────────────────────────────────────────────────────────────
35
82
  export class LessonBuilder {
36
83
  meta;
@@ -49,20 +96,7 @@ export class LessonBuilder {
49
96
  title,
50
97
  slug,
51
98
  };
52
- this.options = {
53
- outDir: options.outDir ?? (callerDir ? path.join(callerDir, "out") : "./out"),
54
- contentBase: options.contentBase ?? callerDir ?? ".",
55
- theme: options.theme ?? "light",
56
- palette: options.palette ?? "ink",
57
- strict: options.strict ?? process.env.NODE_ENV !== "development",
58
- preset: {
59
- layout: "lesson",
60
- density: "comfortable",
61
- tone: "scholarly",
62
- ...options.preset,
63
- },
64
- ...options,
65
- };
99
+ this.options = mergeOptions(options, callerDir);
66
100
  }
67
101
  // ── Meta setters ────────────────────────────────────────────────────────────
68
102
  /**
@@ -142,7 +176,6 @@ export class LessonBuilder {
142
176
  _getMeta() {
143
177
  return this.meta;
144
178
  }
145
- // biome-ignore lint/suspicious/noExplicitAny: Overload implementation
146
179
  add(src, opts = {}) {
147
180
  const lower = src.toLowerCase();
148
181
  if (lower.endsWith(".md") || lower.endsWith(".mdx"))
@@ -379,7 +412,9 @@ export class LessonBuilder {
379
412
  fs.mkdirSync(outDir, { recursive: true });
380
413
  const outPath = path.join(outDir, `${this.meta.slug}.html`);
381
414
  fs.writeFileSync(outPath, html, "utf-8");
382
- copyCoreAssets(outDir);
415
+ if (this.options.standalone === false) {
416
+ copyAssets(outDir);
417
+ }
383
418
  const relPath = path.relative(process.cwd(), outPath);
384
419
  console.log(` ✓ Built lesson (${this.blocks.length} blocks) → ${relPath}`);
385
420
  return outPath;
@@ -507,20 +542,7 @@ export class ChapterBuilder {
507
542
  title,
508
543
  slug,
509
544
  };
510
- this.options = {
511
- outDir: options.outDir ?? (callerDir ? path.join(callerDir, "out") : "./out"),
512
- contentBase: options.contentBase ?? callerDir ?? ".",
513
- theme: options.theme ?? "light",
514
- palette: options.palette ?? "ink",
515
- strict: options.strict ?? process.env.NODE_ENV !== "development",
516
- preset: {
517
- layout: "lesson",
518
- density: "comfortable",
519
- tone: "scholarly",
520
- ...options.preset,
521
- },
522
- ...options,
523
- };
545
+ this.options = mergeOptions(options, callerDir);
524
546
  }
525
547
  slug(slug) {
526
548
  this.meta.slug = slug;
@@ -568,7 +590,9 @@ export class ChapterBuilder {
568
590
  fs.mkdirSync(outDir, { recursive: true });
569
591
  const outPath = path.join(outDir, `${this.meta.slug}.html`);
570
592
  fs.writeFileSync(outPath, html, "utf-8");
571
- copyCoreAssets(outDir);
593
+ if (this.options.standalone === false) {
594
+ copyAssets(outDir);
595
+ }
572
596
  const relPath = path.relative(process.cwd(), outPath);
573
597
  console.log(` ✓ Built chapter (${this.lessonBuilders.length} lessons) → ${relPath}`);
574
598
  return outPath;
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAGA,wBAAsB,OAAO,kBAkD5B"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAGA,wBAAsB,OAAO,kBA6F5B"}
package/dist/cli/init.js CHANGED
@@ -44,5 +44,46 @@ export const firstLesson = lesson("First Lesson", { contentBase: import.meta.dir
44
44
  `, "utf-8");
45
45
  console.log(" Created: chapters/01-chapter/lessons/01-lesson/lesson.ts");
46
46
  }
47
- console.log("Done! You can now run `bun chapters/01-chapter/chapter.ts` to build your project.");
47
+ const packageJsonPath = path.resolve(process.cwd(), "package.json");
48
+ let pkg = {};
49
+ if (fs.existsSync(packageJsonPath)) {
50
+ try {
51
+ pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
52
+ }
53
+ catch (e) {
54
+ console.error(" Failed to parse existing package.json, ignoring.");
55
+ }
56
+ }
57
+ else {
58
+ pkg = {
59
+ name: "my-md-project",
60
+ version: "1.0.0",
61
+ private: true
62
+ };
63
+ }
64
+ pkg.scripts = {
65
+ ...(pkg.scripts || {}),
66
+ build: "bun chapters/01-chapter/chapter.ts",
67
+ dev: "md dev",
68
+ g: "md g",
69
+ generate: "md generate"
70
+ };
71
+ let mrMdVersion = "latest";
72
+ try {
73
+ // Find mr-md's own package.json to get its version
74
+ const __dirname = path.dirname(new URL(import.meta.url).pathname);
75
+ const ownPkgPath = path.resolve(__dirname, "../../package.json");
76
+ const ownPkg = JSON.parse(fs.readFileSync(ownPkgPath, "utf-8"));
77
+ mrMdVersion = ownPkg.version;
78
+ }
79
+ catch (e) {
80
+ // Fallback if unable to read
81
+ }
82
+ pkg.dependencies = {
83
+ ...(pkg.dependencies || {}),
84
+ "mr-md": mrMdVersion
85
+ };
86
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
87
+ console.log(" Updated: package.json");
88
+ console.log("\nDone! You can now run `npm run dev` or `bun run dev` to start the local development server.");
48
89
  }
package/dist/cli.js CHANGED
File without changes
@@ -15,11 +15,10 @@ function bkSimDoc(js, props, loop, dependencies) {
15
15
  ";window.bkSetupCalled=false;" +
16
16
  'window.bkCanvasPoint=function(e,c){const r=(c||e.currentTarget||e.target).getBoundingClientRect(),w=(c&&c.__bkLogicalW)||800,h=(c&&c.__bkLogicalH)||500;return{x:(e.clientX-r.left)*w/r.width,y:(e.clientY-r.top)*h/r.height}};' +
17
17
  'window.bkFitCanvas=function(c,reqW,reqH,o){if(!c)return{scale:1,width:reqW,height:reqH,cssScale:1};const d=window.devicePixelRatio||1;const w=reqW;const h=reqH;c.__bkLogicalW=w;c.__bkLogicalH=h;c.style.width=w+"px";c.style.height=h+"px";c.style.position="relative";c.style.left="auto";c.style.top="auto";c.style.transformOrigin="center center";const sx=window.innerWidth/w,sy=window.innerHeight/h,cssS=Math.max(sx,sy);c.style.transform="scale("+cssS+")";const pw=Math.max(1,Math.round(w*d)),ph=Math.max(1,Math.round(h*d));if(!o||o.bitmap!==false){if(c.width!==pw||c.height!==ph){c.width=pw;c.height=ph}}return{scale:d,width:w,height:h,cssScale:cssS}};' +
18
- 'window.bkSetup=function(w,h,f){window.bkSetupCalled=true;const c=document.getElementById("c");if(!c)return;const ctx=c.getContext("2d");let loopId=null;let fit=window.bkFitCanvas(c,w,h);function l(){if(window.innerWidth>=32&&window.innerHeight>=32){ctx.save();ctx.scale(fit.scale,fit.scale);f(ctx,fit.width,fit.height);ctx.restore()}if(window.__loop){loopId=requestAnimationFrame(l)}else{loopId=null}}function i(){if(window.innerWidth>=32&&window.innerHeight>=32){fit=window.bkFitCanvas(c,w,h);l()}else{requestAnimationFrame(i)}}i();window.addEventListener("resize",function(){fit=window.bkFitCanvas(c,w,h);if(!window.__loop&&window.innerWidth>=32&&window.innerHeight>=32&&!loopId){ctx.save();ctx.scale(fit.scale,fit.scale);f(ctx,fit.width,fit.height);ctx.restore()}});window.addEventListener("message",function(event){if(!event.data)return;if(event.data.type==="bk:play"){window.__loop=true;if(!loopId)loopId=requestAnimationFrame(l)}else if(event.data.type==="bk:pause"){window.__loop=false}});};' +
19
- 'window.addEventListener("message",function(event){if(!event.data||event.data.type!=="bk:set-props")return;window.__simProps=Object.assign({},window.__simProps,event.data.props);window.dispatchEvent(new CustomEvent("bk:props",{detail:window.__simProps}));});' +
18
+ 'window.bkSetup=function(w,h,f){window.bkSetupCalled=true;const c=document.getElementById("c");if(!c)return;const ctx=c.getContext("2d");let loopId=null;let fit=window.bkFitCanvas(c,w,h);function l(){if(window.innerWidth>=32&&window.innerHeight>=32){ctx.save();ctx.scale(fit.scale,fit.scale);f(ctx,fit.width,fit.height);ctx.restore()}if(window.__loop){loopId=requestAnimationFrame(l)}else{loopId=null}}function i(){if(window.innerWidth>=32&&window.innerHeight>=32){fit=window.bkFitCanvas(c,w,h);l()}else{requestAnimationFrame(i)}}i();window.addEventListener("resize",function(){fit=window.bkFitCanvas(c,w,h);if(!window.__loop&&window.innerWidth>=32&&window.innerHeight>=32&&!loopId){ctx.save();ctx.scale(fit.scale,fit.scale);f(ctx,fit.width,fit.height);ctx.restore()}});window.addEventListener("message",function(event){if(event.source!==window.parent)return;if(!event.data)return;if(event.data.type==="bk:play"){window.__loop=true;if(!loopId)loopId=requestAnimationFrame(l)}else if(event.data.type==="bk:pause"){window.__loop=false}else if(event.data.type==="bk:set-props"){window.__simProps=Object.assign({},window.__simProps,event.data.props);window.dispatchEvent(new CustomEvent("bk:props",{detail:window.__simProps}));}});};' +
20
19
  "try{" +
21
20
  js +
22
- '}catch(e){console.error("Simulation Error:",e);document.body.innerHTML="<div style=\'padding: 20px; color: red; font-family: monospace;\'>Error: "+e.message+"</div>"}' +
21
+ '}catch(e){console.error("Simulation Error:",e);const d=document.createElement("div");d.style.cssText="padding:20px;color:red;font-family:monospace";d.textContent="Error: "+e.message;document.body.innerHTML="";document.body.appendChild(d);}' +
23
22
  "if(!window.bkSetupCalled){function fallbackScale(){window.bkFitCanvas(document.getElementById('c'),800,500,{bitmap:false});}fallbackScale();window.addEventListener('resize', fallbackScale);}" +
24
23
  "</" + "script></body></html>"
25
24
  );
@@ -76,27 +75,14 @@ function bkWireMaximizeControls() {
76
75
  }
77
76
 
78
77
  function bkWireInteractiveFrames() {
79
- const activate = (e) => {
78
+ const interactiveHandler = (e) => {
80
79
  const obj = e.target.closest?.(".bk-object");
81
- if (!obj) return;
82
- const frame = obj.querySelector(".bk-embed-interactive");
83
- if (frame) {
84
- frame.classList.add("is-interactive");
85
- const iframe = frame.querySelector("iframe");
86
- if (iframe && iframe.contentWindow) {
87
- iframe.contentWindow.postMessage({ type: "bk:play" }, "*");
88
- }
89
- }
90
- };
91
- document.addEventListener("pointerdown", activate, { passive: true });
92
- document.addEventListener("focusin", activate, { passive: true });
80
+ const activateFrame = obj ? obj.querySelector(".bk-embed-interactive") : null;
93
81
 
94
- const exitInteractive = (e) => {
95
82
  document
96
83
  .querySelectorAll(".bk-embed-interactive.is-interactive")
97
84
  .forEach((frame) => {
98
- const container = frame.closest(".bk-object") || frame;
99
- if (!container.contains(e.target)) {
85
+ if (frame !== activateFrame) {
100
86
  frame.classList.remove("is-interactive");
101
87
  const iframe = frame.querySelector("iframe");
102
88
  if (iframe && iframe.contentWindow) {
@@ -104,9 +90,17 @@ function bkWireInteractiveFrames() {
104
90
  }
105
91
  }
106
92
  });
93
+
94
+ if (activateFrame && !activateFrame.classList.contains("is-interactive")) {
95
+ activateFrame.classList.add("is-interactive");
96
+ const iframe = activateFrame.querySelector("iframe");
97
+ if (iframe && iframe.contentWindow) {
98
+ iframe.contentWindow.postMessage({ type: "bk:play" }, "*");
99
+ }
100
+ }
107
101
  };
108
- document.addEventListener("pointerdown", exitInteractive, { passive: true });
109
- document.addEventListener("focusin", exitInteractive, { passive: true });
102
+ document.addEventListener("pointerdown", interactiveHandler, { passive: true });
103
+ document.addEventListener("focusin", interactiveHandler, { passive: true });
110
104
 
111
105
  const obs = new IntersectionObserver((entries) => {
112
106
  entries.forEach((e) => {
@@ -132,6 +126,22 @@ function bkWireInteractiveFrames() {
132
126
  document.querySelectorAll(".bk-embed-interactive").forEach((frame) => {
133
127
  obs.observe(frame);
134
128
  });
129
+
130
+ document.addEventListener('contentvisibilityautostatechange', (e) => {
131
+ const frame = e.target;
132
+ if (frame && frame.classList && frame.classList.contains('bk-embed-interactive')) {
133
+ const iframe = frame.querySelector('iframe');
134
+ if (!iframe || !iframe.contentWindow) return;
135
+
136
+ if (e.skipped) {
137
+ iframe.contentWindow.postMessage({ type: "bk:pause" }, "*");
138
+ } else {
139
+ if (frame.dataset.isAnimation === "true" || frame.classList.contains("is-interactive")) {
140
+ iframe.contentWindow.postMessage({ type: "bk:play" }, "*");
141
+ }
142
+ }
143
+ }
144
+ }, { capture: true });
135
145
  }
136
146
 
137
147
  function bkWireSidebarToggle() {
@@ -148,15 +158,61 @@ function bkWireSidebarToggle() {
148
158
  );
149
159
  }
150
160
 
161
+ function bkBroadcastTheme(targetWindow) {
162
+ const root = document.documentElement;
163
+ const styles = getComputedStyle(root);
164
+ const state = {
165
+ theme: root.dataset.theme || "light",
166
+ palette: root.dataset.palette || "ink",
167
+ ui: root.dataset.ui || "standard",
168
+ colors: {
169
+ bg: styles.getPropertyValue('--bg').trim(),
170
+ paper: styles.getPropertyValue('--paper').trim(),
171
+ line: styles.getPropertyValue('--line').trim(),
172
+ 'line-strong': styles.getPropertyValue('--line-strong').trim(),
173
+ text: styles.getPropertyValue('--text').trim(),
174
+ 'text-light': styles.getPropertyValue('--text-light').trim(),
175
+ accent: styles.getPropertyValue('--accent').trim(),
176
+ 'accent-soft': styles.getPropertyValue('--accent-soft').trim()
177
+ }
178
+ };
179
+ if (targetWindow) {
180
+ targetWindow.postMessage({ type: "bk:theme-sync", state }, "*");
181
+ } else {
182
+ document.querySelectorAll(".bk-embed-interactive iframe").forEach(iframe => {
183
+ if (iframe.contentWindow) iframe.contentWindow.postMessage({ type: "bk:theme-sync", state }, "*");
184
+ });
185
+ }
186
+ }
187
+
188
+ window.addEventListener("message", function(e) {
189
+ const isValidSource = Array.from(document.querySelectorAll("iframe")).some(f => f.contentWindow === e.source);
190
+ if (!isValidSource) return;
191
+
192
+ if (e.data && e.data.type === "bk:request-theme") {
193
+ // Small delay to ensure CSS has applied if this happens right on load
194
+ requestAnimationFrame(() => bkBroadcastTheme(e.source));
195
+ }
196
+ });
197
+
198
+ // Watch for OS theme changes if on auto
199
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
200
+ if (document.documentElement.dataset.theme === "auto") {
201
+ bkBroadcastTheme();
202
+ }
203
+ });
204
+
151
205
  function bkWireThemeControls() {
152
206
  const root = document.documentElement;
153
207
  const button = document.getElementById("bk-settings-button");
154
208
  const panel = document.getElementById("bk-theme-panel");
155
209
  const themeBtns = document.querySelectorAll("#bk-theme-icons button");
156
- const paletteBtns = document.querySelectorAll("#bk-palette-icons button");
210
+ const paletteBtns = document.querySelectorAll("#bk-palette-icons button");
211
+ const uiBtns = document.querySelectorAll("#bk-ui-icons button");
157
212
  let savedTheme = localStorage.getItem("bk-theme");
158
213
  if (!savedTheme) savedTheme = "auto";
159
214
  const savedPalette = localStorage.getItem("bk-palette");
215
+ const savedUi = localStorage.getItem("bk-ui");
160
216
 
161
217
  function updateThemeBtn(val) {
162
218
  themeBtns.forEach(b => {
@@ -165,9 +221,42 @@ function bkWireThemeControls() {
165
221
  });
166
222
  }
167
223
 
224
+ const proPalettes = {
225
+ ink: "elixir",
226
+ field: "trunk",
227
+ ember: "lava"
228
+ };
229
+
230
+ const proIcons = {
231
+ elixir: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 3v4.4L4.8 14.5a2.5 2.5 0 0 0 2.2 3.5h10a2.5 2.5 0 0 0 2.2-3.5L15 7.4V3"></path><path d="M9 14h6"></path><path d="M10 3h4"></path></svg>',
232
+ trunk: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m8 3 4 8 5-5 5 15H2L8 3z"></path></svg>',
233
+ lava: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m3 21 4.5-9"></path><path d="M16.5 12 21 21"></path><path d="m11 21 1.4-2.8"></path><path d="m15 21-1.4-2.8"></path><path d="M11 6a3 3 0 0 1 2-2 3 3 0 0 1 2 2"></path><path d="M12 12a3 3 0 0 0 3-3"></path><path d="M9 12a3 3 0 0 1-3-3"></path><path d="M12 21v-3.5"></path><path d="M10 18h4"></path></svg>'
234
+ };
235
+
236
+ const normalIcons = {
237
+ ink: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2.69l5.66 5.66a8 8 0 1 1-11.31 0z"></path></svg>',
238
+ field: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z"></path><path d="M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12"></path></svg>',
239
+ ember: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8.5 14.5A2.5 2.5 0 0011 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 11-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 002.5 2.5z"></path></svg>'
240
+ };
241
+
168
242
  function updatePaletteBtn(val) {
169
243
  paletteBtns.forEach(b => {
170
- if(b.dataset.palette === val) b.classList.add("active");
244
+ const basePalette = b.dataset.palette;
245
+
246
+ if (val === proPalettes[basePalette]) {
247
+ b.innerHTML = proIcons[val];
248
+ } else {
249
+ b.innerHTML = normalIcons[basePalette];
250
+ }
251
+
252
+ if(basePalette === val || proPalettes[basePalette] === val) b.classList.add("active");
253
+ else b.classList.remove("active");
254
+ });
255
+ }
256
+
257
+ function updateUiBtn(val) {
258
+ uiBtns.forEach(b => {
259
+ if(b.dataset.ui === val) b.classList.add("active");
171
260
  else b.classList.remove("active");
172
261
  });
173
262
  }
@@ -181,6 +270,10 @@ function bkWireThemeControls() {
181
270
  updatePaletteBtn(normalizedPalette);
182
271
  root.setAttribute("data-palette", normalizedPalette);
183
272
  }
273
+ if (savedUi) {
274
+ updateUiBtn(savedUi);
275
+ root.setAttribute("data-ui", savedUi);
276
+ }
184
277
 
185
278
  button &&
186
279
  panel &&
@@ -210,29 +303,85 @@ function bkWireThemeControls() {
210
303
  localStorage.setItem("bk-theme", val);
211
304
  updateThemeBtn(val);
212
305
  root.setAttribute("data-theme", val);
306
+ bkBroadcastTheme();
213
307
  });
214
308
  });
215
309
 
216
- paletteBtns.forEach(btn => {
310
+ paletteBtns.forEach(btn => {
311
+ btn.addEventListener("click", (e) => {
312
+ const baseVal = btn.dataset.palette;
313
+ let currentVal = root.getAttribute("data-palette") || "ink";
314
+ let newVal = baseVal;
315
+
316
+ if (e.detail === 2) {
317
+ if (currentVal === proPalettes[baseVal]) {
318
+ newVal = baseVal;
319
+ } else {
320
+ newVal = proPalettes[baseVal];
321
+ }
322
+ } else {
323
+ if (currentVal === proPalettes[baseVal]) {
324
+ newVal = proPalettes[baseVal];
325
+ }
326
+ }
327
+
328
+ localStorage.setItem("bk-palette", newVal);
329
+ updatePaletteBtn(newVal);
330
+ root.setAttribute("data-palette", newVal);
331
+ bkBroadcastTheme();
332
+ });
333
+ });
334
+
335
+ uiBtns.forEach(btn => {
217
336
  btn.addEventListener("click", () => {
218
- const val = btn.dataset.palette;
219
- localStorage.setItem("bk-palette", val);
220
- updatePaletteBtn(val);
221
- root.setAttribute("data-palette", val);
337
+ const val = btn.dataset.ui;
338
+ localStorage.setItem("bk-ui", val);
339
+ updateUiBtn(val);
340
+ root.setAttribute("data-ui", val);
341
+ bkBroadcastTheme();
222
342
  });
223
343
  });
224
344
  }
225
345
 
226
346
  // Quiz interaction
227
- // biome-ignore lint/correctness/noUnusedVariables: Used in generated HTML
228
347
  function bkAnswer(btn, qid) {
229
- // biome-ignore lint/correctness/noUnusedVariables: Kept for clarity
230
- const isCorrect = btn.dataset.correct === "true";
231
348
  const question = document.getElementById(qid);
349
+ if (!question) return;
350
+ const quiz = question.closest(".bk-quiz");
351
+ const dataEl = quiz ? quiz.querySelector(".bk-quiz-data") : null;
352
+ let isCorrect = false;
353
+
354
+ if (dataEl) {
355
+ try {
356
+ const answers = JSON.parse(dataEl.textContent || "[]");
357
+ // qid is format "quiz-IDX-qQI"
358
+ const match = qid.match(/-q(\d+)$/);
359
+ if (match) {
360
+ const qi = parseInt(match[1], 10);
361
+ const optIdx = parseInt(btn.dataset.optIdx, 10);
362
+ isCorrect = answers[qi] === optIdx;
363
+ }
364
+ } catch(e) {}
365
+ }
366
+
232
367
  question.querySelectorAll(".bk-opt").forEach((b) => {
233
- if (b.dataset.correct === "true") {
368
+ b.disabled = true; // Disable buttons for screen readers
369
+ const optIdx = parseInt(b.dataset.optIdx, 10);
370
+ // If we know the answer, highlight it
371
+ if (dataEl) {
372
+ try {
373
+ const answers = JSON.parse(dataEl.textContent || "[]");
374
+ const match = qid.match(/-q(\d+)$/);
375
+ if (match && answers[parseInt(match[1], 10)] === optIdx) {
376
+ b.classList.add("correct");
377
+ return;
378
+ }
379
+ } catch(e) {}
380
+ }
381
+
382
+ if (b === btn && isCorrect) {
234
383
  b.classList.add("correct");
235
- } else if (b === btn) {
384
+ } else if (b === btn && !isCorrect) {
236
385
  b.classList.add("wrong");
237
386
  } else {
238
387
  b.classList.add("disabled");
@@ -1 +1 @@
1
- {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../src/renderer/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAA0B,MAAM,aAAa,CAAC;AAC/E,OAAO,EACN,WAAW,EAKX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,OAAO,EAAmC,MAAM,YAAY,CAAC;AAG3E,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3C;AACD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAID,iBAAS,WAAW,CACnB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CAuBxC;AAED,iBAAS,gBAAgB,CACxB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CA+QxC;AA4KD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../src/renderer/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAA0B,MAAM,aAAa,CAAC;AAC/E,OAAO,EACN,WAAW,EAKX,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,KAAK,OAAO,EAAmC,MAAM,YAAY,CAAC;AAG3E,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO3C;AACD,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE3C;AAID,iBAAS,WAAW,CACnB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CAuBxC;AAED,iBAAS,gBAAgB,CACxB,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CA4RxC;AAyMD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}