@open-press/cli 0.3.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/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/cli.js +365 -0
- package/package.json +57 -0
- package/template/core/.turbo/turbo-test.log +341 -0
- package/template/core/CHANGELOG.md +11 -0
- package/template/core/README.md +36 -0
- package/template/core/engine/chrome-pdf.d.mts +34 -0
- package/template/core/engine/chrome-pdf.mjs +344 -0
- package/template/core/engine/cli.mjs +93 -0
- package/template/core/engine/commands/_shared.mjs +170 -0
- package/template/core/engine/commands/deploy.mjs +31 -0
- package/template/core/engine/commands/dev.mjs +26 -0
- package/template/core/engine/commands/export.mjs +8 -0
- package/template/core/engine/commands/init.mjs +24 -0
- package/template/core/engine/commands/inspect.mjs +35 -0
- package/template/core/engine/commands/migrate-to-react.mjs +27 -0
- package/template/core/engine/commands/pdf.mjs +26 -0
- package/template/core/engine/commands/preview.mjs +26 -0
- package/template/core/engine/commands/render.mjs +17 -0
- package/template/core/engine/commands/replace.mjs +41 -0
- package/template/core/engine/commands/search.mjs +33 -0
- package/template/core/engine/commands/typecheck.mjs +5 -0
- package/template/core/engine/commands/validate.mjs +17 -0
- package/template/core/engine/config.d.mts +40 -0
- package/template/core/engine/config.mjs +160 -0
- package/template/core/engine/deploy-sync.mjs +15 -0
- package/template/core/engine/document-export.mjs +15 -0
- package/template/core/engine/file-utils.mjs +106 -0
- package/template/core/engine/fonts.mjs +62 -0
- package/template/core/engine/init.mjs +90 -0
- package/template/core/engine/inspection.mjs +348 -0
- package/template/core/engine/issue-report.mjs +44 -0
- package/template/core/engine/katex-assets.mjs +45 -0
- package/template/core/engine/page-block.mjs +30 -0
- package/template/core/engine/page-renderer.mjs +217 -0
- package/template/core/engine/pdf-media.mjs +45 -0
- package/template/core/engine/public-assets.mjs +19 -0
- package/template/core/engine/react/chapter-css.mjs +53 -0
- package/template/core/engine/react/comment-endpoint.d.mts +11 -0
- package/template/core/engine/react/comment-endpoint.mjs +128 -0
- package/template/core/engine/react/comment-marker.mjs +306 -0
- package/template/core/engine/react/document-entry.mjs +253 -0
- package/template/core/engine/react/document-export.mjs +392 -0
- package/template/core/engine/react/mdx-compile.mjs +295 -0
- package/template/core/engine/react/measurement-css.mjs +44 -0
- package/template/core/engine/react/migrate-to-react.mjs +355 -0
- package/template/core/engine/react/pagination-constants.mjs +3 -0
- package/template/core/engine/react/pagination.mjs +121 -0
- package/template/core/engine/react/project-asset-endpoint.d.mts +10 -0
- package/template/core/engine/react/project-asset-endpoint.mjs +379 -0
- package/template/core/engine/react/workspace-discovery.mjs +156 -0
- package/template/core/engine/source-text-tools.mjs +280 -0
- package/template/core/engine/source-workspace.mjs +76 -0
- package/template/core/engine/static-server.mjs +493 -0
- package/template/core/engine/validation.mjs +172 -0
- package/template/core/index.html +13 -0
- package/template/core/openpress.config.mjs +12 -0
- package/template/core/package.json +86 -0
- package/template/core/src/main.tsx +16 -0
- package/template/core/src/openpress/App.tsx +127 -0
- package/template/core/src/openpress/composerMentions.ts +188 -0
- package/template/core/src/openpress/core/basePages.tsx +87 -0
- package/template/core/src/openpress/core/index.tsx +20 -0
- package/template/core/src/openpress/core/types.ts +71 -0
- package/template/core/src/openpress/frameScheduler.ts +32 -0
- package/template/core/src/openpress/indexes.ts +329 -0
- package/template/core/src/openpress/inspector.ts +282 -0
- package/template/core/src/openpress/pageRoute.ts +21 -0
- package/template/core/src/openpress/pagination.ts +845 -0
- package/template/core/src/openpress/projectIdentity.ts +15 -0
- package/template/core/src/openpress/projectSources.ts +24 -0
- package/template/core/src/openpress/projectWorkspace.tsx +919 -0
- package/template/core/src/openpress/publicPage.tsx +469 -0
- package/template/core/src/openpress/reactDocumentMetadata.ts +41 -0
- package/template/core/src/openpress/readerPageRegistry.ts +41 -0
- package/template/core/src/openpress/readerRuntime.ts +230 -0
- package/template/core/src/openpress/readerScroll.ts +92 -0
- package/template/core/src/openpress/readerState.ts +15 -0
- package/template/core/src/openpress/renderer.tsx +91 -0
- package/template/core/src/openpress/runtimeMode.ts +22 -0
- package/template/core/src/openpress/types.ts +112 -0
- package/template/core/src/openpress/workbench.tsx +1299 -0
- package/template/core/src/openpress/workbenchPanels.tsx +122 -0
- package/template/core/src/openpress/workbenchTypes.ts +4 -0
- package/template/core/src/styles/openpress/app-shell.css +251 -0
- package/template/core/src/styles/openpress/media-workspace.css +230 -0
- package/template/core/src/styles/openpress/print-route.css +186 -0
- package/template/core/src/styles/openpress/project-workspace.css +1318 -0
- package/template/core/src/styles/openpress/public-viewer.css +983 -0
- package/template/core/src/styles/openpress/reader-runtime.css +792 -0
- package/template/core/src/styles/openpress/responsive.css +384 -0
- package/template/core/src/styles/openpress/workbench-panels.css +558 -0
- package/template/core/src/styles/openpress/workbench.css +720 -0
- package/template/core/src/styles/openpress.css +14 -0
- package/template/core/src/vite-env.d.ts +9 -0
- package/template/core/tsconfig.json +37 -0
- package/template/core/vite.config.ts +512 -0
- package/template/skills/chinese-ai-writing-polish/SKILL.md +195 -0
- package/template/skills/claude-document/SKILL.md +66 -0
- package/template/skills/claude-document/starter/document/chapters/01-document-shape/chapter.tsx +30 -0
- package/template/skills/claude-document/starter/document/chapters/01-document-shape/content/01-document-shape.mdx +51 -0
- package/template/skills/claude-document/starter/document/chapters/02-review-loop/chapter.tsx +30 -0
- package/template/skills/claude-document/starter/document/chapters/02-review-loop/content/01-review-loop.mdx +31 -0
- package/template/skills/claude-document/starter/document/components/ChapterOpenerVisual.tsx +96 -0
- package/template/skills/claude-document/starter/document/components/Page.tsx +27 -0
- package/template/skills/claude-document/starter/document/design.md +142 -0
- package/template/skills/claude-document/starter/document/index.tsx +89 -0
- package/template/skills/claude-document/starter/document/media/README.md +13 -0
- package/template/skills/claude-document/starter/document/openpress.config.mjs +26 -0
- package/template/skills/claude-document/starter/document/theme/README.md +15 -0
- package/template/skills/claude-document/starter/document/theme/base/page-contract.css +525 -0
- package/template/skills/claude-document/starter/document/theme/base/print.css +93 -0
- package/template/skills/claude-document/starter/document/theme/base/typography.css +612 -0
- package/template/skills/claude-document/starter/document/theme/fonts.css +4 -0
- package/template/skills/claude-document/starter/document/theme/page-surfaces/back-cover.css +72 -0
- package/template/skills/claude-document/starter/document/theme/page-surfaces/chapter-opener.css +236 -0
- package/template/skills/claude-document/starter/document/theme/page-surfaces/cover.css +309 -0
- package/template/skills/claude-document/starter/document/theme/page-surfaces/toc.css +213 -0
- package/template/skills/claude-document/starter/document/theme/patterns/_chart-frame.css +53 -0
- package/template/skills/claude-document/starter/document/theme/patterns/figure-grid.css +68 -0
- package/template/skills/claude-document/starter/document/theme/patterns/table-utilities.css +66 -0
- package/template/skills/claude-document/starter/document/theme/shell/reader-controls.css +789 -0
- package/template/skills/claude-document/starter/document/theme/tokens.css +89 -0
- package/template/skills/claude-document/starter/openpress.config.mjs +5 -0
- package/template/skills/editorial-monograph/SKILL.md +73 -0
- package/template/skills/editorial-monograph/starter/document/chapters/01-product-and-use-cases/content/01-product-and-use-cases.mdx +31 -0
- package/template/skills/editorial-monograph/starter/document/chapters/02-workflow/content/01-workflow.mdx +89 -0
- package/template/skills/editorial-monograph/starter/document/chapters/03-agent-skills-contributors/content/01-agent-skills-contributors.mdx +52 -0
- package/template/skills/editorial-monograph/starter/document/chapters/04-validation-deploy/content/01-validation-deploy.mdx +39 -0
- package/template/skills/editorial-monograph/starter/document/components/ChapterOpenerVisual/index.tsx +76 -0
- package/template/skills/editorial-monograph/starter/document/components/Page.tsx +27 -0
- package/template/skills/editorial-monograph/starter/document/components/TokenSwatchGrid/index.tsx +46 -0
- package/template/skills/editorial-monograph/starter/document/components/TokenSwatchGrid/style.css +63 -0
- package/template/skills/editorial-monograph/starter/document/components/TypeSpecimen/index.tsx +38 -0
- package/template/skills/editorial-monograph/starter/document/components/TypeSpecimen/style.css +111 -0
- package/template/skills/editorial-monograph/starter/document/design.md +279 -0
- package/template/skills/editorial-monograph/starter/document/index.tsx +73 -0
- package/template/skills/editorial-monograph/starter/document/media/README.md +13 -0
- package/template/skills/editorial-monograph/starter/document/openpress.config.mjs +26 -0
- package/template/skills/editorial-monograph/starter/document/theme/README.md +11 -0
- package/template/skills/editorial-monograph/starter/document/theme/base/page-contract.css +505 -0
- package/template/skills/editorial-monograph/starter/document/theme/base/print.css +93 -0
- package/template/skills/editorial-monograph/starter/document/theme/base/typography.css +336 -0
- package/template/skills/editorial-monograph/starter/document/theme/fonts.css +3 -0
- package/template/skills/editorial-monograph/starter/document/theme/page-surfaces/back-cover.css +43 -0
- package/template/skills/editorial-monograph/starter/document/theme/page-surfaces/chapter-opener.css +205 -0
- package/template/skills/editorial-monograph/starter/document/theme/page-surfaces/cover.css +147 -0
- package/template/skills/editorial-monograph/starter/document/theme/page-surfaces/toc.css +139 -0
- package/template/skills/editorial-monograph/starter/document/theme/patterns/_chart-frame.css +49 -0
- package/template/skills/editorial-monograph/starter/document/theme/patterns/figure-grid.css +68 -0
- package/template/skills/editorial-monograph/starter/document/theme/patterns/table-utilities.css +66 -0
- package/template/skills/editorial-monograph/starter/document/theme/shell/reader-controls.css +761 -0
- package/template/skills/editorial-monograph/starter/document/theme/tokens.css +80 -0
- package/template/skills/editorial-monograph/starter/openpress.config.mjs +5 -0
- package/template/skills/openpress/SKILL.md +114 -0
- package/template/skills/openpress/references/cli-commands.md +31 -0
- package/template/skills/openpress/references/local-review.md +43 -0
- package/template/skills/openpress-deploy/SKILL.md +69 -0
- package/template/skills/openpress-deploy/references/cloudflare-pages.md +51 -0
- package/template/skills/openpress-design/SKILL.md +51 -0
- package/template/skills/openpress-design/references/pdf-safe-css.md +29 -0
- package/template/skills/openpress-design/references/responsive-fixed-layout.md +48 -0
- package/template/skills/openpress-design/references/theme-and-components.md +77 -0
- package/template/skills/openpress-diagram-drawing/SKILL.md +44 -0
- package/template/skills/openpress-diagram-drawing/references/diagram-patterns.md +93 -0
- package/template/skills/openpress-document-hierarchy/SKILL.md +81 -0
- package/template/skills/openpress-document-hierarchy/agents/openai.yaml +4 -0
- package/template/skills/openpress-document-hierarchy/references/data-structures-outline.md +115 -0
- package/template/skills/openpress-init/SKILL.md +84 -0
- package/template/skills/openpress-style-pack-contributor/SKILL.md +62 -0
- package/template/skills/openpress-style-pack-contributor/references/starter-contract.md +49 -0
- package/template/skills/openpress-update/SKILL.md +88 -0
- package/template/skills/openpress-writing/SKILL.md +68 -0
- package/template/skills/openpress-writing/references/source-and-writing-rules.md +120 -0
- package/template/skills/teaching-notes-writing/SKILL.md +54 -0
- package/template/skills/teaching-notes-writing/references/programming.md +65 -0
- package/template/skills/teaching-notes-writing/references/teaching-patterns.md +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 quan0715
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# @open-press/cli
|
|
2
|
+
|
|
3
|
+
Scaffolder for [open-press](https://github.com/quan0715/open-press) — an AI-first fixed-layout document workspace.
|
|
4
|
+
|
|
5
|
+
## Quick start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @open-press/cli init my-doc --pack editorial-monograph
|
|
9
|
+
cd my-doc
|
|
10
|
+
npm run dev
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Then open the local URL printed by Vite (typically `http://127.0.0.1:5173/?dev=1`).
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
npx @open-press/cli init <target> [flags]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
| Flag | Description |
|
|
22
|
+
| -------------------- | --------------------------------------------------------------------------- |
|
|
23
|
+
| `--pack <name>` | Style pack starter: `editorial-monograph` or `claude-document` |
|
|
24
|
+
| `--title <s>` | Document title (written to `openpress.config.mjs`) |
|
|
25
|
+
| `--subtitle <s>` | Document subtitle |
|
|
26
|
+
| `--organization <s>` | Organization name |
|
|
27
|
+
| `--author <s>` | Author name |
|
|
28
|
+
| `--no-git` | Skip `git init` |
|
|
29
|
+
| `--no-install` | Skip `npm install` |
|
|
30
|
+
| `--force` | Allow scaffolding into a non-empty target |
|
|
31
|
+
| `--help` | Print help |
|
|
32
|
+
|
|
33
|
+
## What it creates
|
|
34
|
+
|
|
35
|
+
A self-contained workspace with:
|
|
36
|
+
|
|
37
|
+
- `engine/`, `src/`, `vite.config.ts` — the open-press framework (snapshot of `@open-press/core`)
|
|
38
|
+
- `document/` — your content (populated from the chosen style pack)
|
|
39
|
+
- `.claude/skills/` and `.agents/skills/` — agent skill files for Claude Code, Codex, Cursor, Copilot, etc.
|
|
40
|
+
- `openpress.config.mjs` — workspace metadata (title, subtitle, organization, author)
|
|
41
|
+
- `AGENTS.md` — agent contract
|
|
42
|
+
|
|
43
|
+
## After init
|
|
44
|
+
|
|
45
|
+
Workspace commands (run via `npm run` or `node engine/cli.mjs`):
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
npm run dev # start workbench
|
|
49
|
+
npm run build # render production output (dist-react/)
|
|
50
|
+
npm run preview # preview production build
|
|
51
|
+
npm run openpress:validate # structural checks
|
|
52
|
+
npm run openpress:pdf # render PDF
|
|
53
|
+
npm run openpress:deploy:dry-run
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT — see [LICENSE](https://github.com/quan0715/open-press/blob/main/LICENSE).
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli.ts
|
|
4
|
+
import process2 from "process";
|
|
5
|
+
|
|
6
|
+
// src/init.ts
|
|
7
|
+
import { spawn } from "child_process";
|
|
8
|
+
import { existsSync } from "fs";
|
|
9
|
+
import { cp, mkdir as mkdir2, readdir, rm as rm2 } from "fs/promises";
|
|
10
|
+
import path2 from "path";
|
|
11
|
+
import process from "process";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
|
|
14
|
+
// src/degit.ts
|
|
15
|
+
import { createWriteStream } from "fs";
|
|
16
|
+
import { mkdir, rm, stat } from "fs/promises";
|
|
17
|
+
import { tmpdir } from "os";
|
|
18
|
+
import path from "path";
|
|
19
|
+
import { Readable } from "stream";
|
|
20
|
+
import { pipeline } from "stream/promises";
|
|
21
|
+
import { x as extract } from "tar";
|
|
22
|
+
async function pathIsEmpty(target) {
|
|
23
|
+
try {
|
|
24
|
+
const s = await stat(target);
|
|
25
|
+
if (!s.isDirectory()) return false;
|
|
26
|
+
const { readdir: readdir2 } = await import("fs/promises");
|
|
27
|
+
const entries = await readdir2(target);
|
|
28
|
+
return entries.length === 0;
|
|
29
|
+
} catch {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/metadata.ts
|
|
35
|
+
import { readFile, writeFile } from "fs/promises";
|
|
36
|
+
async function patchOpenpressConfig(configPath, patch) {
|
|
37
|
+
let source = await readFile(configPath, "utf8");
|
|
38
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
39
|
+
if (value === void 0 || value === null || value === "") continue;
|
|
40
|
+
const escaped = escapeStringForJs(value);
|
|
41
|
+
const re = new RegExp(`(${key}\\s*:\\s*)("[^"]*"|'[^']*'|\`[^\`]*\`)`, "m");
|
|
42
|
+
if (re.test(source)) {
|
|
43
|
+
source = source.replace(re, `$1"${escaped}"`);
|
|
44
|
+
} else {
|
|
45
|
+
source = source.replace(/(export\s+default\s*\{)/, `$1
|
|
46
|
+
${key}: "${escaped}",`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
await writeFile(configPath, source);
|
|
50
|
+
}
|
|
51
|
+
function escapeStringForJs(value) {
|
|
52
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
53
|
+
}
|
|
54
|
+
async function patchPackageJsonName(packagePath, newName) {
|
|
55
|
+
const text = await readFile(packagePath, "utf8");
|
|
56
|
+
const pkg = JSON.parse(text);
|
|
57
|
+
const prevName = typeof pkg.name === "string" ? pkg.name : "";
|
|
58
|
+
pkg.name = newName;
|
|
59
|
+
pkg.version = "0.0.0";
|
|
60
|
+
pkg.private = true;
|
|
61
|
+
pkg.description = `open-press workspace: ${newName}`;
|
|
62
|
+
for (const field of [
|
|
63
|
+
"publishConfig",
|
|
64
|
+
"files",
|
|
65
|
+
"bin",
|
|
66
|
+
"main",
|
|
67
|
+
"types",
|
|
68
|
+
"exports",
|
|
69
|
+
"homepage",
|
|
70
|
+
"repository",
|
|
71
|
+
"bugs",
|
|
72
|
+
"keywords",
|
|
73
|
+
"license",
|
|
74
|
+
"author"
|
|
75
|
+
]) {
|
|
76
|
+
delete pkg[field];
|
|
77
|
+
}
|
|
78
|
+
await writeFile(packagePath, JSON.stringify(pkg, null, 2) + "\n");
|
|
79
|
+
return prevName;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/init.ts
|
|
83
|
+
var KNOWN_PACKS = ["editorial-monograph", "claude-document"];
|
|
84
|
+
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
85
|
+
var TEMPLATE_ROOT = path2.resolve(__dirname, "..", "template");
|
|
86
|
+
var TEMPLATE_CORE = path2.join(TEMPLATE_ROOT, "core");
|
|
87
|
+
var TEMPLATE_SKILLS = path2.join(TEMPLATE_ROOT, "skills");
|
|
88
|
+
async function init(options) {
|
|
89
|
+
validatePack(options.pack);
|
|
90
|
+
ensureTemplateBundled();
|
|
91
|
+
const target = path2.resolve(process.cwd(), options.target);
|
|
92
|
+
await ensureTarget(target, options.force);
|
|
93
|
+
log(`Creating open-press workspace at ${target}`);
|
|
94
|
+
log("Copying framework (engine + runtime + config)\u2026");
|
|
95
|
+
await cp(TEMPLATE_CORE, target, { recursive: true });
|
|
96
|
+
const docDest = path2.join(target, "document");
|
|
97
|
+
if (options.pack) {
|
|
98
|
+
log(`Applying style pack: ${options.pack}`);
|
|
99
|
+
await rm2(docDest, { recursive: true, force: true });
|
|
100
|
+
await mkdir2(docDest, { recursive: true });
|
|
101
|
+
const packStarter = path2.join(TEMPLATE_SKILLS, options.pack, "starter", "document");
|
|
102
|
+
if (!existsSync(packStarter)) {
|
|
103
|
+
throw new Error(`Style pack starter not found: ${packStarter}`);
|
|
104
|
+
}
|
|
105
|
+
await cp(packStarter, docDest, { recursive: true });
|
|
106
|
+
} else {
|
|
107
|
+
await mkdir2(docDest, { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
log("Installing SKILL files\u2026");
|
|
110
|
+
await installSkills(target);
|
|
111
|
+
const pkgPath = path2.join(target, "package.json");
|
|
112
|
+
if (existsSync(pkgPath)) {
|
|
113
|
+
await patchPackageJsonName(pkgPath, path2.basename(target));
|
|
114
|
+
}
|
|
115
|
+
const configPath = path2.join(target, "openpress.config.mjs");
|
|
116
|
+
if (existsSync(configPath) && hasMetadata(options)) {
|
|
117
|
+
log("Writing metadata into openpress.config.mjs");
|
|
118
|
+
await patchOpenpressConfig(configPath, {
|
|
119
|
+
title: options.title,
|
|
120
|
+
subtitle: options.subtitle,
|
|
121
|
+
organization: options.organization,
|
|
122
|
+
author: options.author
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (options.install) {
|
|
126
|
+
log("Installing dependencies (npm install)\u2026");
|
|
127
|
+
await runInTarget(target, "npm", ["install"]);
|
|
128
|
+
} else {
|
|
129
|
+
log("Skipping npm install (--no-install)");
|
|
130
|
+
}
|
|
131
|
+
if (options.git) {
|
|
132
|
+
log("Initializing git repository\u2026");
|
|
133
|
+
try {
|
|
134
|
+
await runInTarget(target, "git", ["init"]);
|
|
135
|
+
await runInTarget(target, "git", ["add", "-A"]);
|
|
136
|
+
await runInTarget(target, "git", ["commit", "-m", "Initial commit from open-press"], { silent: true });
|
|
137
|
+
} catch {
|
|
138
|
+
log("(git not available; skipping repo init)");
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
log("Skipping git init (--no-git)");
|
|
142
|
+
}
|
|
143
|
+
printNextSteps(target, options);
|
|
144
|
+
}
|
|
145
|
+
async function installSkills(target) {
|
|
146
|
+
const skillDirs = await readdir(TEMPLATE_SKILLS, { withFileTypes: true });
|
|
147
|
+
const claudeRoot = path2.join(target, ".claude", "skills");
|
|
148
|
+
const agentsRoot = path2.join(target, ".agents", "skills");
|
|
149
|
+
await mkdir2(claudeRoot, { recursive: true });
|
|
150
|
+
await mkdir2(agentsRoot, { recursive: true });
|
|
151
|
+
for (const dir of skillDirs) {
|
|
152
|
+
if (!dir.isDirectory()) continue;
|
|
153
|
+
const source = path2.join(TEMPLATE_SKILLS, dir.name);
|
|
154
|
+
const claudeTarget = path2.join(claudeRoot, dir.name);
|
|
155
|
+
const agentsTarget = path2.join(agentsRoot, dir.name);
|
|
156
|
+
await copySkillFiles(source, claudeTarget);
|
|
157
|
+
await copySkillFiles(source, agentsTarget);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async function copySkillFiles(source, dest) {
|
|
161
|
+
await mkdir2(dest, { recursive: true });
|
|
162
|
+
const entries = await readdir(source, { withFileTypes: true });
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (entry.name === "starter" || entry.name === "agents") continue;
|
|
165
|
+
const from = path2.join(source, entry.name);
|
|
166
|
+
const to = path2.join(dest, entry.name);
|
|
167
|
+
await cp(from, to, { recursive: true });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function ensureTemplateBundled() {
|
|
171
|
+
if (!existsSync(TEMPLATE_CORE) || !existsSync(TEMPLATE_SKILLS)) {
|
|
172
|
+
throw new Error(
|
|
173
|
+
`Template not bundled at ${TEMPLATE_ROOT}. If running from source, run \`pnpm sync:template\` in packages/cli first.`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
function validatePack(pack) {
|
|
178
|
+
if (pack === void 0) return;
|
|
179
|
+
if (!KNOWN_PACKS.includes(pack)) {
|
|
180
|
+
throw new Error(`Unknown style pack: ${pack}. Known packs: ${KNOWN_PACKS.join(", ")}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function ensureTarget(target, force) {
|
|
184
|
+
if (existsSync(target)) {
|
|
185
|
+
if (force) return;
|
|
186
|
+
const empty = await pathIsEmpty(target);
|
|
187
|
+
if (!empty) {
|
|
188
|
+
throw new Error(`Target ${target} is not empty. Pass --force to scaffold into it anyway.`);
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
await mkdir2(target, { recursive: true });
|
|
193
|
+
}
|
|
194
|
+
function hasMetadata(options) {
|
|
195
|
+
return Boolean(options.title || options.subtitle || options.organization || options.author);
|
|
196
|
+
}
|
|
197
|
+
async function runInTarget(cwd, command, args, opts = {}) {
|
|
198
|
+
return new Promise((resolve, reject) => {
|
|
199
|
+
const child = spawn(command, args, {
|
|
200
|
+
cwd,
|
|
201
|
+
stdio: opts.silent ? ["ignore", "ignore", "ignore"] : "inherit",
|
|
202
|
+
shell: process.platform === "win32"
|
|
203
|
+
});
|
|
204
|
+
child.once("error", reject);
|
|
205
|
+
child.once("close", (code) => {
|
|
206
|
+
if (code === 0) resolve();
|
|
207
|
+
else reject(new Error(`${command} ${args.join(" ")} exited with code ${code}`));
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
function log(message) {
|
|
212
|
+
process.stdout.write(`\u25B8 ${message}
|
|
213
|
+
`);
|
|
214
|
+
}
|
|
215
|
+
function printNextSteps(target, options) {
|
|
216
|
+
const rel = path2.relative(process.cwd(), target) || ".";
|
|
217
|
+
const lines = [
|
|
218
|
+
"",
|
|
219
|
+
"\u2713 Done! Your open-press workspace is ready.",
|
|
220
|
+
"",
|
|
221
|
+
"Next steps:",
|
|
222
|
+
` cd ${rel}`
|
|
223
|
+
];
|
|
224
|
+
if (!options.install) {
|
|
225
|
+
lines.push(" npm install");
|
|
226
|
+
}
|
|
227
|
+
lines.push(
|
|
228
|
+
"",
|
|
229
|
+
" # start the workbench:",
|
|
230
|
+
" npm run dev",
|
|
231
|
+
"",
|
|
232
|
+
"Then open the local URL printed by vite (typically http://127.0.0.1:5173/?dev=1).",
|
|
233
|
+
"",
|
|
234
|
+
"AI agent skills are installed under .claude/skills/ and .agents/skills/.",
|
|
235
|
+
"Edit content under document/chapters/, or ask your AI agent to help.",
|
|
236
|
+
""
|
|
237
|
+
);
|
|
238
|
+
process.stdout.write(lines.join("\n"));
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// src/cli.ts
|
|
242
|
+
var HELP = `open-press \u2014 AI-first fixed-layout document workspaces.
|
|
243
|
+
|
|
244
|
+
Usage:
|
|
245
|
+
npx @open-press/cli init <target> [flags]
|
|
246
|
+
|
|
247
|
+
Flags:
|
|
248
|
+
--pack <name> Style pack starter: editorial-monograph | claude-document
|
|
249
|
+
--title <s> Document title (written to openpress.config.mjs)
|
|
250
|
+
--subtitle <s> Document subtitle
|
|
251
|
+
--organization <s> Organization name
|
|
252
|
+
--author <s> Author name (defaults to git user.name)
|
|
253
|
+
--no-git Skip git init
|
|
254
|
+
--no-install Skip npm install
|
|
255
|
+
--force Allow non-empty target
|
|
256
|
+
--help Show this help
|
|
257
|
+
|
|
258
|
+
Examples:
|
|
259
|
+
npx @open-press/cli init my-doc --pack editorial-monograph
|
|
260
|
+
npx @open-press/cli init my-doc --pack claude-document --title "Q2 Brief" --author Quan
|
|
261
|
+
`;
|
|
262
|
+
async function main(argv) {
|
|
263
|
+
if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
|
|
264
|
+
process2.stdout.write(HELP);
|
|
265
|
+
return 0;
|
|
266
|
+
}
|
|
267
|
+
const [subcommand, ...rest] = argv;
|
|
268
|
+
if (subcommand !== "init") {
|
|
269
|
+
process2.stderr.write(`Unknown command: ${subcommand}
|
|
270
|
+
|
|
271
|
+
`);
|
|
272
|
+
process2.stderr.write(HELP);
|
|
273
|
+
return 1;
|
|
274
|
+
}
|
|
275
|
+
const options = parseInitArgs(rest);
|
|
276
|
+
if (!options) {
|
|
277
|
+
process2.stderr.write(HELP);
|
|
278
|
+
return 1;
|
|
279
|
+
}
|
|
280
|
+
try {
|
|
281
|
+
await init(options);
|
|
282
|
+
return 0;
|
|
283
|
+
} catch (err) {
|
|
284
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
285
|
+
process2.stderr.write(`open-press init failed: ${msg}
|
|
286
|
+
`);
|
|
287
|
+
return 1;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function parseInitArgs(args) {
|
|
291
|
+
if (args.length === 0) {
|
|
292
|
+
process2.stderr.write("open-press init: target path is required.\n\n");
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
const options = {
|
|
296
|
+
target: "",
|
|
297
|
+
pack: void 0,
|
|
298
|
+
title: void 0,
|
|
299
|
+
subtitle: void 0,
|
|
300
|
+
organization: void 0,
|
|
301
|
+
author: void 0,
|
|
302
|
+
git: true,
|
|
303
|
+
install: true,
|
|
304
|
+
force: false
|
|
305
|
+
};
|
|
306
|
+
for (let i = 0; i < args.length; i++) {
|
|
307
|
+
const arg = args[i];
|
|
308
|
+
switch (arg) {
|
|
309
|
+
case "--pack":
|
|
310
|
+
options.pack = args[++i];
|
|
311
|
+
break;
|
|
312
|
+
case "--title":
|
|
313
|
+
options.title = args[++i];
|
|
314
|
+
break;
|
|
315
|
+
case "--subtitle":
|
|
316
|
+
options.subtitle = args[++i];
|
|
317
|
+
break;
|
|
318
|
+
case "--organization":
|
|
319
|
+
options.organization = args[++i];
|
|
320
|
+
break;
|
|
321
|
+
case "--author":
|
|
322
|
+
options.author = args[++i];
|
|
323
|
+
break;
|
|
324
|
+
case "--no-git":
|
|
325
|
+
options.git = false;
|
|
326
|
+
break;
|
|
327
|
+
case "--no-install":
|
|
328
|
+
options.install = false;
|
|
329
|
+
break;
|
|
330
|
+
case "--git":
|
|
331
|
+
options.git = true;
|
|
332
|
+
break;
|
|
333
|
+
case "--install":
|
|
334
|
+
options.install = true;
|
|
335
|
+
break;
|
|
336
|
+
case "--force":
|
|
337
|
+
options.force = true;
|
|
338
|
+
break;
|
|
339
|
+
default:
|
|
340
|
+
if (arg.startsWith("--")) {
|
|
341
|
+
process2.stderr.write(`Unknown flag: ${arg}
|
|
342
|
+
|
|
343
|
+
`);
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
if (options.target) {
|
|
347
|
+
process2.stderr.write(`Unexpected positional: ${arg}
|
|
348
|
+
|
|
349
|
+
`);
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
options.target = arg;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (!options.target) {
|
|
356
|
+
process2.stderr.write("open-press init: target path is required.\n\n");
|
|
357
|
+
return null;
|
|
358
|
+
}
|
|
359
|
+
return options;
|
|
360
|
+
}
|
|
361
|
+
main(process2.argv.slice(2)).then((code) => process2.exit(code)).catch((err) => {
|
|
362
|
+
process2.stderr.write(`${err instanceof Error ? err.stack ?? err.message : String(err)}
|
|
363
|
+
`);
|
|
364
|
+
process2.exit(1);
|
|
365
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@open-press/cli",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Scaffolder for open-press — AI-first fixed-layout document workspaces.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "quan0715",
|
|
8
|
+
"homepage": "https://github.com/quan0715/open-press#readme",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/quan0715/open-press.git",
|
|
12
|
+
"directory": "packages/cli"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/quan0715/open-press/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"document",
|
|
19
|
+
"mdx",
|
|
20
|
+
"react",
|
|
21
|
+
"pdf",
|
|
22
|
+
"a4",
|
|
23
|
+
"fixed-layout",
|
|
24
|
+
"ai-first",
|
|
25
|
+
"scaffold",
|
|
26
|
+
"init",
|
|
27
|
+
"cli"
|
|
28
|
+
],
|
|
29
|
+
"bin": {
|
|
30
|
+
"open-press": "dist/cli.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"template",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=20"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"tar": "^7.5.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^25.8.0",
|
|
48
|
+
"tsup": "^8.5.0",
|
|
49
|
+
"typescript": "^6.0.3"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"sync:template": "node scripts/sync-template.mjs",
|
|
53
|
+
"build": "pnpm sync:template && tsup",
|
|
54
|
+
"dev": "tsup --watch",
|
|
55
|
+
"typecheck": "tsc --noEmit"
|
|
56
|
+
}
|
|
57
|
+
}
|