mosage 0.2.0 → 0.8.0

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 (121) hide show
  1. package/README.md +16 -15
  2. package/bin.js +2 -0
  3. package/dist/build-C7NW_3Pk.js +14 -0
  4. package/dist/check-CP4873Wx.js +41 -0
  5. package/dist/cli/bin.d.ts +1 -0
  6. package/dist/cli/bin.js +228 -0
  7. package/dist/config-DPm1BBAb.js +2619 -0
  8. package/dist/config-TlTe7Ona.d.ts +24 -0
  9. package/dist/context-BqsdSrAQ.js +1084 -0
  10. package/dist/dev-Biz42qlu.js +17 -0
  11. package/dist/diagram-xlVDekYk.js +763 -0
  12. package/dist/export-Bi6nuxjT.js +31 -0
  13. package/dist/import-D2jNB07F.js +25 -0
  14. package/dist/index.d.ts +455 -0
  15. package/dist/index.js +693 -0
  16. package/dist/{cli.js → init-Bbtj2pxF.js} +34 -68
  17. package/dist/preview-CLm51aRt.js +19 -0
  18. package/dist/sdk-DjpX6mCv.js +51 -0
  19. package/dist/vite/index.d.ts +25 -0
  20. package/dist/vite/index.js +2 -0
  21. package/env.d.ts +83 -0
  22. package/package.json +59 -12
  23. package/{template/.agents/skills → skills}/create-doc/SKILL.md +1 -1
  24. package/{template/.agents/skills → skills}/create-theme/SKILL.md +1 -1
  25. package/{template/.agents/skills → skills}/doc-authoring/SKILL.md +8 -9
  26. package/{template/.agents/skills → skills}/doc-authoring/references/assets.md +1 -1
  27. package/{template/.agents/skills → skills}/doc-authoring/references/design-system.md +1 -1
  28. package/{template/.agents/skills → skills}/doc-authoring/references/long-form.md +4 -4
  29. package/{template/.agents/skills → skills}/doc-authoring/references/pagination.md +1 -1
  30. package/src/app/app.tsx +42 -0
  31. package/src/app/components/data-table.tsx +196 -0
  32. package/src/app/components/design-panel/design-panel.tsx +318 -0
  33. package/src/app/components/design-panel/design-provider.tsx +121 -0
  34. package/src/app/components/design-panel/use-design.ts +85 -0
  35. package/src/app/components/diagram.tsx +76 -0
  36. package/src/app/components/doc-assets.tsx +129 -0
  37. package/src/app/components/doc-search.tsx +248 -0
  38. package/src/app/components/doc-sidebar.tsx +162 -0
  39. package/src/app/components/flow-page.tsx +93 -0
  40. package/src/app/components/footnote.tsx +204 -0
  41. package/src/app/components/image-placeholder.tsx +50 -0
  42. package/src/app/components/inspector/inspector.tsx +518 -0
  43. package/src/app/components/numbering.tsx +224 -0
  44. package/src/app/components/page-frame.tsx +70 -0
  45. package/src/app/components/sidebar/folder-item.tsx +212 -0
  46. package/src/app/components/sidebar/icon-picker.tsx +99 -0
  47. package/src/app/components/sidebar/sidebar.tsx +252 -0
  48. package/src/app/components/table-of-contents.tsx +93 -0
  49. package/src/app/components/theme-toggle.tsx +50 -0
  50. package/src/app/components/themes/markdown.tsx +249 -0
  51. package/src/app/components/themes/theme-preview.tsx +74 -0
  52. package/src/app/components/ui/menu.tsx +143 -0
  53. package/src/app/index.html +12 -0
  54. package/src/app/lib/agent-bridge.ts +140 -0
  55. package/src/app/lib/assets.ts +151 -0
  56. package/src/app/lib/design-presets.ts +109 -0
  57. package/src/app/lib/design.ts +88 -0
  58. package/src/app/lib/diagnostics.ts +282 -0
  59. package/src/app/lib/doc-preview.tsx +29 -0
  60. package/src/app/lib/docs.ts +26 -0
  61. package/src/app/lib/docx/extract.ts +1623 -0
  62. package/src/app/lib/docx/fonts.test.ts +136 -0
  63. package/src/app/lib/docx/fonts.ts +166 -0
  64. package/src/app/lib/docx/media.ts +102 -0
  65. package/src/app/lib/docx/model.ts +206 -0
  66. package/src/app/lib/docx/paragraph.test.ts +92 -0
  67. package/src/app/lib/docx/paragraph.ts +107 -0
  68. package/src/app/lib/docx/props.ts +187 -0
  69. package/src/app/lib/docx/styles.ts +306 -0
  70. package/src/app/lib/docx/units.ts +35 -0
  71. package/src/app/lib/docx/write.test.ts +507 -0
  72. package/src/app/lib/docx/write.ts +581 -0
  73. package/src/app/lib/docx/xml.ts +39 -0
  74. package/src/app/lib/export-docx.ts +289 -0
  75. package/src/app/lib/export-dom.ts +318 -0
  76. package/src/app/lib/export-html.ts +156 -0
  77. package/src/app/lib/export-image.ts +70 -0
  78. package/src/app/lib/export-pdf.ts +165 -0
  79. package/src/app/lib/flow-measure.test.ts +31 -0
  80. package/src/app/lib/flow-measure.ts +183 -0
  81. package/src/app/lib/flow.test.ts +110 -0
  82. package/src/app/lib/flow.ts +136 -0
  83. package/src/app/lib/folders.ts +192 -0
  84. package/src/app/lib/footnotes.test.tsx +102 -0
  85. package/src/app/lib/footnotes.ts +94 -0
  86. package/src/app/lib/inspector/fiber.ts +99 -0
  87. package/src/app/lib/labels.test.ts +18 -0
  88. package/src/app/lib/labels.ts +181 -0
  89. package/src/app/lib/outline.ts +118 -0
  90. package/src/app/lib/page-context.tsx +43 -0
  91. package/src/app/lib/page-range.test.ts +95 -0
  92. package/src/app/lib/page-range.ts +90 -0
  93. package/src/app/lib/print-ready.ts +69 -0
  94. package/src/app/lib/rasterize.ts +173 -0
  95. package/src/app/lib/scan.ts +26 -0
  96. package/src/app/lib/sdk.test.ts +32 -0
  97. package/src/app/lib/sdk.ts +115 -0
  98. package/src/app/lib/themes.ts +31 -0
  99. package/src/app/lib/use-doc-module.ts +53 -0
  100. package/src/app/lib/use-doc-pages.ts +147 -0
  101. package/src/app/lib/utils.ts +6 -0
  102. package/src/app/lib/view-mode.test.ts +91 -0
  103. package/src/app/lib/view-mode.ts +104 -0
  104. package/src/app/main.tsx +14 -0
  105. package/src/app/routes/assets.tsx +257 -0
  106. package/src/app/routes/doc.tsx +877 -0
  107. package/src/app/routes/home-shell.tsx +203 -0
  108. package/src/app/routes/home.tsx +269 -0
  109. package/src/app/routes/themes.tsx +121 -0
  110. package/src/app/styles.css +97 -0
  111. package/src/app/virtual.d.ts +30 -0
  112. package/template/AGENTS.md +1 -1
  113. package/template/README.md +24 -52
  114. package/template/docs/getting-started/index.tsx +2 -2
  115. package/template/mosage.config.ts +1 -1
  116. package/template/package.json +1 -1
  117. package/template/tsconfig.json +1 -1
  118. package/README.zh-TW.md +0 -28
  119. /package/{template/.agents/skills → skills}/apply-comments/SKILL.md +0 -0
  120. /package/{template/.agents/skills → skills}/current-doc/SKILL.md +0 -0
  121. /package/{template/.agents/skills → skills}/doc-authoring/references/tables-and-charts.md +0 -0
