ai-spector 0.8.81 → 0.8.85

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 (163) hide show
  1. package/README.md +1 -1
  2. package/README.vi.md +1 -1
  3. package/dist/core/course/catalog.d.ts.map +1 -1
  4. package/dist/core/course/catalog.js +17 -12
  5. package/dist/core/course/catalog.js.map +1 -1
  6. package/dist/core/course/fallback.d.ts +9 -0
  7. package/dist/core/course/fallback.d.ts.map +1 -0
  8. package/dist/core/course/fallback.js +15 -0
  9. package/dist/core/course/fallback.js.map +1 -0
  10. package/dist/core/course/html-shell.d.ts +1 -0
  11. package/dist/core/course/html-shell.d.ts.map +1 -1
  12. package/dist/core/course/html-shell.js +45 -6
  13. package/dist/core/course/html-shell.js.map +1 -1
  14. package/dist/core/course/locale.d.ts +9 -7
  15. package/dist/core/course/locale.d.ts.map +1 -1
  16. package/dist/core/course/locale.js +77 -30
  17. package/dist/core/course/locale.js.map +1 -1
  18. package/dist/core/course/redirects.d.ts +3 -0
  19. package/dist/core/course/redirects.d.ts.map +1 -0
  20. package/dist/core/course/redirects.js +33 -0
  21. package/dist/core/course/redirects.js.map +1 -0
  22. package/dist/core/course/render.d.ts +7 -0
  23. package/dist/core/course/render.d.ts.map +1 -1
  24. package/dist/core/course/render.js +35 -2
  25. package/dist/core/course/render.js.map +1 -1
  26. package/dist/core/course/sections.js +7 -7
  27. package/dist/core/course/sections.js.map +1 -1
  28. package/dist/core/course/serve.d.ts.map +1 -1
  29. package/dist/core/course/serve.js +30 -6
  30. package/dist/core/course/serve.js.map +1 -1
  31. package/dist/core/operations/import-plan.d.ts +24 -0
  32. package/dist/core/operations/import-plan.d.ts.map +1 -0
  33. package/dist/core/operations/import-plan.js +11 -0
  34. package/dist/core/operations/import-plan.js.map +1 -0
  35. package/dist/core/operations/init.js +1 -1
  36. package/dist/core/operations/init.js.map +1 -1
  37. package/dist/core/operations/setup.js +1 -1
  38. package/dist/core/operations/setup.js.map +1 -1
  39. package/dist/core/operations/task-gates.d.ts.map +1 -1
  40. package/dist/core/operations/task-gates.js +23 -0
  41. package/dist/core/operations/task-gates.js.map +1 -1
  42. package/dist/core/operations/task-templates.d.ts +2 -2
  43. package/dist/core/operations/task-templates.d.ts.map +1 -1
  44. package/dist/core/operations/task-templates.js +18 -0
  45. package/dist/core/operations/task-templates.js.map +1 -1
  46. package/dist/core/operations/task.d.ts +34 -1
  47. package/dist/core/operations/task.d.ts.map +1 -1
  48. package/dist/core/operations/task.js +87 -0
  49. package/dist/core/operations/task.js.map +1 -1
  50. package/dist/core/operations/template-import-gates.d.ts +21 -0
  51. package/dist/core/operations/template-import-gates.d.ts.map +1 -0
  52. package/dist/core/operations/template-import-gates.js +85 -0
  53. package/dist/core/operations/template-import-gates.js.map +1 -0
  54. package/dist/core/operations/template-list.d.ts +39 -0
  55. package/dist/core/operations/template-list.d.ts.map +1 -0
  56. package/dist/core/operations/template-list.js +144 -0
  57. package/dist/core/operations/template-list.js.map +1 -0
  58. package/dist/core/operations/template.d.ts +28 -0
  59. package/dist/core/operations/template.d.ts.map +1 -1
  60. package/dist/core/operations/template.js +212 -81
  61. package/dist/core/operations/template.js.map +1 -1
  62. package/dist/core/template/import-aspects.d.ts +44 -0
  63. package/dist/core/template/import-aspects.d.ts.map +1 -0
  64. package/dist/core/template/import-aspects.js +105 -0
  65. package/dist/core/template/import-aspects.js.map +1 -0
  66. package/dist/core/template/scan-inference.d.ts +30 -0
  67. package/dist/core/template/scan-inference.d.ts.map +1 -0
  68. package/dist/core/template/scan-inference.js +450 -0
  69. package/dist/core/template/scan-inference.js.map +1 -0
  70. package/dist/core/workflow/active-worker.d.ts.map +1 -1
  71. package/dist/core/workflow/active-worker.js +22 -10
  72. package/dist/core/workflow/active-worker.js.map +1 -1
  73. package/dist/interfaces/mcp/schemas.d.ts +483 -5
  74. package/dist/interfaces/mcp/schemas.d.ts.map +1 -1
  75. package/dist/interfaces/mcp/schemas.js +77 -1
  76. package/dist/interfaces/mcp/schemas.js.map +1 -1
  77. package/dist/interfaces/mcp/server.js +41 -5
  78. package/dist/interfaces/mcp/server.js.map +1 -1
  79. package/dist/interfaces/mcp/tools/task.d.ts +3 -1
  80. package/dist/interfaces/mcp/tools/task.d.ts.map +1 -1
  81. package/dist/interfaces/mcp/tools/task.js +15 -1
  82. package/dist/interfaces/mcp/tools/task.js.map +1 -1
  83. package/dist/interfaces/mcp/tools/template.d.ts +30 -11
  84. package/dist/interfaces/mcp/tools/template.d.ts.map +1 -1
  85. package/dist/interfaces/mcp/tools/template.js +65 -36
  86. package/dist/interfaces/mcp/tools/template.js.map +1 -1
  87. package/package.json +1 -1
  88. package/scaffold/claude/.claude/skills/ai-spector-course/references/course-guide.md +48 -41
  89. package/scaffold/claude/.claude/skills/ai-spector-course/skill.md +12 -9
  90. package/scaffold/claude/.claude/skills/ai-spector-template-import/references/import-aspects.md +74 -0
  91. package/scaffold/claude/.claude/workflows/README.md +1 -0
  92. package/scaffold/claude/.claude/workflows/template-import.md +18 -0
  93. package/scaffold/cursor/commands/README.md +1 -0
  94. package/scaffold/cursor/commands/template-import.md +18 -0
  95. package/scaffold/cursor/skills/ai-spector-course/SKILL.md +12 -9
  96. package/scaffold/cursor/skills/ai-spector-course/references/course-guide.md +48 -41
  97. package/scaffold/cursor/skills/ai-spector-template-import/references/import-aspects.md +74 -0
  98. package/website/README.md +13 -4
  99. package/website/docs/en/01-welcome/01-what-is-ai-spector.md +60 -0
  100. package/website/docs/en/01-welcome/README.md +7 -0
  101. package/website/docs/en/02-get-started/01-setup-via-chat.md +66 -0
  102. package/website/docs/en/02-get-started/README.md +7 -0
  103. package/website/docs/en/03-chat-basics/01-how-chat-works.md +72 -0
  104. package/website/docs/en/03-chat-basics/02-four-kinds-of-approve.md +64 -0
  105. package/website/docs/en/03-chat-basics/README.md +8 -0
  106. package/website/docs/en/04-changes/01-add-or-change-requirement.md +58 -0
  107. package/website/docs/en/04-changes/README.md +7 -0
  108. package/website/docs/en/05-generate/01-generate-srs.md +67 -0
  109. package/website/docs/en/05-generate/README.md +7 -0
  110. package/website/docs/en/06-review/01-document-review.md +61 -0
  111. package/website/docs/en/06-review/02-resolve-comments.md +56 -0
  112. package/website/docs/en/06-review/README.md +8 -0
  113. package/website/docs/en/07-everyday/01-tasks-and-workspace.md +71 -0
  114. package/website/docs/en/07-everyday/README.md +5 -0
  115. package/website/docs/en/README.md +32 -0
  116. package/website/docs/vi/01-welcome/01-what-is-ai-spector.md +60 -0
  117. package/website/docs/vi/01-welcome/README.md +7 -0
  118. package/website/docs/vi/02-get-started/01-setup-via-chat.md +66 -0
  119. package/website/docs/vi/02-get-started/README.md +7 -0
  120. package/website/docs/vi/03-chat-basics/01-how-chat-works.md +72 -0
  121. package/website/docs/vi/03-chat-basics/02-four-kinds-of-approve.md +64 -0
  122. package/website/docs/vi/03-chat-basics/README.md +8 -0
  123. package/website/docs/vi/04-changes/01-add-or-change-requirement.md +58 -0
  124. package/website/docs/vi/04-changes/README.md +7 -0
  125. package/website/docs/vi/05-generate/01-generate-srs.md +67 -0
  126. package/website/docs/vi/05-generate/README.md +7 -0
  127. package/website/docs/vi/06-review/01-document-review.md +61 -0
  128. package/website/docs/vi/06-review/02-resolve-comments.md +56 -0
  129. package/website/docs/vi/06-review/README.md +8 -0
  130. package/website/docs/vi/07-everyday/01-tasks-and-workspace.md +71 -0
  131. package/website/docs/vi/07-everyday/README.md +5 -0
  132. package/website/docs/vi/README.md +32 -0
  133. package/website/docs/01-get-started/01-prerequisites-and-init.md +0 -88
  134. package/website/docs/01-get-started/02-setup-and-skills.md +0 -70
  135. package/website/docs/01-get-started/README.md +0 -17
  136. package/website/docs/01-get-started/_category_.json +0 -4
  137. package/website/docs/02-chat-basics/01-how-chat-works.md +0 -95
  138. package/website/docs/02-chat-basics/02-workspace-and-tasks.md +0 -82
  139. package/website/docs/02-chat-basics/03-incremental-changes.md +0 -59
  140. package/website/docs/02-chat-basics/README.md +0 -19
  141. package/website/docs/02-chat-basics/_category_.json +0 -4
  142. package/website/docs/03-graph/01-sources-and-analyze.md +0 -70
  143. package/website/docs/03-graph/02-validate-index-explore.md +0 -83
  144. package/website/docs/03-graph/README.md +0 -18
  145. package/website/docs/03-graph/_category_.json +0 -4
  146. package/website/docs/04-generate/01-generate-srs.md +0 -101
  147. package/website/docs/04-generate/02-basic-design.md +0 -61
  148. package/website/docs/04-generate/README.md +0 -21
  149. package/website/docs/04-generate/_category_.json +0 -4
  150. package/website/docs/05-prototype/01-translations.md +0 -43
  151. package/website/docs/05-prototype/02-build-prototype.md +0 -142
  152. package/website/docs/05-prototype/03-external-prototype-map.md +0 -127
  153. package/website/docs/05-prototype/README.md +0 -11
  154. package/website/docs/05-prototype/_category_.json +0 -4
  155. package/website/docs/06-review/01-document-review.md +0 -108
  156. package/website/docs/06-review/02-comment-threads.md +0 -68
  157. package/website/docs/06-review/README.md +0 -12
  158. package/website/docs/06-review/_category_.json +0 -4
  159. package/website/docs/07-advanced/01-custom-templates.md +0 -46
  160. package/website/docs/07-advanced/02-search-and-editors.md +0 -52
  161. package/website/docs/07-advanced/README.md +0 -10
  162. package/website/docs/07-advanced/_category_.json +0 -4
  163. package/website/docs/README.md +0 -56
