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.
- package/README.md +16 -15
- package/bin.js +2 -0
- package/dist/build-C7NW_3Pk.js +14 -0
- package/dist/check-CP4873Wx.js +41 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +228 -0
- package/dist/config-DPm1BBAb.js +2619 -0
- package/dist/config-TlTe7Ona.d.ts +24 -0
- package/dist/context-BqsdSrAQ.js +1084 -0
- package/dist/dev-Biz42qlu.js +17 -0
- package/dist/diagram-xlVDekYk.js +763 -0
- package/dist/export-Bi6nuxjT.js +31 -0
- package/dist/import-D2jNB07F.js +25 -0
- package/dist/index.d.ts +455 -0
- package/dist/index.js +693 -0
- package/dist/{cli.js → init-Bbtj2pxF.js} +34 -68
- package/dist/preview-CLm51aRt.js +19 -0
- package/dist/sdk-DjpX6mCv.js +51 -0
- package/dist/vite/index.d.ts +25 -0
- package/dist/vite/index.js +2 -0
- package/env.d.ts +83 -0
- package/package.json +59 -12
- package/{template/.agents/skills → skills}/create-doc/SKILL.md +1 -1
- package/{template/.agents/skills → skills}/create-theme/SKILL.md +1 -1
- package/{template/.agents/skills → skills}/doc-authoring/SKILL.md +8 -9
- package/{template/.agents/skills → skills}/doc-authoring/references/assets.md +1 -1
- package/{template/.agents/skills → skills}/doc-authoring/references/design-system.md +1 -1
- package/{template/.agents/skills → skills}/doc-authoring/references/long-form.md +4 -4
- package/{template/.agents/skills → skills}/doc-authoring/references/pagination.md +1 -1
- package/src/app/app.tsx +42 -0
- package/src/app/components/data-table.tsx +196 -0
- package/src/app/components/design-panel/design-panel.tsx +318 -0
- package/src/app/components/design-panel/design-provider.tsx +121 -0
- package/src/app/components/design-panel/use-design.ts +85 -0
- package/src/app/components/diagram.tsx +76 -0
- package/src/app/components/doc-assets.tsx +129 -0
- package/src/app/components/doc-search.tsx +248 -0
- package/src/app/components/doc-sidebar.tsx +162 -0
- package/src/app/components/flow-page.tsx +93 -0
- package/src/app/components/footnote.tsx +204 -0
- package/src/app/components/image-placeholder.tsx +50 -0
- package/src/app/components/inspector/inspector.tsx +518 -0
- package/src/app/components/numbering.tsx +224 -0
- package/src/app/components/page-frame.tsx +70 -0
- package/src/app/components/sidebar/folder-item.tsx +212 -0
- package/src/app/components/sidebar/icon-picker.tsx +99 -0
- package/src/app/components/sidebar/sidebar.tsx +252 -0
- package/src/app/components/table-of-contents.tsx +93 -0
- package/src/app/components/theme-toggle.tsx +50 -0
- package/src/app/components/themes/markdown.tsx +249 -0
- package/src/app/components/themes/theme-preview.tsx +74 -0
- package/src/app/components/ui/menu.tsx +143 -0
- package/src/app/index.html +12 -0
- package/src/app/lib/agent-bridge.ts +140 -0
- package/src/app/lib/assets.ts +151 -0
- package/src/app/lib/design-presets.ts +109 -0
- package/src/app/lib/design.ts +88 -0
- package/src/app/lib/diagnostics.ts +282 -0
- package/src/app/lib/doc-preview.tsx +29 -0
- package/src/app/lib/docs.ts +26 -0
- package/src/app/lib/docx/extract.ts +1623 -0
- package/src/app/lib/docx/fonts.test.ts +136 -0
- package/src/app/lib/docx/fonts.ts +166 -0
- package/src/app/lib/docx/media.ts +102 -0
- package/src/app/lib/docx/model.ts +206 -0
- package/src/app/lib/docx/paragraph.test.ts +92 -0
- package/src/app/lib/docx/paragraph.ts +107 -0
- package/src/app/lib/docx/props.ts +187 -0
- package/src/app/lib/docx/styles.ts +306 -0
- package/src/app/lib/docx/units.ts +35 -0
- package/src/app/lib/docx/write.test.ts +507 -0
- package/src/app/lib/docx/write.ts +581 -0
- package/src/app/lib/docx/xml.ts +39 -0
- package/src/app/lib/export-docx.ts +289 -0
- package/src/app/lib/export-dom.ts +318 -0
- package/src/app/lib/export-html.ts +156 -0
- package/src/app/lib/export-image.ts +70 -0
- package/src/app/lib/export-pdf.ts +165 -0
- package/src/app/lib/flow-measure.test.ts +31 -0
- package/src/app/lib/flow-measure.ts +183 -0
- package/src/app/lib/flow.test.ts +110 -0
- package/src/app/lib/flow.ts +136 -0
- package/src/app/lib/folders.ts +192 -0
- package/src/app/lib/footnotes.test.tsx +102 -0
- package/src/app/lib/footnotes.ts +94 -0
- package/src/app/lib/inspector/fiber.ts +99 -0
- package/src/app/lib/labels.test.ts +18 -0
- package/src/app/lib/labels.ts +181 -0
- package/src/app/lib/outline.ts +118 -0
- package/src/app/lib/page-context.tsx +43 -0
- package/src/app/lib/page-range.test.ts +95 -0
- package/src/app/lib/page-range.ts +90 -0
- package/src/app/lib/print-ready.ts +69 -0
- package/src/app/lib/rasterize.ts +173 -0
- package/src/app/lib/scan.ts +26 -0
- package/src/app/lib/sdk.test.ts +32 -0
- package/src/app/lib/sdk.ts +115 -0
- package/src/app/lib/themes.ts +31 -0
- package/src/app/lib/use-doc-module.ts +53 -0
- package/src/app/lib/use-doc-pages.ts +147 -0
- package/src/app/lib/utils.ts +6 -0
- package/src/app/lib/view-mode.test.ts +91 -0
- package/src/app/lib/view-mode.ts +104 -0
- package/src/app/main.tsx +14 -0
- package/src/app/routes/assets.tsx +257 -0
- package/src/app/routes/doc.tsx +877 -0
- package/src/app/routes/home-shell.tsx +203 -0
- package/src/app/routes/home.tsx +269 -0
- package/src/app/routes/themes.tsx +121 -0
- package/src/app/styles.css +97 -0
- package/src/app/virtual.d.ts +30 -0
- package/template/AGENTS.md +1 -1
- package/template/README.md +24 -52
- package/template/docs/getting-started/index.tsx +2 -2
- package/template/mosage.config.ts +1 -1
- package/template/package.json +1 -1
- package/template/tsconfig.json +1 -1
- package/README.zh-TW.md +0 -28
- /package/{template/.agents/skills → skills}/apply-comments/SKILL.md +0 -0
- /package/{template/.agents/skills → skills}/current-doc/SKILL.md +0 -0
- /package/{template/.agents/skills → skills}/doc-authoring/references/tables-and-charts.md +0 -0
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
82
|
-
const
|
|
83
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
140
|
-
await
|
|
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?.
|
|
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 };
|
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.
|
|
4
|
-
"description": "
|
|
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": "
|
|
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
|
-
"
|
|
37
|
+
"docx",
|
|
21
38
|
"pdf",
|
|
22
|
-
"
|
|
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/
|
|
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/
|
|
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": "
|
|
106
|
+
"build": "tsdown",
|
|
60
107
|
"typecheck": "tsc --noEmit",
|
|
61
|
-
"
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
```
|
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
100
|
+
import { DataTable } from 'mosage';
|
|
101
101
|
import services from './data/services.csv';
|
|
102
102
|
|
|
103
103
|
<DataTable
|