mr-md 1.0.4 → 2.0.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 (58) hide show
  1. package/README.md +10 -5
  2. package/dist/builder.d.ts +6 -20
  3. package/dist/builder.d.ts.map +1 -1
  4. package/dist/builder.js +38 -97
  5. package/dist/cli/dev.d.ts +2 -0
  6. package/dist/cli/dev.d.ts.map +1 -0
  7. package/dist/cli/dev.js +92 -0
  8. package/dist/cli/generate.d.ts +2 -0
  9. package/dist/cli/generate.d.ts.map +1 -0
  10. package/dist/cli/generate.js +171 -0
  11. package/dist/cli/init.d.ts +2 -0
  12. package/dist/cli/init.d.ts.map +1 -0
  13. package/dist/cli/init.js +89 -0
  14. package/dist/cli.d.ts +3 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +27 -0
  17. package/dist/client/app.js +282 -107
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/renderer/blocks.d.ts.map +1 -1
  22. package/dist/renderer/blocks.js +88 -16
  23. package/dist/renderer/html-neo.d.ts +7 -0
  24. package/dist/renderer/html-neo.d.ts.map +1 -0
  25. package/dist/renderer/html-neo.js +173 -0
  26. package/dist/renderer/html.d.ts.map +1 -1
  27. package/dist/renderer/html.js +36 -7
  28. package/dist/renderer/index-neo.d.ts +4 -0
  29. package/dist/renderer/index-neo.d.ts.map +1 -0
  30. package/dist/renderer/index-neo.js +469 -0
  31. package/dist/renderer/index.d.ts +1 -2
  32. package/dist/renderer/index.d.ts.map +1 -1
  33. package/dist/renderer/index.js +29 -379
  34. package/dist/renderer/markdown.d.ts +1 -1
  35. package/dist/renderer/markdown.d.ts.map +1 -1
  36. package/dist/renderer/markdown.js +3 -3
  37. package/dist/renderer/utils.d.ts +1 -1
  38. package/dist/renderer/utils.d.ts.map +1 -1
  39. package/dist/renderer/utils.js +41 -34
  40. package/dist/styles/theme-neo.css +1369 -0
  41. package/dist/styles/theme.css +412 -127
  42. package/dist/types.d.ts +8 -10
  43. package/dist/types.d.ts.map +1 -1
  44. package/package.json +8 -7
  45. package/src/builder.ts +49 -125
  46. package/src/cli/dev.ts +102 -0
  47. package/src/cli/generate.ts +191 -0
  48. package/src/cli/init.ts +97 -0
  49. package/src/cli.ts +29 -0
  50. package/src/client/app.js +282 -107
  51. package/src/index.ts +1 -1
  52. package/src/renderer/blocks.ts +89 -15
  53. package/src/renderer/html.ts +36 -7
  54. package/src/renderer/index.ts +30 -394
  55. package/src/renderer/markdown.ts +3 -2
  56. package/src/renderer/utils.ts +43 -36
  57. package/src/styles/theme.css +412 -127
  58. package/src/types.ts +8 -12
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mr-md",
3
- "version": "1.0.4",
3
+ "version": "2.0.0-beta",
4
4
  "description": "Mr Markdown is an opinionated TypeScript SDK for building interactive, single-file learning pages.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -12,18 +12,18 @@
12
12
  "default": "./dist/index.js"
13
13
  }
14
14
  },
15
+ "bin": {
16
+ "md": "./dist/cli.js"
17
+ },
15
18
  "files": [
16
19
  "dist",
17
20
  "src"
18
21
  ],
19
- "directories": {
20
- "demo": "demo"
21
- },
22
22
  "scripts": {
23
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/",
24
24
  "prepublishOnly": "bun run build",
25
- "build:example": "bun demo/src/course.ts",
26
- "serve:example": "bunx serve demo/out",
25
+ "build:docs": "bun docs-site/build.ts",
26
+ "serve:docs": "bunx serve docs-site/out",
27
27
  "typecheck": "bunx tsc --noEmit",
28
28
  "test": "bun test && bun run typecheck",
29
29
  "test:watch": "bun test --watch",
@@ -57,6 +57,7 @@
57
57
  "highlight.js": "^11.11.1",
58
58
  "katex": "^0.16.47",
59
59
  "marked": "^18.0.4",
60
- "marked-highlight": "^2.2.4"
60
+ "marked-highlight": "^2.2.4",
61
+ "ts-morph": "^28.0.0"
61
62
  }