package/README.md CHANGED
@@ -4,7 +4,7 @@ Documentation workflow in **Cursor** or **Claude Code**: traceability graph, SRS
4
4
 
5
5
  **Needs:** Node 20+, Git, [Cursor](https://cursor.com) and/or [Claude Code](https://docs.anthropic.com/en/docs/claude-code), Python 3.11+ *(optional — CocoIndex semantic search)*.
6
6
 
7
- **Learn:** `npm run docs:dev` · [Course](website/docs/README.md) · Tiếng Việt: `/vi/docs/` · Offline: `npx ai-spector course serve --open`
7
+ **Learn:** `npm run docs:dev` · [Course](website/docs/en/README.md) · Tiếng Việt: `/vi/docs/` · Offline: `npx ai-spector course serve --open`
8
8
 
9
9
  **Tiếng Việt:** [README.vi.md](README.vi.md)
10
10
 
package/README.vi.md CHANGED
@@ -4,7 +4,7 @@ Công cụ làm tài liệu phần mềm trên **Cursor** hoặc **Claude Code**
4
4
 
5
5
  **Cần có:** Node 20+, Git, [Cursor](https://cursor.com) và/hoặc [Claude Code](https://docs.anthropic.com/en/docs/claude-code), Python 3.11+ *(không bắt buộc — dùng cho tìm kiếm thông minh với CocoIndex)*.
6
6
 
7
- Hướng dẫn từng bước: `npm run docs:dev` hoặc `npx ai-spector course serve --open` · [Course](website/docs/README.md)
7
+ Hướng dẫn từng bước: `npm run docs:dev` hoặc `npx ai-spector course serve --open` · [Course](website/docs/vi/README.md)
8
8
 
9
9
  **English:** [README.md](README.md)
10
10
 
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/core/course/catalog.ts"],"names":[],"mappings":"AAIA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAGvE,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqED,qBAAa,mBAAoB,SAAQ,KAAK;IAE1C,QAAQ,CAAC,MAAM,EAAE,YAAY;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE;gBADtB,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,EAAE;CAKlC;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,MAAM,CAeR;AAED,6EAA6E;AAC7E,wBAAsB,iBAAiB,CACrC,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBvB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAGpF;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,CAYhE"}
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/core/course/catalog.ts"],"names":[],"mappings":"AAIA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAGvE,MAAM,WAAW,UAAU;IACzB,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqED,qBAAa,mBAAoB,SAAQ,KAAK;IAE1C,QAAQ,CAAC,MAAM,EAAE,YAAY;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,EAAE;gBADtB,MAAM,EAAE,YAAY,EACpB,YAAY,EAAE,MAAM,EAAE;CAKlC;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,YAAY,EACrB,YAAY,EAAE,MAAM,EAAE,GACrB,MAAM,CAeR;AAMD,6EAA6E;AAC7E,wBAAsB,iBAAiB,CACrC,WAAW,CAAC,EAAE,MAAM,EACpB,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAmBjB;AAED,wBAAsB,eAAe,CACnC,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,UAAU,EAAE,CAAC,CAqBvB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAGpF;AAED,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EAAE,EACnB,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,IAAI,CAAC,EAAE,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,UAAU,CAAA;CAAE,CAYhE"}
@@ -80,28 +80,33 @@ export function formatCourseNotFoundMessage(_locale, checkedPaths) {
80
80
  ...checkedPaths.map((p) => ` - ${p}`),
81
81
  "",
82
82
  "Fix:",
83
- " 1. Reinstall ai-spector (course ships in node_modules/ai-spector/website/docs/):",
83
+ " 1. Reinstall ai-spector (course ships in node_modules/ai-spector/website/docs/{locale}/):",
84
84
  " npm install ai-spector",
85
85
  " 2. Or add a local copy in your project:",
86
- " docs/course/ (optional override)",
87
- " 3. From the ai-spector repo: edit website/docs/ (docs/course is a dev symlink).",
86
+ " docs/course/en/ or docs/course/vi/ (optional override)",
87
+ " 3. From the ai-spector repo: edit website/docs/en/ or website/docs/vi/.",
88
88
  ];
89
89
  return lines.join("\n");
90
90
  }
91
+ function localeCourseDir(base, locale) {
92
+ return join(base, locale);
93
+ }
91
94
  /** Prefer project-local course copy when present; otherwise bundled docs. */
92
95
  export async function resolveCourseRoot(projectRoot, locale = DEFAULT_COURSE_LOCALE) {
93
- const bundled = courseBundleRoot();
94
- const local = projectRoot ? join(projectRoot, "docs", "course") : undefined;
96
+ const bundledBase = courseBundleRoot();
97
+ const localBase = projectRoot ? join(projectRoot, "docs", "course") : undefined;
95
98
  const checkedPaths = [];
96
- if (local) {
97
- checkedPaths.push(local);
98
- if (await pathExists(local)) {
99
- return local;
99
+ if (localBase) {
100
+ const localLocale = localeCourseDir(localBase, locale);
101
+ checkedPaths.push(localLocale);
102
+ if (await pathExists(localLocale)) {
103
+ return localLocale;
100
104
  }
101
105
  }
102
- checkedPaths.push(bundled);
103
- if (await pathExists(bundled)) {
104
- return bundled;
106
+ const bundledLocale = localeCourseDir(bundledBase, locale);
107
+ checkedPaths.push(bundledLocale);
108
+ if (await pathExists(bundledLocale)) {
109
+ return bundledLocale;
105
110
  }
106
111
  throw new CourseNotFoundError(locale, checkedPaths);
107
112
  }
@@ -1 +1 @@
1
- {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/core/course/catalog.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/core/course/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CoursePage } from "./catalog.js";
2
+ import type { CourseLocale } from "./locale.js";
3
+ export interface PageResolveResult {
4
+ page?: CoursePage;
5
+ fallback: boolean;
6
+ bodyLocale: CourseLocale;
7
+ }
8
+ export declare function resolvePageWithFallback(locale: CourseLocale, slug: string, localePages: CoursePage[], enPages: CoursePage[]): PageResolveResult;
9
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../../src/core/course/fallback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,UAAU,EAAE,GACpB,iBAAiB,CAYnB"}
@@ -0,0 +1,15 @@
1
+ import { pageBySlug } from "./catalog.js";
2
+ export function resolvePageWithFallback(locale, slug, localePages, enPages) {
3
+ const page = pageBySlug(localePages, slug);
4
+ if (page) {
5
+ return { page, fallback: false, bodyLocale: locale };
6
+ }
7
+ if (locale === "vi") {
8
+ const enPage = pageBySlug(enPages, slug);
9
+ if (enPage) {
10
+ return { page: enPage, fallback: true, bodyLocale: "en" };
11
+ }
12
+ }
13
+ return { fallback: false, bodyLocale: locale };
14
+ }
15
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../../src/core/course/fallback.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAS1C,MAAM,UAAU,uBAAuB,CACrC,MAAoB,EACpB,IAAY,EACZ,WAAyB,EACzB,OAAqB;IAErB,MAAM,IAAI,GAAG,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC3C,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IACvD,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAC5D,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACjD,CAAC"}
@@ -9,6 +9,7 @@ export interface CourseShellOptions {
9
9
  prev?: CoursePage;
10
10
  next?: CoursePage;
11
11
  locale?: CourseLocale;
12
+ localeFallback?: boolean;
12
13
  }
13
14
  export declare function buildCoursePageHtml(opts: CourseShellOptions): string;
14
15
  //# sourceMappingURL=html-shell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"html-shell.d.ts","sourceRoot":"","sources":["../../../src/core/course/html-shell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AA6XrB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AA6GD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAiGpE"}
1
+ {"version":3,"file":"html-shell.d.ts","sourceRoot":"","sources":["../../../src/core/course/html-shell.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AA8YrB,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAoID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAoGpE"}
@@ -302,6 +302,23 @@ button { font: inherit; cursor: pointer; }
302
302
  }
303
303
  .chat-hint strong { color: var(--accent); }
304
304
  .chat-hint code { font-size: .85em; }
305
+
306
+ .callout { margin: 1.25rem 0; padding: 1rem 1.1rem; border-radius: var(--radius); border: 1px solid var(--border); }
307
+ .callout.exercise { border-color: var(--accent-border); background: var(--accent-soft); }
308
+ .callout.exercise::before { content: "Try it now"; display: block; font-weight: 700; color: var(--accent); margin-bottom: .5rem; }
309
+ .callout.roletip { font-size: .88rem; background: var(--bg); }
310
+ .callout.roletip::before { content: "Role tip"; display: block; font-weight: 600; color: var(--muted); margin-bottom: .35rem; }
311
+ .callout.behind { font-size: .85rem; color: var(--muted); }
312
+ .locale-switch { font-size: .78rem; display: flex; align-items: center; gap: .25rem; }
313
+ .locale-switch a { color: var(--muted); text-decoration: none; }
314
+ .locale-switch a.locale-active { color: var(--accent); font-weight: 700; }
315
+ .locale-sep { color: var(--muted); }
316
+ .locale-fallback-banner { background: #fef3c7; color: #92400e; padding: .75rem 1rem; border-radius: var(--radius); margin-bottom: 1rem; font-size: .88rem; }
317
+ @media (prefers-color-scheme: dark) {
318
+ .locale-fallback-banner { background: #422006; color: #fde68a; }
319
+ }
320
+ .nav-group-disabled h3 { color: var(--muted); opacity: .7; }
321
+ .nav-disabled { display: block; padding: .32rem .45rem; font-size: .82rem; color: var(--muted); }
305
322
  `;
306
323
  const SCRIPTS = (copyLabel, copiedLabel) => `
307
324
  (function () {
@@ -405,14 +422,33 @@ function lessonProgress(pages, activeSlug) {
405
422
  return { index, total, pct };
406
423
  }
407
424
  const SECTION_IDS = [
408
- "01-get-started",
409
- "02-chat-basics",
410
- "03-graph",
411
- "04-generate",
412
- "05-prototype",
425
+ "01-welcome",
426
+ "02-get-started",
427
+ "03-chat-basics",
428
+ "04-changes",
429
+ "05-generate",
413
430
  "06-review",
414
- "07-advanced",
431
+ "07-everyday",
415
432
  ];
433
+ function localeSwitcherHtml(activeLocale, activeSlug) {
434
+ const locales = ["en", "vi"];
435
+ return locales
436
+ .map((loc) => {
437
+ const active = loc === activeLocale ? ' class="locale-active"' : "";
438
+ return `<a href="${coursePageUrl(loc, activeSlug)}"${active}>${loc.toUpperCase()}</a>`;
439
+ })
440
+ .join('<span class="locale-sep">|</span>');
441
+ }
442
+ function advancedStubHtml(locale) {
443
+ const title = locale === "vi" ? "Nâng cao (sắp ra mắt)" : "Advanced (coming soon)";
444
+ const hint = locale === "vi"
445
+ ? "Đồ thị, prototype, mẫu tùy chỉnh…"
446
+ : "Graph, prototype, custom templates…";
447
+ return `<div class="nav-group nav-group-disabled"><h3>${escapeHtml(title)}</h3><ul><li><span class="nav-disabled">${escapeHtml(hint)}</span></li></ul></div>`;
448
+ }
449
+ function fallbackBannerHtml(ui) {
450
+ return `<div class="locale-fallback-banner" role="status">${escapeHtml(ui.localeFallback)}</div>`;
451
+ }
416
452
  function navGroups(pages, locale) {
417
453
  return SECTION_IDS
418
454
  .map((sectionId) => {
@@ -521,6 +557,7 @@ export function buildCoursePageHtml(opts) {
521
557
  <span>${escapeHtml(progressLabel)}</span>
522
558
  <div class="progress-bar" aria-hidden="true"><div class="progress-fill" style="width:${progress.pct}%"></div></div>
523
559
  </div>
560
+ <div class="locale-switch">${localeSwitcherHtml(locale, opts.activeSlug)}</div>
524
561
  <a class="open-chat" href="#chat-hint">${escapeHtml(ui.tryInChat)}</a>
525
562
  </header>
526
563
  <div class="sidebar-backdrop"></div>
@@ -531,9 +568,11 @@ export function buildCoursePageHtml(opts) {
531
568
  <input type="search" class="search" placeholder="${escapeHtml(ui.searchPlaceholder)}" aria-label="${escapeHtml(ui.searchAria)}" />
532
569
  <div class="nav-group"><ul>${topNav}</ul></div>
533
570
  ${sectionNav}
571
+ ${advancedStubHtml(locale)}
534
572
  </aside>
535
573
  <div class="main-wrap">
536
574
  <div class="content-panel">
575
+ ${opts.localeFallback ? fallbackBannerHtml(ui) : ""}
537
576
  ${breadcrumbHtml(opts.activePage, locale, ui)}
538
577
  ${metaBadges(opts.activePage, progress, ui)}
539
578
  <div class="${withTocClass}">
@@ -1 +1 @@
1
- {"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../../src/core/course/html-shell.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"html-shell.js","sourceRoot":"","sources":["../../../src/core/course/html-shell.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export type CourseLocale = "en";
1
+ export type CourseLocale = "en" | "vi";
2
2
  export declare const DEFAULT_COURSE_LOCALE: CourseLocale;
3
3
  export declare const SUPPORTED_COURSE_LOCALES: readonly CourseLocale[];
4
4
  export interface CourseUiStrings {
@@ -19,16 +19,18 @@ export interface CourseUiStrings {
19
19
  copy: string;
20
20
  copied: string;
21
21
  inEditor: string;
22
+ localeFallback: string;
22
23
  }
23
24
  export declare const SECTION_LABELS: Record<string, string>;
24
- export declare function courseUi(_locale?: CourseLocale): CourseUiStrings;
25
- export declare function sectionLabelForLocale(sectionId: string, _locale?: CourseLocale): string;
26
- export declare function chatHintForSection(sectionId: string | undefined, _locale?: CourseLocale): string;
27
- export declare function coursePathPrefix(_locale?: CourseLocale): string;
28
- export declare function coursePageUrl(_locale: CourseLocale, slug: string): string;
25
+ export declare const SECTION_LABELS_VI: Record<string, string>;
26
+ export declare function courseUi(locale?: CourseLocale): CourseUiStrings;
27
+ export declare function sectionLabelForLocale(sectionId: string, locale?: CourseLocale): string;
28
+ export declare function chatHintForSection(sectionId: string | undefined, locale?: CourseLocale): string;
29
+ export declare function coursePathPrefix(locale?: CourseLocale): string;
30
+ export declare function coursePageUrl(locale: CourseLocale, slug: string): string;
29
31
  export declare function parseCourseRequest(pathname: string): {
30
32
  locale: CourseLocale;
31
33
  slug: string;
32
34
  };
33
- export declare function normalizeCourseLocale(_value?: string): CourseLocale;
35
+ export declare function normalizeCourseLocale(value?: string): CourseLocale;
34
36
  //# sourceMappingURL=locale.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../../src/core/course/locale.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC;AAEhC,eAAO,MAAM,qBAAqB,EAAE,YAAmB,CAAC;AAExD,eAAO,MAAM,wBAAwB,EAAE,SAAS,YAAY,EAAoB,CAAC;AAEjF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACnD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAsBD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQjD,CAAC;AAeF,wBAAgB,QAAQ,CAAC,OAAO,GAAE,YAAoC,GAAG,eAAe,CAEvF;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,YAAoC,GAAG,MAAM,CAE9G;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,GAAE,YAAoC,GAC5C,MAAM,CAKR;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,YAAoC,GAAG,MAAM,CAEtF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGzE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAM3F;AAED,wBAAgB,qBAAqB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAEnE"}
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../../src/core/course/locale.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,IAAI,CAAC;AAEvC,eAAO,MAAM,qBAAqB,EAAE,YAAmB,CAAC;AAExD,eAAO,MAAM,wBAAwB,EAAE,SAAS,YAAY,EAA0B,CAAC;AAEvF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACnD,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CACxB;AA4CD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQjD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAQpD,CAAC;AA2BF,wBAAgB,QAAQ,CAAC,MAAM,GAAE,YAAoC,GAAG,eAAe,CAEtF;AAED,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,YAAoC,GAC3C,MAAM,CAGR;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,MAAM,GAAE,YAAoC,GAC3C,MAAM,CAMR;AAED,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,YAAoC,GAAG,MAAM,CAErF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAGxE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAW3F;AAED,wBAAgB,qBAAqB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,CAElE"}
@@ -1,9 +1,9 @@
1
1
  export const DEFAULT_COURSE_LOCALE = "en";
2
- export const SUPPORTED_COURSE_LOCALES = ["en"];
3
- const UI = {
2
+ export const SUPPORTED_COURSE_LOCALES = ["en", "vi"];
3
+ const UI_EN = {
4
4
  course: "Course",
5
5
  courseTitle: "AI Spector Course",
6
- brandSub: "16 lessons · ~10 min each",
6
+ brandSub: "9 lessons · ~10 min each",
7
7
  searchPlaceholder: "Search lessons…",
8
8
  searchAria: "Search lessons",
9
9
  onThisPage: "On this page",
@@ -18,43 +18,85 @@ const UI = {
18
18
  copy: "Copy",
19
19
  copied: "Copied",
20
20
  inEditor: "In Cursor / Claude Code:",
21
+ localeFallback: "Vietnamese translation not available yet — showing English.",
22
+ };
23
+ const UI_VI = {
24
+ course: "Khóa học",
25
+ courseTitle: "Khóa học AI Spector",
26
+ brandSub: "9 bài · ~10 phút mỗi bài",
27
+ searchPlaceholder: "Tìm bài học…",
28
+ searchAria: "Tìm bài học",
29
+ onThisPage: "Trong trang này",
30
+ previous: "Trước",
31
+ next: "Tiếp",
32
+ lessonOf: (i, t) => `Bài ${i}/${t}`,
33
+ lessonBadge: (i, t) => `Bài ${i} / ${t}`,
34
+ browse: "Duyệt",
35
+ progressTitle: "Tiến độ khóa học",
36
+ tryInChat: "Thử trong chat ↓",
37
+ openNav: "Mở menu",
38
+ copy: "Sao chép",
39
+ copied: "Đã sao chép",
40
+ inEditor: "Trong Cursor / Claude Code:",
41
+ localeFallback: "Bản dịch tiếng Việt chưa có — hiển thị tiếng Anh.",
21
42
  };
22
43
  export const SECTION_LABELS = {
23
- "01-get-started": "Get started",
24
- "02-chat-basics": "Chat basics",
25
- "03-graph": "Graph & sources",
26
- "04-generate": "Generate documents",
27
- "05-prototype": "Design & prototype",
28
- "06-review": "Review & changes",
29
- "07-advanced": "Advanced",
44
+ "01-welcome": "Welcome",
45
+ "02-get-started": "Get started",
46
+ "03-chat-basics": "Chat basics",
47
+ "04-changes": "Changes",
48
+ "05-generate": "Generate",
49
+ "06-review": "Review",
50
+ "07-everyday": "Everyday",
51
+ };
52
+ export const SECTION_LABELS_VI = {
53
+ "01-welcome": "Giới thiệu",
54
+ "02-get-started": "Bắt đầu",
55
+ "03-chat-basics": "Chat cơ bản",
56
+ "04-changes": "Thay đổi",
57
+ "05-generate": "Tạo tài liệu",
58
+ "06-review": "Rà soát",
59
+ "07-everyday": "Hàng ngày",
30
60
  };
31
61
  const CHAT_HINTS = {
32
- "01-get-started": "Try in chat: <code>setup ai-spector project</code>",
33
- "02-chat-basics": "Try in chat: <code>help me approve</code> or <code>active tasks</code>",
34
- "03-graph": "Try in chat: <code>analyze my data source</code> or <code>validate the graph</code>",
35
- "04-generate": "Try in chat: <code>generate the SRS</code> or <code>generate basic design</code>",
36
- "05-prototype": "Try in chat: <code>generate prototype</code>, <code>help me pick a theme</code>, or <code>map external prototype URLs</code>",
62
+ "01-welcome": "Try in chat: <code>open the course</code>",
63
+ "02-get-started": "Try in chat: <code>setup ai-spector project</code>",
64
+ "03-chat-basics": "Try in chat: <code>help me approve</code>",
65
+ "04-changes": "Try in chat: <code>I want to add login with Google</code>",
66
+ "05-generate": "Try in chat: <code>generate the SRS</code>",
37
67
  "06-review": "Try in chat: <code>review documents</code> or <code>resolve comments</code>",
38
- "07-advanced": "Try in chat: <code>set up template pack</code> or <code>find mentions of rate limiting</code>",
68
+ "07-everyday": "Try in chat: <code>active tasks</code> or <code>check my workspace</code>",
39
69
  default: "Ask in chat: <code>open the ai-spector course</code> or <code>help me learn ai-spector</code>",
40
70
  };
41
- export function courseUi(_locale = DEFAULT_COURSE_LOCALE) {
42
- return UI;
71
+ const CHAT_HINTS_VI = {
72
+ "01-welcome": "Thử trong chat: <code>open the course</code>",
73
+ "02-get-started": "Thử trong chat: <code>setup ai-spector project</code>",
74
+ "03-chat-basics": "Thử trong chat: <code>help me approve</code>",
75
+ "04-changes": "Thử trong chat: <code>I want to add login with Google</code>",
76
+ "05-generate": "Thử trong chat: <code>generate the SRS</code>",
77
+ "06-review": "Thử trong chat: <code>review documents</code> hoặc <code>resolve comments</code>",
78
+ "07-everyday": "Thử trong chat: <code>active tasks</code> hoặc <code>check my workspace</code>",
79
+ default: "Hỏi trong chat: <code>open the ai-spector course</code> hoặc <code>help me learn ai-spector</code>",
80
+ };
81
+ export function courseUi(locale = DEFAULT_COURSE_LOCALE) {
82
+ return locale === "vi" ? UI_VI : UI_EN;
43
83
  }
44
- export function sectionLabelForLocale(sectionId, _locale = DEFAULT_COURSE_LOCALE) {
45
- return SECTION_LABELS[sectionId] ?? sectionId;
84
+ export function sectionLabelForLocale(sectionId, locale = DEFAULT_COURSE_LOCALE) {
85
+ const labels = locale === "vi" ? SECTION_LABELS_VI : SECTION_LABELS;
86
+ return labels[sectionId] ?? sectionId;
46
87
  }
47
- export function chatHintForSection(sectionId, _locale = DEFAULT_COURSE_LOCALE) {
48
- if (sectionId && CHAT_HINTS[sectionId]) {
49
- return CHAT_HINTS[sectionId];
88
+ export function chatHintForSection(sectionId, locale = DEFAULT_COURSE_LOCALE) {
89
+ const hints = locale === "vi" ? CHAT_HINTS_VI : CHAT_HINTS;
90
+ if (sectionId && hints[sectionId]) {
91
+ return hints[sectionId];
50
92
  }
51
- return CHAT_HINTS.default;
93
+ return hints.default;
52
94
  }
53
- export function coursePathPrefix(_locale = DEFAULT_COURSE_LOCALE) {
54
- return "/course";
95
+ export function coursePathPrefix(locale = DEFAULT_COURSE_LOCALE) {
96
+ return `/course/${locale}`;
55
97
  }
56
- export function coursePageUrl(_locale, slug) {
57
- const base = coursePathPrefix();
98
+ export function coursePageUrl(locale, slug) {
99
+ const base = coursePathPrefix(locale);
58
100
  return `${base}/${slug === "index" ? "index" : slug}`;
59
101
  }
60
102
  export function parseCourseRequest(pathname) {
@@ -62,9 +104,14 @@ export function parseCourseRequest(pathname) {
62
104
  if (!trimmed || trimmed === "index") {
63
105
  return { locale: "en", slug: "index" };
64
106
  }
107
+ const [first, ...rest] = trimmed.split("/");
108
+ if (first === "en" || first === "vi") {
109
+ const slugRest = rest.join("/");
110
+ return { locale: first, slug: slugRest || "index" };
111
+ }
65
112
  return { locale: "en", slug: trimmed };
66
113
  }
67
- export function normalizeCourseLocale(_value) {
68
- return "en";
114
+ export function normalizeCourseLocale(value) {
115
+ return value === "vi" ? "vi" : "en";
69
116
  }
70
117
  //# sourceMappingURL=locale.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"locale.js","sourceRoot":"","sources":["../../../src/core/course/locale.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"locale.js","sourceRoot":"","sources":["../../../src/core/course/locale.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function legacyCourseRedirect(slug: string): string | undefined;
2
+ export declare function isLegacyCoursePath(pathAfterCourse: string): boolean;
3
+ //# sourceMappingURL=redirects.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../../src/core/course/redirects.ts"],"names":[],"mappings":"AAeA,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAWrE;AAED,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAKnE"}
@@ -0,0 +1,33 @@
1
+ const LEGACY_REDIRECTS = {
2
+ index: "/course/en/index",
3
+ "01-get-started": "/course/en/02-get-started",
4
+ "01-get-started/01-prerequisites-and-init": "/course/en/02-get-started/01-setup-via-chat",
5
+ "01-get-started/02-setup-and-skills": "/course/en/02-get-started/01-setup-via-chat",
6
+ "02-chat-basics": "/course/en/03-chat-basics",
7
+ "02-chat-basics/01-how-chat-works": "/course/en/03-chat-basics/01-how-chat-works",
8
+ "02-chat-basics/02-workspace-and-tasks": "/course/en/07-everyday/01-tasks-and-workspace",
9
+ "02-chat-basics/03-incremental-changes": "/course/en/04-changes/01-add-or-change-requirement",
10
+ "04-generate/01-generate-srs": "/course/en/05-generate/01-generate-srs",
11
+ "04-generate/02-basic-design": "/course/en/index?migrated=1",
12
+ "06-review/01-document-review": "/course/en/06-review/01-document-review",
13
+ "06-review/02-comment-threads": "/course/en/06-review/02-resolve-comments",
14
+ };
15
+ export function legacyCourseRedirect(slug) {
16
+ if (slug.startsWith("en/") || slug.startsWith("vi/")) {
17
+ return undefined;
18
+ }
19
+ if (slug in LEGACY_REDIRECTS) {
20
+ return LEGACY_REDIRECTS[slug];
21
+ }
22
+ if (slug && slug !== "index") {
23
+ return "/course/en/index?migrated=1";
24
+ }
25
+ return undefined;
26
+ }
27
+ export function isLegacyCoursePath(pathAfterCourse) {
28
+ if (!pathAfterCourse || pathAfterCourse === "index") {
29
+ return false;
30
+ }
31
+ return !pathAfterCourse.startsWith("en/") && !pathAfterCourse.startsWith("vi/");
32
+ }
33
+ //# sourceMappingURL=redirects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../../src/core/course/redirects.ts"],"names":[],"mappings":"AAAA,MAAM,gBAAgB,GAA2B;IAC/C,KAAK,EAAE,kBAAkB;IACzB,gBAAgB,EAAE,2BAA2B;IAC7C,0CAA0C,EAAE,6CAA6C;IACzF,oCAAoC,EAAE,6CAA6C;IACnF,gBAAgB,EAAE,2BAA2B;IAC7C,kCAAkC,EAAE,6CAA6C;IACjF,uCAAuC,EAAE,+CAA+C;IACxF,uCAAuC,EAAE,oDAAoD;IAC7F,6BAA6B,EAAE,wCAAwC;IACvE,6BAA6B,EAAE,6BAA6B;IAC5D,8BAA8B,EAAE,yCAAyC;IACzE,8BAA8B,EAAE,0CAA0C;CAC3E,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,IAAI,IAAI,gBAAgB,EAAE,CAAC;QAC7B,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QAC7B,OAAO,6BAA6B,CAAC;IACvC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,eAAuB;IACxD,IAAI,CAAC,eAAe,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAClF,CAAC"}
@@ -1,7 +1,14 @@
1
1
  import type { CoursePage } from "./catalog.js";
2
2
  import { type CourseLocale } from "./locale.js";
3
+ /** Turn :::exercise / :::roletip / :::behind fences into placeholders for HTML injection after render. */
4
+ export declare function preprocessCallouts(markdown: string, locale?: CourseLocale): {
5
+ markdown: string;
6
+ callouts: string[];
7
+ };
3
8
  /** Turn GFM ```mermaid fences into elements mermaid.js can render. */
4
9
  export declare function transformMermaidBlocks(html: string): string;
10
+ /** Turn :::exercise / :::roletip / :::behind fences into styled callouts. */
11
+ export declare function preprocessCalloutsOnly(markdown: string, locale?: CourseLocale): string;
5
12
  export declare function renderCourseMarkdown(markdown: string, currentRelPath?: string, locale?: CourseLocale): Promise<string>;
6
13
  export declare function loadPageHtml(courseRoot: string, page: CoursePage, locale?: CourseLocale): Promise<string>;
7
14
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/core/course/render.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AA0DtF,sEAAsE;AACtE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,cAAc,SAAc,EAC5B,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAGjB"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/core/course/render.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAwC,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAkBtF,0GAA0G;AAC1G,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,YAAoC,GAC3C;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAW1C;AA8DD,sEAAsE;AACtE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ3D;AAED,6EAA6E;AAC7E,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,YAAoC,GAC3C,MAAM,CAER;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,cAAc,SAAc,EAC5B,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,YAAoC,GAC3C,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -11,6 +11,33 @@ const mdProcessor = unified()
11
11
  .use(remarkGfm)
12
12
  .use(remarkRehype)
13
13
  .use(rehypeStringify);
14
+ const CALLOUT_PLACEHOLDER = "AISPECTOR_CALLOUT_";
15
+ function calloutHtml(kind, body, locale) {
16
+ const behindLabel = locale === "vi" ? "Chi tiết kỹ thuật" : "Behind the scenes";
17
+ if (kind === "behind") {
18
+ return `<details class="callout behind"><summary>${behindLabel}</summary>${body.trim()}</details>`;
19
+ }
20
+ return `<div class="callout ${kind}">${body.trim()}</div>`;
21
+ }
22
+ /** Turn :::exercise / :::roletip / :::behind fences into placeholders for HTML injection after render. */
23
+ export function preprocessCallouts(markdown, locale = DEFAULT_COURSE_LOCALE) {
24
+ const callouts = [];
25
+ const processed = markdown.replace(/:::(exercise|roletip|behind)\n([\s\S]*?):::/g, (_, kind, body) => {
26
+ const idx = callouts.length;
27
+ callouts.push(calloutHtml(kind, body, locale));
28
+ return `\n\n${CALLOUT_PLACEHOLDER}${idx}\n\n`;
29
+ });
30
+ return { markdown: processed, callouts };
31
+ }
32
+ function injectCallouts(html, callouts) {
33
+ let result = html;
34
+ for (let i = 0; i < callouts.length; i++) {
35
+ const para = new RegExp(`<p>${CALLOUT_PLACEHOLDER}${i}</p>`, "g");
36
+ result = result.replace(para, callouts[i]);
37
+ result = result.replaceAll(`${CALLOUT_PLACEHOLDER}${i}`, callouts[i]);
38
+ }
39
+ return result;
40
+ }
14
41
  function slugFromHref(href, currentRelPath, locale) {
15
42
  const clean = href.split("#")[0];
16
43
  const hash = href.includes("#") ? `#${href.split("#").slice(1).join("#")}` : "";
@@ -61,10 +88,16 @@ export function transformMermaidBlocks(html) {
61
88
  return `<div class="mermaid-diagram"><pre class="mermaid">${diagram}</pre></div>`;
62
89
  });
63
90
  }
91
+ /** Turn :::exercise / :::roletip / :::behind fences into styled callouts. */
92
+ export function preprocessCalloutsOnly(markdown, locale = DEFAULT_COURSE_LOCALE) {
93
+ return preprocessCallouts(markdown, locale).markdown;
94
+ }
64
95
  export async function renderCourseMarkdown(markdown, currentRelPath = "README.md", locale = DEFAULT_COURSE_LOCALE) {
65
- const prepared = rewriteMarkdownLinks(markdown, currentRelPath, locale);
96
+ const { markdown: withPlaceholders, callouts } = preprocessCallouts(markdown, locale);
97
+ const prepared = rewriteMarkdownLinks(withPlaceholders, currentRelPath, locale);
66
98
  const file = await mdProcessor.process(prepared);
67
- return transformMermaidBlocks(String(file));
99
+ const html = transformMermaidBlocks(String(file));
100
+ return injectCallouts(html, callouts);
68
101
  }
69
102
  export async function loadPageHtml(courseRoot, page, locale = DEFAULT_COURSE_LOCALE) {
70
103
  const markdown = await readFile(join(courseRoot, page.relPath), "utf8");