@@ -1,15 +1,13 @@
1
- #!/usr/bin/env node
1
+ import { n as packageRoot, r as readCoreVersion, t as syncSkills } from "./cli/bin.js";
2
2
  import chalk from "chalk";
3
- import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
4
3
  import { basename, dirname, join, resolve } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { Command } from "commander";
7
- import prompts from "prompts";
8
- import { spawn } from "node:child_process";
9
4
  import { existsSync } from "node:fs";
10
- //#region src/git.ts
5
+ import { cp, mkdir, readFile, readdir, rm, symlink, writeFile } from "node:fs/promises";
6
+ import { spawn } from "node:child_process";
7
+ import prompts from "prompts";
8
+ //#region src/cli/git.ts
11
9
  const IS_WINDOWS$1 = process.platform === "win32";
12
- async function run$1(cmd, args, cwd) {
10
+ async function run(cmd, args, cwd) {
13
11
  return new Promise((resolve, reject) => {
14
12
  const child = spawn(cmd, args, {
15
13
  cwd,
@@ -38,14 +36,14 @@ async function run$1(cmd, args, cwd) {
38
36
  }
39
37
  async function isGitAvailable() {
40
38
  try {
41
- return (await run$1("git", ["--version"], process.cwd())).code === 0;
39
+ return (await run("git", ["--version"], process.cwd())).code === 0;
42
40
  } catch {
43
41
  return false;
44
42
  }
45
43
  }
46
44
  async function isInsideWorkTree(cwd) {
47
45
  try {
48
- const res = await run$1("git", ["rev-parse", "--is-inside-work-tree"], cwd);
46
+ const res = await run("git", ["rev-parse", "--is-inside-work-tree"], cwd);
49
47
  return res.code === 0 && res.stdout.trim() === "true";
50
48
  } catch {
51
49
  return false;
@@ -69,7 +67,7 @@ async function gitInitAndCommit(target) {
69
67
  "chore: init MoSage project"
70
68
  ], "git commit"]
71
69
  ]) {
72
- const res = await run$1("git", [...args], target);
70
+ const res = await run("git", [...args], target);
73
71
  if (res.code !== 0) return {
74
72
  status: "failed",
75
73
  message: `${label} failed: ${res.stderr.trim() || res.stdout.trim()}`
@@ -78,9 +76,22 @@ async function gitInitAndCommit(target) {
78
76
  return { status: "committed" };
79
77
  }
80
78
  //#endregion
81
- //#region src/init.ts
82
- const HERE = dirname(fileURLToPath(import.meta.url));
83
- const TEMPLATE_DIR = resolve(HERE, "..", "template");
79
+ //#region src/cli/package-manager.ts
80
+ const PACKAGE_MANAGERS = [
81
+ "npm",
82
+ "pnpm",
83
+ "yarn",
84
+ "bun"
85
+ ];
86
+ function detectPackageManager() {
87
+ const ua = process.env.npm_config_user_agent ?? "";
88
+ if (ua.startsWith("pnpm")) return "pnpm";
89
+ if (ua.startsWith("yarn")) return "yarn";
90
+ if (ua.startsWith("bun")) return "bun";
91
+ return "npm";
92
+ }
93
+ //#endregion
94
+ //#region src/cli/init.ts
84
95
  const IS_WINDOWS = process.platform === "win32";
85
96
  function sanitizeDirName(value) {
86
97
  const trimmed = value.trim();
@@ -93,9 +104,6 @@ async function isDirNonEmpty(target) {
93
104
  if (!existsSync(target)) return false;
94
105
  return (await readdir(target)).some((e) => !e.startsWith("."));
95
106
  }
96
- function coreVersionRange() {
97
- return `^0.7.0`;
98
- }
99
107
  async function linkOrCopy(relSrc, dst) {
100
108
  await rm(dst, {
101
109
  recursive: true,
@@ -107,17 +115,9 @@ async function linkOrCopy(relSrc, dst) {
107
115
  }
108
116
  await symlink(relSrc, dst);
109
117
  }
110
- async function materializeTemplateLinks(target) {
118
+ async function linkClaudeMd(target) {
111
119
  const claudeMd = join(target, "CLAUDE.md");
112
120
  if (!existsSync(claudeMd) && existsSync(join(target, "AGENTS.md"))) await linkOrCopy("AGENTS.md", claudeMd);
113
- const agentsSkills = join(target, ".agents", "skills");
114
- if (!existsSync(agentsSkills)) return;
115
- const claudeSkills = join(target, ".claude", "skills");
116
- await mkdir(claudeSkills, { recursive: true });
117
- for (const entry of await readdir(agentsSkills, { withFileTypes: true })) {
118
- if (!entry.isDirectory()) continue;
119
- await linkOrCopy(join("..", "..", ".agents", "skills", entry.name), join(claudeSkills, entry.name));
120
- }
121
121
  }
122
122
  async function runInstall(pm, cwd) {
123
123
  await new Promise((res, rej) => {
@@ -132,19 +132,22 @@ async function runInstall(pm, cwd) {
132
132
  }
133
133
  async function init(opts) {
134
134
  const { dir, force, name, packageManager, install, git } = opts;
135
- if (!existsSync(TEMPLATE_DIR)) throw new Error(`Template missing at ${TEMPLATE_DIR}. If you are running from source, run \`pnpm --filter mosage build\` first.`);
135
+ const root = packageRoot();
136
+ const templateDir = root ? join(root, "template") : "";
137
+ if (!root || !existsSync(templateDir)) throw new Error("Project template not found — reinstall mosage.");
136
138
  const target = resolve(process.cwd(), dir);
137
139
  await mkdir(target, { recursive: true });
138
140
  if (await isDirNonEmpty(target) && !force) throw new Error(`Target ${target} is not empty. Pass --force to scaffold into it anyway.`);
139
- await cp(TEMPLATE_DIR, target, { recursive: true });
140
- await materializeTemplateLinks(target);
141
+ await cp(templateDir, target, { recursive: true });
142
+ await linkClaudeMd(target);
143
+ await syncSkills(join(root, "skills"), { quiet: true }, target);
141
144
  const pkgPath = join(target, "package.json");
142
145
  if (existsSync(pkgPath)) {
143
146
  const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
144
147
  pkg.name = name ?? basename(target);
145
148
  pkg.version = "0.0.0";
146
149
  pkg.private = true;
147
- if (pkg.dependencies?.["mosage-core"]) pkg.dependencies["mosage-core"] = coreVersionRange();
150
+ if (pkg.dependencies?.mosage) pkg.dependencies.mosage = `^${await readCoreVersion()}`;
148
151
  await writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
149
152
  }
150
153
  await writeFile(join(target, ".gitignore"), "node_modules\ndist\n.DS_Store\n");
@@ -181,27 +184,6 @@ async function init(opts) {
181
184
  const devCommand = packageManager === "npm" ? "npm run dev" : `${packageManager} dev`;
182
185
  process.stdout.write(` ${chalk.cyan(devCommand)}\n`);
183
186
  }
184
- //#endregion
185
- //#region src/package-manager.ts
186
- const PACKAGE_MANAGERS = [
187
- "npm",
188
- "pnpm",
189
- "yarn",
190
- "bun"
191
- ];
192
- function detectPackageManager() {
193
- const ua = process.env.npm_config_user_agent ?? "";
194
- if (ua.startsWith("pnpm")) return "pnpm";
195
- if (ua.startsWith("yarn")) return "yarn";
196
- if (ua.startsWith("bun")) return "bun";
197
- return "npm";
198
- }
199
- //#endregion
200
- //#region src/index.ts
201
- async function readVersion() {
202
- const here = dirname(fileURLToPath(import.meta.url));
203
- return JSON.parse(await readFile(join(here, "..", "package.json"), "utf8")).version;
204
- }
205
187
  function onCancel() {
206
188
  process.stdout.write(chalk.dim("\nCancelled.\n"));
207
189
  process.exit(130);
@@ -276,21 +258,5 @@ async function runInit(dirArg, flags) {
276
258
  git: flags.git !== false
277
259
  });
278
260
  }
279
- async function run(argv) {
280
- const version = await readVersion();
281
- const program = new Command();
282
- program.name("mosage").description("Scaffold and manage MoSage workspaces.").version(version, "-v, --version", "print version").helpOption("-h, --help", "show help").showHelpAfterError(chalk.dim("(run `mosage --help` for usage)"));
283
- program.command("init").description("Create a new MoSage workspace").argument("[dir]", "target directory", void 0).option("-f, --force", "overwrite non-empty target directory", false).option("-n, --name <name>", "override package name (defaults to folder name)").option("--use-npm", "use npm to install dependencies").option("--use-pnpm", "use pnpm to install dependencies").option("--use-yarn", "use yarn to install dependencies").option("--use-bun", "use bun to install dependencies").option("--no-install", "skip dependency installation").option("--no-git", "skip git init and initial commit").action(async (dir, flags) => {
284
- await runInit(dir, flags);
285
- });
286
- await program.parseAsync(argv, { from: "user" });
287
- }
288
- //#endregion
289
- //#region src/cli.ts
290
- run(process.argv.slice(2)).catch((err) => {
291
- const message = err instanceof Error ? err.message : String(err);
292
- process.stderr.write(`${chalk.red("error:")} ${message}\n`);
293
- process.exit(1);
294
- });
295
261
  //#endregion
296
- export {};
262
+ export { runInit };
@@ -0,0 +1,19 @@
1
+ import { t as createViteConfig } from "./config-DPm1BBAb.js";
2
+ import { mergeConfig, preview as preview$1 } from "vite";
3
+ //#region src/cli/preview.ts
4
+ async function preview(opts = {}) {
5
+ const base = await createViteConfig({
6
+ userCwd: process.cwd(),
7
+ mode: "build"
8
+ });
9
+ const config = mergeConfig(base, { preview: {
10
+ ...opts.port !== void 0 ? { port: opts.port } : {},
11
+ ...opts.host !== void 0 ? { host: opts.host } : {},
12
+ ...opts.open !== void 0 ? { open: opts.open } : {}
13
+ } });
14
+ const server = await preview$1(config);
15
+ server.printUrls();
16
+ server.bindCLIShortcuts({ print: true });
17
+ }
18
+ //#endregion
19
+ export { preview };
@@ -0,0 +1,51 @@
1
+ //#region src/app/lib/sdk.ts
2
+ /** The only sheets a document may be laid out on. */
3
+ const PAGE_SIZE_NAMES = [
4
+ "A4",
5
+ "B4",
6
+ "A3"
7
+ ];
8
+ const ORIENTATIONS = ["portrait", "landscape"];
9
+ /**
10
+ * Portrait dimensions in CSS pixels at 96dpi — the unit authors write in —
11
+ * paired with the physical millimetres used when printing. Keeping both means a
12
+ * page laid out at 794×1123 on screen maps to a real A4 sheet with no rescaling.
13
+ */
14
+ const PAGE_SIZES = {
15
+ A4: {
16
+ width: 794,
17
+ height: 1123,
18
+ mm: [210, 297]
19
+ },
20
+ B4: {
21
+ width: 971,
22
+ height: 1376,
23
+ mm: [257, 364]
24
+ },
25
+ A3: {
26
+ width: 1123,
27
+ height: 1587,
28
+ mm: [297, 420]
29
+ }
30
+ };
31
+ const DEFAULT_PAGE_SIZE = "A4";
32
+ const DEFAULT_ORIENTATION = "portrait";
33
+ function isPageSizeName(value) {
34
+ return typeof value === "string" && value in PAGE_SIZES;
35
+ }
36
+ function isOrientation(value) {
37
+ return value === "portrait" || value === "landscape";
38
+ }
39
+ function resolvePageGeometry(meta) {
40
+ const size = PAGE_SIZES[meta?.pageSize ?? "A4"] ?? PAGE_SIZES["A4"];
41
+ const landscape = meta?.orientation === "landscape";
42
+ const [across, down] = landscape ? [size.mm[1], size.mm[0]] : size.mm;
43
+ return {
44
+ width: landscape ? size.height : size.width,
45
+ height: landscape ? size.width : size.height,
46
+ mm: [across, down],
47
+ css: `${across}mm ${down}mm`
48
+ };
49
+ }
50
+ //#endregion
51
+ export { PAGE_SIZE_NAMES as a, resolvePageGeometry as c, PAGE_SIZES as i, DEFAULT_PAGE_SIZE as n, isOrientation as o, ORIENTATIONS as r, isPageSizeName as s, DEFAULT_ORIENTATION as t };
@@ -0,0 +1,25 @@
1
+ import { n as MoSageConfig } from "../config-TlTe7Ona.js";
2
+ import { InlineConfig, Plugin } from "vite";
3
+ //#region src/vite/mosage-plugin.d.ts
4
+ type MoSagePluginOptions = {
5
+ userCwd: string;
6
+ config: MoSageConfig;
7
+ coreVersion: string;
8
+ };
9
+ declare function mosagePlugin(opts: MoSagePluginOptions): Plugin;
10
+ //#endregion
11
+ //#region src/vite/config.d.ts
12
+ type CreateViteConfigOptions = {
13
+ userCwd: string;
14
+ config?: MoSageConfig;
15
+ mode?: 'serve' | 'build';
16
+ /**
17
+ * Drive the app from a headless browser rather than a person. Leaves out the
18
+ * plugins that exist to serve a reader — chiefly the one publishing the
19
+ * reading position, which an export would otherwise overwrite.
20
+ */
21
+ headless?: boolean;
22
+ };
23
+ declare function createViteConfig(opts: CreateViteConfigOptions): Promise<InlineConfig>;
24
+ //#endregion
25
+ export { createViteConfig, mosagePlugin };
@@ -0,0 +1,2 @@
1
+ import { t as createViteConfig, u as mosagePlugin } from "../config-DPm1BBAb.js";
2
+ export { createViteConfig, mosagePlugin };
package/env.d.ts ADDED
@@ -0,0 +1,83 @@
1
+ // Ambient module declarations for assets imported from `docs/<id>/assets/`
2
+ // and for the data files the framework parses at build time.
3
+ // Mirrors Vite's default asset handling (default export = resolved URL).
4
+ //
5
+ // Consumers opt in via tsconfig:
6
+ //
7
+ // { "compilerOptions": { "types": ["mosage/env"] } }
8
+
9
+ declare module '*.svg' {
10
+ const src: string;
11
+ export default src;
12
+ }
13
+ declare module '*.png' {
14
+ const src: string;
15
+ export default src;
16
+ }
17
+ declare module '*.jpg' {
18
+ const src: string;
19
+ export default src;
20
+ }
21
+ declare module '*.jpeg' {
22
+ const src: string;
23
+ export default src;
24
+ }
25
+ declare module '*.webp' {
26
+ const src: string;
27
+ export default src;
28
+ }
29
+ declare module '*.gif' {
30
+ const src: string;
31
+ export default src;
32
+ }
33
+ declare module '*.avif' {
34
+ const src: string;
35
+ export default src;
36
+ }
37
+ declare module '*.woff' {
38
+ const src: string;
39
+ export default src;
40
+ }
41
+ declare module '*.woff2' {
42
+ const src: string;
43
+ export default src;
44
+ }
45
+ declare module '*.ttf' {
46
+ const src: string;
47
+ export default src;
48
+ }
49
+ declare module '*.otf' {
50
+ const src: string;
51
+ export default src;
52
+ }
53
+
54
+ // Parsed by the `mosage:data` Vite plugin — the default export is the rows.
55
+ declare module '*.csv' {
56
+ type CellValue = string | number | null;
57
+ export const columns: string[];
58
+ export const rows: Array<Record<string, CellValue>>;
59
+ export default rows;
60
+ }
61
+ declare module '*.tsv' {
62
+ type CellValue = string | number | null;
63
+ export const columns: string[];
64
+ export const rows: Array<Record<string, CellValue>>;
65
+ export default rows;
66
+ }
67
+
68
+ // Compiled by the `mosage:diagram` Vite plugin — the default export is the
69
+ // themed SVG and its natural size, ready for `<Diagram chart={…} />`.
70
+ declare module '*.mmd' {
71
+ export const svg: string;
72
+ export const width: number;
73
+ export const height: number;
74
+ const chart: { svg: string; width: number; height: number };
75
+ export default chart;
76
+ }
77
+ declare module '*.mermaid' {
78
+ export const svg: string;
79
+ export const width: number;
80
+ export const height: number;
81
+ const chart: { svg: string; width: number; height: number };
82
+ export default chart;
83
+ }
package/package.json CHANGED
@@ -1,25 +1,46 @@
1
1
  {
2
2
  "name": "mosage",
3
- "version": "0.2.0",
4
- "description": "Scaffold a MoSage workspace with agent skills preconfigured.",
3
+ "version": "0.8.0",
4
+ "description": "Write documents with your coding agent — MoSage scaffolds the workspace and handles the pages, print layout, and export (PDF, HTML, Word).",
5
5
  "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ },
11
+ "./vite": {
12
+ "types": "./dist/vite/index.d.ts",
13
+ "import": "./dist/vite/index.js"
14
+ },
15
+ "./env": {
16
+ "types": "./env.d.ts"
17
+ }
18
+ },
6
19
  "bin": {
7
- "mosage": "dist/cli.js"
20
+ "mosage": "./bin.js"
8
21
  },
9
22
  "files": [
23
+ "bin.js",
10
24
  "dist",
25
+ "env.d.ts",
26
+ "src/app",
27
+ "skills",
11
28
  "template",
12
- "README.md",
13
- "README.zh-TW.md"
29
+ "README.md"
14
30
  ],
15
31
  "engines": {
16
32
  "node": ">=18"
17
33
  },
18
34
  "keywords": [
35
+ "agent",
19
36
  "document",
20
- "report",
37
+ "docx",
21
38
  "pdf",
22
- "scaffold"
39
+ "react",
40
+ "report",
41
+ "scaffold",
42
+ "vite",
43
+ "word"
23
44
  ],
24
45
  "license": "MIT",
25
46
  "author": {
@@ -30,7 +51,7 @@
30
51
  "repository": {
31
52
  "type": "git",
32
53
  "url": "git+https://github.com/nickchen1998/MoSage.git",
33
- "directory": "packages/cli"
54
+ "directory": "packages/core"
34
55
  },
35
56
  "bugs": {
36
57
  "url": "https://github.com/nickchen1998/MoSage/issues"
@@ -39,15 +60,41 @@
39
60
  "access": "public"
40
61
  },
41
62
  "dependencies": {
63
+ "@babel/parser": "^8.0.4",
64
+ "@tailwindcss/vite": "^4.3.3",
65
+ "@vitejs/plugin-react": "^6.0.5",
42
66
  "chalk": "^6.0.0",
67
+ "clsx": "^2.1.1",
43
68
  "commander": "^15.0.0",
69
+ "fast-glob": "^3.3.2",
70
+ "fflate": "^0.8.3",
71
+ "lucide-react": "^1.25.0",
72
+ "next-themes": "^0.4.6",
73
+ "react": "^18.3.1",
74
+ "react-dom": "^18.3.1",
75
+ "react-router-dom": "^7.18.1",
76
+ "tailwind-merge": "^3.5.0",
77
+ "tailwindcss": "^4.2.2",
78
+ "vite": "^8.2.1",
44
79
  "prompts": "^2.4.2"
45
80
  },
46
81
  "devDependencies": {
82
+ "@playwright/test": "~1.56.1",
47
83
  "@types/node": "^22.19.17",
48
- "@types/prompts": "^2.4.9",
84
+ "@types/react": "^18.3.12",
85
+ "@types/react-dom": "^18.3.1",
86
+ "playwright": "~1.56.1",
49
87
  "tsdown": "^0.22.14",
50
- "typescript": "^5.9.3"
88
+ "typescript": "^5.9.3",
89
+ "@types/prompts": "^2.4.9"
90
+ },
91
+ "peerDependencies": {
92
+ "playwright": "*"
93
+ },
94
+ "peerDependenciesMeta": {
95
+ "playwright": {
96
+ "optional": true
97
+ }
51
98
  },
52
99
  "contributors": [
53
100
  {
@@ -56,8 +103,8 @@
56
103
  }
57
104
  ],
58
105
  "scripts": {
59
- "build": "node scripts/sync-template-skills.mjs && tsdown",
106
+ "build": "tsdown",
60
107
  "typecheck": "tsc --noEmit",
61
- "sync:template-skills": "node scripts/sync-template-skills.mjs"
108
+ "test:e2e": "pnpm run build && playwright test"
62
109
  }
63
110
  }
@@ -89,7 +89,7 @@ While writing:
89
89
 
90
90
  ## Step 7 — Self-review
91
91
 
92
- **Run `mosage check <id>` first.** You cannot see the sheets you produced; it renders them at true page size and reports clipped content, blank pages, stranded headings, and unreadable type, each with a source location. Fix every error before moving on. (Driving the MCP server instead? `check_layout`, and `render_page` when you need to look at a sheet.)
92
+ **Run `mosage check <id>` first.** You cannot see the sheets you produced; it renders them at true page size and reports clipped content, blank pages, stranded headings, and unreadable type, each with a source location. Fix every error before moving on.
93
93
 
94
94
  Then run the checklist in `doc-authoring` ("Self-review before finishing"), and re-read the prose once as a reader: does the summary state the conclusion? Does every claim have a source?
95
95
 
@@ -145,7 +145,7 @@ Include a callout and a stat component when the theme calls for them.
145
145
  A normal document module — **two pages**: a cover and one content page that exercises the theme's headings, body copy, a table, and the running footer.
146
146
 
147
147
  ```tsx
148
- import { type DesignSystem, type DocPage, useDocPageCount, useDocPageNumber } from 'mosage-core';
148
+ import { type DesignSystem, type DocPage, useDocPageCount, useDocPageNumber } from 'mosage';
149
149
 
150
150
  export const design: DesignSystem = { /* the same const as in the .md */ };
151
151
 
@@ -34,14 +34,14 @@ Themes are produced by the `create-theme` skill and are pure documentation: copy
34
34
  - Put the document under `docs/<kebab-case-id>/`.
35
35
  - Entry is `docs/<id>/index.tsx`. Images/fonts go under `docs/<id>/assets/`.
36
36
  - Do **not** touch `package.json`, `mosage.config.ts`, or other documents.
37
- - Do not add dependencies. Only `react`, `mosage-core`, and standard web APIs are available.
37
+ - Do not add dependencies. Only `react`, `mosage`, and standard web APIs are available.
38
38
  - A document is **one `index.tsx` plus `assets/`** — nothing else. Helper components and constants live inside `index.tsx`; no sibling `.tsx` files, no `README.md`.
39
39
 
40
40
  ## File contract
41
41
 
42
42
  ```tsx
43
43
  // docs/<id>/index.tsx
44
- import type { DocMeta, DocPage } from 'mosage-core';
44
+ import type { DocMeta, DocPage } from 'mosage';
45
45
 
46
46
  const Cover: DocPage = () => <div>…</div>;
47
47
  const Body: DocPage = () => <div>…</div>;
@@ -65,7 +65,7 @@ export default [Cover, Body] satisfies DocPage[];
65
65
  ## Two ways to fill pages
66
66
 
67
67
  ```tsx
68
- import { flow, type DocEntry } from 'mosage-core';
68
+ import { flow, type DocEntry } from 'mosage';
69
69
 
70
70
  const Body = flow(
71
71
  <>
@@ -172,7 +172,7 @@ flowchart TD
172
172
  ```
173
173
 
174
174
  ```tsx
175
- import { Diagram } from 'mosage-core';
175
+ import { Diagram } from 'mosage';
176
176
  import architecture from './architecture.mmd';
177
177
 
178
178
  <Diagram chart={architecture} caption="請求路徑" width={420} />
@@ -194,7 +194,7 @@ fault, and `mosage check` reports it as one.
194
194
  ## Table of contents
195
195
 
196
196
  ```tsx
197
- import { TableOfContents } from 'mosage-core';
197
+ import { TableOfContents } from 'mosage';
198
198
 
199
199
  const Contents: DocPage = () => (
200
200
  <div style={page}>
@@ -209,7 +209,7 @@ Page numbers come from the scan, so they are always correct — **never hand-wri
209
209
  ## Page numbers, headers, footers
210
210
 
211
211
  ```tsx
212
- import { useDocPageCount, useDocPageNumber } from 'mosage-core';
212
+ import { useDocPageCount, useDocPageNumber } from 'mosage';
213
213
 
214
214
  const Footer = () => {
215
215
  const page = useDocPageNumber();
@@ -230,7 +230,7 @@ const Footer = () => {
230
230
  ## Starter template
231
231
 
232
232
  ```tsx
233
- import { type DesignSystem, type DocMeta, type DocPage, useDocPageCount, useDocPageNumber } from 'mosage-core';
233
+ import { type DesignSystem, type DocMeta, type DocPage, useDocPageCount, useDocPageNumber } from 'mosage';
234
234
 
235
235
  export const design: DesignSystem = {
236
236
  palette: {
@@ -394,8 +394,7 @@ mosage check <id> # every document if you omit the id; exits non-zero on err
394
394
  It renders each sheet at true page size and reports what a reader would call a
395
395
  mistake — content clipped by the page edge, a blank sheet, a heading stranded at
396
396
  the foot of a page, type too small to print, an image that never loaded — each
397
- with the `line:column` in your source. Agents driving the MCP server call
398
- `check_layout` for the same report, and `render_page` for a PNG of one sheet.
397
+ with the `line:column` in your source.
399
398
 
400
399
  **Run it after writing a document and after any edit that changes how much text
401
400
  is on a page.** The checklist below is what you reason about; `check` is what
@@ -30,7 +30,7 @@ Rules:
30
30
  When a page needs a real image **the user has to provide** — a chart from their data, a product screenshot, a signed diagram — leave a typed placeholder instead of inventing a stand-in:
31
31
 
32
32
  ```tsx
33
- import { ImagePlaceholder } from 'mosage-core';
33
+ import { ImagePlaceholder } from 'mosage';
34
34
 
35
35
  <ImagePlaceholder hint="Revenue by segment, Q1–Q3 2026 — export from the finance dashboard" height={200} />
36
36
  ```
@@ -5,7 +5,7 @@ Every document declares typed design tokens at the top of `index.tsx` and consum
5
5
  ## The shape
6
6
 
7
7
  ```tsx
8
- import type { DesignSystem } from 'mosage-core';
8
+ import type { DesignSystem } from 'mosage';
9
9
 
10
10
  export const design: DesignSystem = {
11
11
  palette: {
@@ -12,7 +12,7 @@ before serializing, so a PDF never contains a blank number.
12
12
  ## Footnotes
13
13
 
14
14
  ```tsx
15
- import { Footnote } from 'mosage-core';
15
+ import { Footnote } from 'mosage';
16
16
 
17
17
  <p style={p}>
18
18
  Spend grew 8% quarter over quarter
@@ -48,7 +48,7 @@ inline instead of at the foot of the page.
48
48
  ## Figures and tables
49
49
 
50
50
  ```tsx
51
- import { Figure } from 'mosage-core';
51
+ import { Figure } from 'mosage';
52
52
 
53
53
  <Figure id="topology" caption="Service topology, Q3 2026">
54
54
  <img src={diagram} alt="Service topology" style={{ width: '100%', display: 'block' }} />
@@ -67,7 +67,7 @@ import { Figure } from 'mosage-core';
67
67
  ## Cross-references
68
68
 
69
69
  ```tsx
70
- import { Ref } from 'mosage-core';
70
+ import { Ref } from 'mosage';
71
71
 
72
72
  <p style={p}>The shape in <Ref to="topology" /> is what the table hides.</p>
73
73
  ```
@@ -97,7 +97,7 @@ export const meta: DocMeta = {
97
97
  ## Data
98
98
 
99
99
  ```tsx
100
- import { DataTable } from 'mosage-core';
100
+ import { DataTable } from 'mosage';
101
101
  import services from './data/services.csv';
102
102
 
103
103
  <DataTable
@@ -12,7 +12,7 @@ A document's default export is a list of **entries**. There are two kinds, and t
12
12
  ## Flow sections
13
13
 
14
14
  ```tsx
15
- import { flow, type DocEntry } from 'mosage-core';
15
+ import { flow, type DocEntry } from 'mosage';
16
16
 
17
17
  const Body = flow(
18
18
  <>