62
63
  }
package/src/builder.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as fs from "fs";
2
2
  import * as path from "path";
3
- import { render, renderChapter, renderCourse } from "./renderer/index.js";
3
+ import { render, renderChapter } from "./renderer/index.js";
4
4
  import type {
5
5
  AnimationBlock,
6
6
  AnimationOptions,
@@ -87,11 +87,11 @@ export class LessonBuilder {
87
87
  slug,
88
88
  };
89
89
  this.options = {
90
- outDir: options.outDir ?? "./out",
90
+ outDir: options.outDir ?? (callerDir ? path.join(callerDir, "out") : "./out"),
91
91
  contentBase: options.contentBase ?? callerDir ?? ".",
92
92
  theme: options.theme ?? "auto",
93
93
  palette: options.palette ?? "ink",
94
- strict: options.strict ?? true,
94
+ strict: options.strict ?? process.env.NODE_ENV !== "development",
95
95
  preset: {
96
96
  layout: "lesson",
97
97
  density: "comfortable",
@@ -155,19 +155,21 @@ export class LessonBuilder {
155
155
  /** @internal Used by ChapterBuilder to push down shared config */
156
156
  _inheritOptions(parentOpts: BuildOptions, parentRawOpts?: BuildOptions) {
157
157
  this.options = {
158
- ...this.options,
159
158
  outDir:
160
- this._rawOptions.outDir ?? parentOpts.outDir ?? this.options.outDir,
161
- contentBase: this._rawOptions.contentBase ?? this.options.contentBase,
159
+ this._rawOptions.outDir ?? (parentRawOpts?.outDir || parentOpts.outDir) ?? this.options.outDir,
160
+ contentBase:
161
+ this._rawOptions.contentBase ??
162
+ parentRawOpts?.contentBase ??
163
+ this.options.contentBase,
162
164
  theme: this._rawOptions.theme ?? parentOpts.theme ?? this.options.theme,
163
165
  palette:
164
166
  this._rawOptions.palette ?? parentOpts.palette ?? this.options.palette,
165
167
  strict:
166
168
  this._rawOptions.strict ?? parentOpts.strict ?? this.options.strict,
167
169
  preset: {
168
- ...this.options.preset,
169
170
  ...parentOpts.preset,
170
171
  ...this._rawOptions.preset,
172
+ ...this.options.preset,
171
173
  },
172
174
  };
173
175
  }
@@ -221,14 +223,12 @@ export class LessonBuilder {
221
223
  | `${string}.avif`,
222
224
  opts?: Omit<MediaOptions, "kind">,
223
225
  ): this;
224
- // biome-ignore lint/suspicious/noExplicitAny: Overload signature
225
- add(src: string, opts?: any): this;
226
- // biome-ignore lint/suspicious/noExplicitAny: Overload implementation
227
- add(src: string, opts: any = {}): this {
226
+ add(src: string, opts?: unknown): this;
227
+ add(src: string, opts: unknown = {}): this {
228
228
  const lower = src.toLowerCase();
229
229
  if (lower.endsWith(".md") || lower.endsWith(".mdx"))
230
230
  return this.markdown(src);
231
- if (lower.endsWith(".json")) return this.quiz(src, opts);
231
+ if (lower.endsWith(".json")) return this.quiz(src, opts as Pick<QuizBlock, "label" | "caption">);
232
232
 
233
233
  if (lower.endsWith(".js") || lower.endsWith(".ts")) {
234
234
  throw new Error(
@@ -239,18 +239,18 @@ export class LessonBuilder {
239
239
  }
240
240
 
241
241
  if (lower.match(/\.(png|jpg|jpeg|gif|webp|avif|svg)$/))
242
- return this.image(src, opts);
243
- if (lower.match(/\.(mp4|webm|mov)$/)) return this.video(src, opts);
244
- if (lower.match(/\.(mp3|wav|ogg|m4a)$/)) return this.audio(src, opts);
242
+ return this.image(src, opts as Omit<MediaOptions, "kind">);
243
+ if (lower.match(/\.(mp4|webm|mov)$/)) return this.video(src, opts as Omit<MediaOptions, "kind">);
244
+ if (lower.match(/\.(mp3|wav|ogg|m4a)$/)) return this.audio(src, opts as Omit<MediaOptions, "kind">);
245
245
  if (lower.includes("youtube.com") || lower.includes("youtu.be"))
246
- return this.youtube(src, opts);
246
+ return this.youtube(src, opts as YouTubeOptions);
247
247
 
248
248
  // Fallback to text/markdown if unknown
249
249
  return this.markdown(src);
250
250
  }
251
251
 
252
252
  /**
253
- * Creates a major chapter heading (H2) and a top-level sidebar navigation entry.
253
+ * Creates a major chapter heading (H1) and a top-level sidebar navigation entry.
254
254
  * @param src Path to a markdown file or raw markdown string.
255
255
  * @param title Optional title override for the sidebar and heading.
256
256
  * @example lesson.heading("# Welcome to Physics")
@@ -279,10 +279,10 @@ export class LessonBuilder {
279
279
  }
280
280
 
281
281
  /**
282
- * Creates a new subsection heading (H3) and a sub-entry in the sidebar.
282
+ * Creates a new subsection heading (H2) and a sub-entry in the sidebar.
283
283
  * @param src Path to a markdown file or raw markdown string.
284
284
  * @param label Optional title override for the sidebar label.
285
- * @example lesson.section("### 1. Kinematics")
285
+ * @example lesson.section("## 1. Kinematics")
286
286
  */
287
287
  section(src: string, label?: string): this {
288
288
  this.blocks.push({ type: "section", src, label } as SectionBlock);
@@ -510,9 +510,23 @@ export class LessonBuilder {
510
510
  */
511
511
  export function lesson(
512
512
  title: string,
513
- options: BuildOptions = {},
513
+ optionsOrSetup?: BuildOptions | ((ctx: LessonBuilder) => void),
514
+ setup?: (ctx: LessonBuilder) => void
514
515
  ): LessonBuilder {
515
- return new LessonBuilder(title, options, getCallerDir());
516
+ let options: BuildOptions = {};
517
+ let cb: ((ctx: LessonBuilder) => void) | undefined = setup;
518
+
519
+ if (typeof optionsOrSetup === "function") {
520
+ cb = optionsOrSetup;
521
+ } else if (optionsOrSetup) {
522
+ options = optionsOrSetup;
523
+ }
524
+
525
+ const builder = new LessonBuilder(title, options, getCallerDir());
526
+ if (cb) {
527
+ cb(builder);
528
+ }
529
+ return builder;
516
530
  }
517
531
 
518
532
  function normalizeSimulationOptions(
@@ -645,11 +659,11 @@ export class ChapterBuilder {
645
659
  slug,
646
660
  };
647
661
  this.options = {
648
- outDir: options.outDir ?? "./out",
662
+ outDir: options.outDir ?? (callerDir ? path.join(callerDir, "out") : "./out"),
649
663
  contentBase: options.contentBase ?? callerDir ?? ".",
650
664
  theme: options.theme ?? "auto",
651
665
  palette: options.palette ?? "ink",
652
- strict: options.strict ?? true,
666
+ strict: options.strict ?? process.env.NODE_ENV !== "development",
653
667
  preset: {
654
668
  layout: "lesson",
655
669
  density: "comfortable",
@@ -665,30 +679,6 @@ export class ChapterBuilder {
665
679
  return this;
666
680
  }
667
681
 
668
- /** @internal Used by CourseBuilder to push down shared config */
669
- _inheritOptions(parentOpts: BuildOptions, parentRawOpts?: BuildOptions) {
670
- this.options = {
671
- ...this.options,
672
- outDir:
673
- this._rawOptions.outDir ?? parentOpts.outDir ?? this.options.outDir,
674
- contentBase: this._rawOptions.contentBase ?? this.options.contentBase,
675
- theme: this._rawOptions.theme ?? parentOpts.theme ?? this.options.theme,
676
- palette:
677
- this._rawOptions.palette ?? parentOpts.palette ?? this.options.palette,
678
- strict:
679
- this._rawOptions.strict ?? parentOpts.strict ?? this.options.strict,
680
- preset: {
681
- ...this.options.preset,
682
- ...parentOpts.preset,
683
- ...this._rawOptions.preset,
684
- },
685
- };
686
-
687
- for (const lb of this.lessonBuilders) {
688
- lb._inheritOptions(this.options, this._rawOptions);
689
- }
690
- }
691
-
692
682
  description(text: string): this {
693
683
  this.meta.description = text;
694
684
  return this;
@@ -767,87 +757,21 @@ export class ChapterBuilder {
767
757
  */
768
758
  export function chapter(
769
759
  title: string,
770
- options: BuildOptions = {},
760
+ optionsOrSetup?: BuildOptions | ((ctx: ChapterBuilder) => void),
761
+ setup?: (ctx: ChapterBuilder) => void
771
762
  ): ChapterBuilder {
772
- return new ChapterBuilder(title, options, getCallerDir());
773
- }
774
-
775
- // ─── CourseBuilder ──────────────────────────────────────────────────────────
776
-
777
- export class CourseBuilder {
778
- private meta: import("./types.js").CourseMeta;
779
- private chapterBuilders: ChapterBuilder[] = [];
780
- private options: BuildOptions;
781
- private _rawOptions: BuildOptions;
763
+ let options: BuildOptions = {};
764
+ let cb: ((ctx: ChapterBuilder) => void) | undefined = setup;
782
765
 
783
- constructor(title: string, options: BuildOptions = {}, callerDir?: string) {
784
- this._rawOptions = options;
785
- let slug = title
786
- .toLowerCase()
787
- .replace(/[^a-z0-9]+/g, "-")
788
- .replace(/(^-|-$)/g, "");
789
- if (!slug) slug = "course";
790
-
791
- this.meta = { title, slug };
792
- this.options = {
793
- outDir: options.outDir ?? "./out",
794
- contentBase: options.contentBase ?? callerDir ?? ".",
795
- theme: options.theme ?? "auto",
796
- palette: options.palette ?? "ink",
797
- strict: options.strict ?? true,
798
- preset: {
799
- layout: "lesson",
800
- density: "comfortable",
801
- tone: "scholarly",
802
- ...options.preset,
803
- },
804
- ...options,
805
- };
806
- }
807
-
808
- slug(slug: string): this {
809
- this.meta.slug = slug;
810
- return this;
811
- }
812
-
813
- description(text: string): this {
814
- this.meta.description = text;
815
- return this;
766
+ if (typeof optionsOrSetup === "function") {
767
+ cb = optionsOrSetup;
768
+ } else if (optionsOrSetup) {
769
+ options = optionsOrSetup;
816
770
  }
817
771
 
818
- chapter(chapterBuilder: ChapterBuilder): this {
819
- chapterBuilder._inheritOptions(this.options, this._rawOptions);
820
- this.chapterBuilders.push(chapterBuilder);
821
- return this;
772
+ const builder = new ChapterBuilder(title, options, getCallerDir());
773
+ if (cb) {
774
+ cb(builder);
822
775
  }
823
-
824
- build(): string {
825
- const chapters: Chapter[] = [];
826
- for (const cb of this.chapterBuilders) {
827
- cb.build();
828
- chapters.push(cb.toJSON());
829
- }
830
-
831
- const courseData: import("./types.js").Course = { meta: this.meta, chapters };
832
- const html = renderCourse(courseData, this.options);
833
-
834
- const outDir = path.resolve(this.options.outDir as string);
835
- if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
836
-
837
- const outPath = path.join(outDir, `${this.meta.slug}.html`);
838
- fs.writeFileSync(outPath, html, "utf-8");
839
-
840
- const relPath = path.relative(process.cwd(), outPath);
841
- console.log(
842
- ` ✓ Built course (${this.chapterBuilders.length} chapters) → ${relPath}`,
843
- );
844
- return outPath;
845
- }
846
- }
847
-
848
- export function course(
849
- title: string,
850
- options: BuildOptions = {},
851
- ): CourseBuilder {
852
- return new CourseBuilder(title, options, getCallerDir());
776
+ return builder;
853
777
  }
package/src/cli/dev.ts ADDED
@@ -0,0 +1,102 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { exec } from "child_process";
4
+
5
+ declare const Bun: any;
6
+
7
+ export async function runDev(args: string[]) {
8
+ const dir = args[0] || ".";
9
+ const outDir = path.resolve(process.cwd(), dir, "out");
10
+
11
+ console.log(`Starting dev server for directory: ${dir}`);
12
+
13
+ let server: any;
14
+
15
+ const rebuild = () => {
16
+ console.log("Rebuilding...");
17
+ const entryPoints = ["chapter.ts", "index.ts", "lesson.ts"];
18
+ for (const entry of entryPoints) {
19
+ const entryPath = path.join(dir, entry);
20
+ 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");
26
+ }
27
+ });
28
+ return;
29
+ }
30
+ }
31
+ console.log("No chapter.ts or lesson.ts found to build automatically.");
32
+ };
33
+
34
+ rebuild();
35
+
36
+ if (fs.existsSync(dir)) {
37
+ let timeout: NodeJS.Timeout;
38
+ fs.watch(dir, { recursive: true }, (eventType, filename) => {
39
+ if (!filename || filename.includes("out/") || filename.includes(".git/")) return;
40
+
41
+ clearTimeout(timeout);
42
+ timeout = setTimeout(() => {
43
+ console.log(`File changed: ${filename}`);
44
+ rebuild();
45
+ }, 200);
46
+ });
47
+ console.log(`Watching ${dir} for changes...`);
48
+ }
49
+
50
+ server = Bun.serve({
51
+ port: 3000,
52
+ async fetch(req: any, srv: any) {
53
+ if (srv.upgrade(req)) return;
54
+
55
+ const url = new URL(req.url);
56
+ let filePath = path.join(outDir, url.pathname);
57
+
58
+ if (filePath.endsWith("/")) {
59
+ const files = fs.existsSync(outDir) ? fs.readdirSync(outDir) : [];
60
+ const htmlFiles = files.filter(f => f.endsWith(".html"));
61
+ if (htmlFiles.includes("index.html")) {
62
+ filePath = path.join(outDir, "index.html");
63
+ } else {
64
+ const chapterFile = htmlFiles.find(f => f.includes("chapter"));
65
+ if (chapterFile) {
66
+ filePath = path.join(outDir, chapterFile);
67
+ } else if (htmlFiles.length > 0) {
68
+ filePath = path.join(outDir, htmlFiles[0]);
69
+ } else {
70
+ filePath += "index.html";
71
+ }
72
+ }
73
+ }
74
+
75
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
76
+ if (filePath.endsWith(".html")) {
77
+ const file = Bun.file(filePath);
78
+ let text = await file.text();
79
+ text = text.replace("</body>", `<script>
80
+ const ws = new WebSocket("ws://localhost:3000/");
81
+ ws.onmessage = (e) => { if (e.data === "reload") location.reload(); };
82
+ </script></body>`);
83
+ return new Response(text, { headers: { "Content-Type": "text/html" } });
84
+ }
85
+ return new Response(Bun.file(filePath));
86
+ }
87
+
88
+ const srcPath = path.join(process.cwd(), dir, url.pathname);
89
+ if (fs.existsSync(srcPath) && fs.statSync(srcPath).isFile()) {
90
+ return new Response(Bun.file(srcPath));
91
+ }
92
+
93
+ return new Response("Not found", { status: 404 });
94
+ },
95
+ websocket: {
96
+ message() {},
97
+ open(ws: any) { ws.subscribe("livereload"); }
98
+ }
99
+ });
100
+
101
+ console.log(`Dev server listening on http://localhost:3000`);
102
+ }
@@ -0,0 +1,191 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+
4
+ function getNextPrefix(dirPath: string): string {
5
+ if (!fs.existsSync(dirPath)) return "01";
6
+
7
+ const files = fs.readdirSync(dirPath, { withFileTypes: true });
8
+ let maxPrefix = 0;
9
+
10
+ for (const file of files) {
11
+ if (file.isDirectory()) {
12
+ const match = file.name.match(/^(\d+)-/);
13
+ if (match) {
14
+ const num = parseInt(match[1], 10);
15
+ if (num > maxPrefix) {
16
+ maxPrefix = num;
17
+ }
18
+ }
19
+ }
20
+ }
21
+
22
+ const next = maxPrefix + 1;
23
+ return next.toString().padStart(2, "0");
24
+ }
25
+
26
+ export async function runGenerate(args: string[]) {
27
+ const type = args[0];
28
+ const rawName = args[1];
29
+
30
+ if (!type || !rawName) {
31
+ console.error("Usage: md g <ch|le|qu|chapter|lesson|quiz> <name>");
32
+ process.exit(1);
33
+ }
34
+
35
+ const name = rawName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
36
+ const cwd = process.cwd();
37
+
38
+ switch (type) {
39
+ case "ch":
40
+ case "chapter": {
41
+ const chaptersDir = path.join(cwd, "chapters");
42
+ if (!fs.existsSync(chaptersDir)) fs.mkdirSync(chaptersDir, { recursive: true });
43
+
44
+ const prefix = getNextPrefix(chaptersDir);
45
+ const chapterDirName = `${prefix}-${name}`;
46
+ const chapterPath = path.join(chaptersDir, chapterDirName);
47
+
48
+ fs.mkdirSync(chapterPath, { recursive: true });
49
+ fs.mkdirSync(path.join(chapterPath, "lessons"), { recursive: true });
50
+
51
+ const varName = name.replace(/-([a-z0-9])/g, g => g[1].toUpperCase());
52
+ const chapterTitle = rawName.replace(/-/g, " ").replace(/\b\w/g, l => l.toUpperCase());
53
+
54
+ const content = `import { chapter } from "mr-md";
55
+
56
+ export const ${varName}Chapter = chapter("${chapterTitle}", ctx => {
57
+ // Add lessons here
58
+ });
59
+
60
+ if (import.meta.main) {
61
+ ${varName}Chapter.build();
62
+ }
63
+ `;
64
+ fs.writeFileSync(path.join(chapterPath, "chapter.ts"), content, "utf-8");
65
+ console.log(`Generated Chapter: chapters/${chapterDirName}`);
66
+ break;
67
+ }
68
+ case "le":
69
+ case "lesson": {
70
+ // Assume we are in a chapter directory
71
+ const lessonsDir = path.join(cwd, "lessons");
72
+ if (!fs.existsSync(lessonsDir)) fs.mkdirSync(lessonsDir, { recursive: true });
73
+
74
+ const prefix = getNextPrefix(lessonsDir);
75
+ const lessonDirName = `${prefix}-${name}`;
76
+ const lessonPath = path.join(lessonsDir, lessonDirName);
77
+
78
+ fs.mkdirSync(lessonPath, { recursive: true });
79
+ fs.mkdirSync(path.join(lessonPath, "sims"), { recursive: true });
80
+ fs.mkdirSync(path.join(lessonPath, "media"), { recursive: true });
81
+ fs.mkdirSync(path.join(lessonPath, "quizzes"), { recursive: true });
82
+ fs.mkdirSync(path.join(lessonPath, "content"), { recursive: true });
83
+
84
+ const lessonTitle = rawName.replace(/-/g, " ").replace(/\b\w/g, l => l.toUpperCase());
85
+ const varName = name.replace(/-([a-z0-9])/g, g => g[1].toUpperCase());
86
+
87
+ const content = `import { lesson } from "mr-md";
88
+
89
+ export const ${varName}Lesson = lesson("${lessonTitle}", { contentBase: import.meta.dir }, ctx => {
90
+ });
91
+ `;
92
+ fs.writeFileSync(path.join(lessonPath, "lesson.ts"), content, "utf-8");
93
+ console.log(`Generated Lesson: lessons/${lessonDirName}`);
94
+
95
+ // Auto import into chapter.ts
96
+ const chapterFile = path.join(cwd, "chapter.ts");
97
+ if (fs.existsSync(chapterFile)) {
98
+ const { Project, SyntaxKind } = await import("ts-morph");
99
+ const project = new Project();
100
+ const sourceFile = project.addSourceFileAtPath(chapterFile);
101
+
102
+ // 1. Add the import
103
+ sourceFile.addImportDeclaration({
104
+ namedImports: [`${varName}Lesson`],
105
+ moduleSpecifier: `./lessons/${lessonDirName}/lesson.js`
106
+ });
107
+
108
+ // 2. Find the chapter(...) call and inject ctx.lesson()
109
+ const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
110
+ const chapterCall = calls.find((c: any) => c.getExpression().getText() === "chapter");
111
+
112
+ if (chapterCall) {
113
+ const args = chapterCall.getArguments();
114
+ const callback = args.find((a: any) => a.getKind() === SyntaxKind.ArrowFunction || a.getKind() === SyntaxKind.FunctionExpression);
115
+ if (callback) {
116
+ const arrow = callback.asKind(SyntaxKind.ArrowFunction);
117
+ const func = callback.asKind(SyntaxKind.FunctionExpression);
118
+ const body = arrow ? arrow.getBody() : func ? func.getBody() : null;
119
+ if (body && body.getKind() === SyntaxKind.Block) {
120
+ body.asKind(SyntaxKind.Block)?.addStatements(`ctx.lesson(${varName}Lesson);`);
121
+ } else {
122
+ console.warn(" ⚠ Could not auto-import: chapter callback must use { } block syntax.");
123
+ }
124
+ } else {
125
+ console.warn(" ⚠ Could not auto-import: could not find chapter callback.");
126
+ }
127
+ }
128
+
129
+ sourceFile.saveSync();
130
+ console.log(`Auto-imported ${varName}Lesson into chapter.ts`);
131
+ }
132
+ break;
133
+ }
134
+ case "qu":
135
+ case "quiz": {
136
+ // Assume we are in a lesson directory
137
+ const quizzesDir = path.join(cwd, "quizzes");
138
+ if (!fs.existsSync(quizzesDir)) fs.mkdirSync(quizzesDir, { recursive: true });
139
+
140
+ const quizPath = path.join(quizzesDir, `${name}.json`);
141
+
142
+ const content = `{
143
+ "questions": [
144
+ {
145
+ "q": "Sample question?",
146
+ "options": ["A", "B"],
147
+ "answer": 0
148
+ }
149
+ ]
150
+ }
151
+ `;
152
+ fs.writeFileSync(quizPath, content, "utf-8");
153
+ console.log(`Generated Quiz: quizzes/${name}.json`);
154
+
155
+ // Auto import into lesson.ts
156
+ const lessonFile = path.join(cwd, "lesson.ts");
157
+ if (fs.existsSync(lessonFile)) {
158
+ const { Project, SyntaxKind } = await import("ts-morph");
159
+ const project = new Project();
160
+ const sourceFile = project.addSourceFileAtPath(lessonFile);
161
+
162
+ const calls = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
163
+ const lessonCall = calls.find((c: any) => c.getExpression().getText() === "lesson");
164
+
165
+ if (lessonCall) {
166
+ const args = lessonCall.getArguments();
167
+ const callback = args.find((a: any) => a.getKind() === SyntaxKind.ArrowFunction || a.getKind() === SyntaxKind.FunctionExpression);
168
+ if (callback) {
169
+ const arrow = callback.asKind(SyntaxKind.ArrowFunction);
170
+ const func = callback.asKind(SyntaxKind.FunctionExpression);
171
+ const body = arrow ? arrow.getBody() : func ? func.getBody() : null;
172
+ if (body && body.getKind() === SyntaxKind.Block) {
173
+ body.asKind(SyntaxKind.Block)?.addStatements(`ctx.quiz("quizzes/${name}.json");`);
174
+ } else {
175
+ console.warn(" ⚠ Could not auto-import quiz: lesson callback must use { } block syntax.");
176
+ }
177
+ } else {
178
+ console.warn(" ⚠ Could not auto-import quiz: could not find lesson callback.");
179
+ }
180
+ }
181
+
182
+ sourceFile.saveSync();
183
+ console.log(`Auto-added quiz to lesson.ts`);
184
+ }
185
+
186
+ break;
187
+ }
188
+ default:
189
+ console.error(`Unknown generator type: ${type}`);
190
+ }
191
+ }