@open-press/cli 1.0.0 → 1.1.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 +11 -12
- package/dist/cli.js +298 -79
- package/package.json +9 -7
- package/template/core/AGENTS.md +0 -130
- package/template/core/CHANGELOG.md +0 -218
- package/template/core/README.md +0 -43
- package/template/core/engine/cli.mjs +0 -96
- package/template/core/engine/commands/_shared.mjs +0 -199
- package/template/core/engine/commands/deploy.mjs +0 -31
- package/template/core/engine/commands/dev.mjs +0 -49
- package/template/core/engine/commands/doctor.mjs +0 -229
- package/template/core/engine/commands/export.mjs +0 -8
- package/template/core/engine/commands/image.mjs +0 -29
- package/template/core/engine/commands/inspect.mjs +0 -35
- package/template/core/engine/commands/pdf.mjs +0 -26
- package/template/core/engine/commands/preview.mjs +0 -26
- package/template/core/engine/commands/render.mjs +0 -17
- package/template/core/engine/commands/replace.mjs +0 -41
- package/template/core/engine/commands/search.mjs +0 -33
- package/template/core/engine/commands/skills-sync.mjs +0 -71
- package/template/core/engine/commands/typecheck.mjs +0 -67
- package/template/core/engine/commands/upgrade.mjs +0 -159
- package/template/core/engine/commands/validate.mjs +0 -17
- package/template/core/engine/document-export.mjs +0 -15
- package/template/core/engine/output/chrome-pdf.d.mts +0 -34
- package/template/core/engine/output/chrome-pdf.mjs +0 -450
- package/template/core/engine/output/deploy-sync.mjs +0 -15
- package/template/core/engine/output/fonts.mjs +0 -62
- package/template/core/engine/output/katex-assets.mjs +0 -45
- package/template/core/engine/output/page-block.mjs +0 -30
- package/template/core/engine/output/pdf-media.mjs +0 -45
- package/template/core/engine/output/public-assets.mjs +0 -19
- package/template/core/engine/output/static-server.mjs +0 -571
- package/template/core/engine/react/caption-numbering.mjs +0 -73
- package/template/core/engine/react/comment-endpoint.d.mts +0 -11
- package/template/core/engine/react/comment-endpoint.mjs +0 -102
- package/template/core/engine/react/comment-marker.mjs +0 -374
- package/template/core/engine/react/document-entry.mjs +0 -331
- package/template/core/engine/react/document-export.mjs +0 -512
- package/template/core/engine/react/http-json.mjs +0 -24
- package/template/core/engine/react/mdx-compile.mjs +0 -629
- package/template/core/engine/react/measurement-css.mjs +0 -157
- package/template/core/engine/react/object-entities.mjs +0 -204
- package/template/core/engine/react/pagination/allocator.mjs +0 -167
- package/template/core/engine/react/pagination/regions.mjs +0 -81
- package/template/core/engine/react/pagination-constants.mjs +0 -3
- package/template/core/engine/react/pagination.mjs +0 -9
- package/template/core/engine/react/pipeline/allocate.mjs +0 -217
- package/template/core/engine/react/pipeline/final-render.mjs +0 -94
- package/template/core/engine/react/pipeline/frame-measurement.mjs +0 -306
- package/template/core/engine/react/pipeline/press-tree.mjs +0 -135
- package/template/core/engine/react/press-tree-inspection.mjs +0 -172
- package/template/core/engine/react/project-asset-endpoint.d.mts +0 -10
- package/template/core/engine/react/project-asset-endpoint.mjs +0 -361
- package/template/core/engine/react/section-css.mjs +0 -56
- package/template/core/engine/react/source-edit-endpoint.d.mts +0 -10
- package/template/core/engine/react/source-edit-endpoint.mjs +0 -75
- package/template/core/engine/react/sources/heading-numbering.mjs +0 -132
- package/template/core/engine/react/sources/mdx-resolver.mjs +0 -439
- package/template/core/engine/react/style-discovery.mjs +0 -160
- package/template/core/engine/runtime/config.d.mts +0 -48
- package/template/core/engine/runtime/config.mjs +0 -172
- package/template/core/engine/runtime/file-utils.mjs +0 -114
- package/template/core/engine/runtime/file-walk.mjs +0 -22
- package/template/core/engine/runtime/inspection.mjs +0 -328
- package/template/core/engine/runtime/issue-report.mjs +0 -44
- package/template/core/engine/runtime/page-geometry.mjs +0 -131
- package/template/core/engine/runtime/path-utils.mjs +0 -20
- package/template/core/engine/runtime/source-text-tools.d.mts +0 -102
- package/template/core/engine/runtime/source-text-tools.mjs +0 -832
- package/template/core/engine/runtime/source-workspace.mjs +0 -168
- package/template/core/engine/runtime/validation.mjs +0 -183
- package/template/core/index.html +0 -13
- package/template/core/openpress.config.mjs +0 -8
- package/template/core/package.json +0 -89
- package/template/core/src/main.tsx +0 -16
- package/template/core/src/openpress/app/OpenPressApp.tsx +0 -296
- package/template/core/src/openpress/app/OpenPressRuntime.tsx +0 -102
- package/template/core/src/openpress/app/WorkspaceGalleryPage.tsx +0 -219
- package/template/core/src/openpress/app/index.ts +0 -2
- package/template/core/src/openpress/core/Frame.tsx +0 -91
- package/template/core/src/openpress/core/FrameContext.tsx +0 -26
- package/template/core/src/openpress/core/MdxArea.tsx +0 -34
- package/template/core/src/openpress/core/Press.tsx +0 -55
- package/template/core/src/openpress/core/Workspace.tsx +0 -36
- package/template/core/src/openpress/core/cn.ts +0 -4
- package/template/core/src/openpress/core/index.tsx +0 -47
- package/template/core/src/openpress/core/primitives.tsx +0 -91
- package/template/core/src/openpress/core/types.ts +0 -236
- package/template/core/src/openpress/core/useSource.ts +0 -28
- package/template/core/src/openpress/document-model/anchorMapModel.ts +0 -27
- package/template/core/src/openpress/document-model/documentIndexes.ts +0 -329
- package/template/core/src/openpress/document-model/documentTypes.ts +0 -147
- package/template/core/src/openpress/document-model/index.ts +0 -7
- package/template/core/src/openpress/document-model/objectEntityModel.ts +0 -55
- package/template/core/src/openpress/document-model/projectIdentityModel.ts +0 -15
- package/template/core/src/openpress/document-model/reactDocumentMetadataModel.ts +0 -27
- package/template/core/src/openpress/document-model/workspaceManifestModel.ts +0 -57
- package/template/core/src/openpress/manuscript/index.tsx +0 -238
- package/template/core/src/openpress/mdx/index.ts +0 -96
- package/template/core/src/openpress/numbering/index.ts +0 -294
- package/template/core/src/openpress/reader/PageThumbnailsPanel.tsx +0 -168
- package/template/core/src/openpress/reader/PublicReaderPage.tsx +0 -267
- package/template/core/src/openpress/reader/ReaderNavigationPanel.tsx +0 -123
- package/template/core/src/openpress/reader/index.ts +0 -11
- package/template/core/src/openpress/reader/pageViewportScaleModel.ts +0 -73
- package/template/core/src/openpress/reader/readerPageRegistry.ts +0 -41
- package/template/core/src/openpress/reader/readerPageRoute.ts +0 -21
- package/template/core/src/openpress/reader/readerScroll.ts +0 -92
- package/template/core/src/openpress/reader/readerStateModel.ts +0 -15
- package/template/core/src/openpress/reader/readerTypes.ts +0 -4
- package/template/core/src/openpress/reader/usePageViewportScale.ts +0 -119
- package/template/core/src/openpress/reader/usePanelState.ts +0 -56
- package/template/core/src/openpress/reader/useReaderHashSync.ts +0 -61
- package/template/core/src/openpress/reader/useReaderKeyboardNav.ts +0 -48
- package/template/core/src/openpress/reader/useReaderRuntime.ts +0 -146
- package/template/core/src/openpress/reader/useReaderScrollAnchor.ts +0 -64
- package/template/core/src/openpress/shared/Panel.tsx +0 -77
- package/template/core/src/openpress/shared/frameScheduler.ts +0 -32
- package/template/core/src/openpress/shared/index.ts +0 -4
- package/template/core/src/openpress/shared/numberUtils.ts +0 -3
- package/template/core/src/openpress/shared/runtimeMode.ts +0 -11
- package/template/core/src/openpress/workbench/Workbench.tsx +0 -506
- package/template/core/src/openpress/workbench/actions/DeploymentControl.tsx +0 -157
- package/template/core/src/openpress/workbench/actions/ExportImageControl.tsx +0 -96
- package/template/core/src/openpress/workbench/actions/PageZoomControl.tsx +0 -182
- package/template/core/src/openpress/workbench/actions/SearchControl.tsx +0 -345
- package/template/core/src/openpress/workbench/actions/deploymentStatusModel.ts +0 -112
- package/template/core/src/openpress/workbench/actions/index.ts +0 -6
- package/template/core/src/openpress/workbench/actions/useDeploymentWorkbench.ts +0 -136
- package/template/core/src/openpress/workbench/dialog/WorkbenchDialog.tsx +0 -72
- package/template/core/src/openpress/workbench/dialog/index.ts +0 -1
- package/template/core/src/openpress/workbench/document/components/DocumentPanel.tsx +0 -127
- package/template/core/src/openpress/workbench/document/components/InlineSourceEditorLayer.tsx +0 -207
- package/template/core/src/openpress/workbench/document/components/ReaderStage.tsx +0 -9
- package/template/core/src/openpress/workbench/document/hooks/useDocumentWorkbenchModel.ts +0 -34
- package/template/core/src/openpress/workbench/document/hooks/useInlineDocumentEditor.ts +0 -525
- package/template/core/src/openpress/workbench/document/index.ts +0 -10
- package/template/core/src/openpress/workbench/index.ts +0 -2
- package/template/core/src/openpress/workbench/inspector/InlineInspectorLayer.tsx +0 -459
- package/template/core/src/openpress/workbench/inspector/index.ts +0 -5
- package/template/core/src/openpress/workbench/inspector/inlineCommentModel.ts +0 -125
- package/template/core/src/openpress/workbench/inspector/inspectorGeometryModel.ts +0 -160
- package/template/core/src/openpress/workbench/inspector/inspectorModel.ts +0 -408
- package/template/core/src/openpress/workbench/inspector/useInspectorComments.ts +0 -254
- package/template/core/src/openpress/workbench/mentions/MentionSuggestionList.tsx +0 -41
- package/template/core/src/openpress/workbench/mentions/index.ts +0 -2
- package/template/core/src/openpress/workbench/mentions/useComposerMentions.ts +0 -185
- package/template/core/src/openpress/workbench/panels/Panel.tsx +0 -1
- package/template/core/src/openpress/workbench/panels/PendingCommentsPanel.tsx +0 -80
- package/template/core/src/openpress/workbench/panels/WorkbenchControlPanel.tsx +0 -29
- package/template/core/src/openpress/workbench/panels/index.ts +0 -3
- package/template/core/src/openpress/workbench/project/ProjectEntryPanel.tsx +0 -525
- package/template/core/src/openpress/workbench/project/ProjectPreviewDialog.tsx +0 -35
- package/template/core/src/openpress/workbench/project/index.ts +0 -2
- package/template/core/src/openpress/workbench/project/projectPreviewTypes.ts +0 -11
- package/template/core/src/openpress/workbench/project/projectSourceModel.ts +0 -24
- package/template/core/src/openpress/workbench/shell/WorkbenchShell.tsx +0 -167
- package/template/core/src/openpress/workbench/shell/index.ts +0 -1
- package/template/core/src/openpress/workbench/workbenchFormatters.ts +0 -120
- package/template/core/src/openpress/workbench/workbenchTypes.ts +0 -35
- package/template/core/src/styles/openpress/app-shell.css +0 -251
- package/template/core/src/styles/openpress/media-workspace.css +0 -230
- package/template/core/src/styles/openpress/print-route.css +0 -184
- package/template/core/src/styles/openpress/project-preview-panel.css +0 -924
- package/template/core/src/styles/openpress/public-viewer.css +0 -688
- package/template/core/src/styles/openpress/reader-runtime.css +0 -989
- package/template/core/src/styles/openpress/responsive.css +0 -245
- package/template/core/src/styles/openpress/workbench-panels.css +0 -707
- package/template/core/src/styles/openpress/workbench.css +0 -1255
- package/template/core/src/styles/openpress/workspace-gallery.css +0 -300
- package/template/core/src/styles/openpress.css +0 -15
- package/template/core/src/vite-env.d.ts +0 -9
- package/template/core/tsconfig.json +0 -40
- package/template/core/vite.config.ts +0 -584
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @open-press/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Workspace CLI for [open-press](https://github.com/quan0715/open-press) — an AI-first fixed-layout document workspace.
|
|
4
4
|
|
|
5
5
|
## Prerequisite
|
|
6
6
|
|
|
@@ -16,7 +16,7 @@ npm run dev
|
|
|
16
16
|
|
|
17
17
|
Then open the local URL printed by Vite (typically `http://127.0.0.1:5173/?dev=1`).
|
|
18
18
|
|
|
19
|
-
The CLI creates
|
|
19
|
+
The CLI creates a package-based OpenPress workspace. Runtime files stay inside `@open-press/core`; your project keeps only source files, theme files, media, and npm scripts.
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
@@ -27,16 +27,15 @@ npx @open-press/cli init <target> [flags]
|
|
|
27
27
|
| Flag | Description |
|
|
28
28
|
| -------------------- | --------------------------------------------------------------------------- |
|
|
29
29
|
| `--title <s>` | Document title (written to workspace config) |
|
|
30
|
-
| `--subtitle <s>` | Document subtitle |
|
|
31
|
-
| `--organization <s>` | Organization name |
|
|
32
|
-
| `--author <s>` | Author name |
|
|
33
30
|
| `--no-git` | Skip `git init` + initial commit (use when scaffolding inside an existing repo) |
|
|
34
31
|
| `--no-install` | Skip `npm install` (offline, or you'll run pnpm/bun yourself) |
|
|
32
|
+
| `--skills` | Install OpenPress agent skills after scaffolding |
|
|
33
|
+
| `--no-skills` | Skip agent skill installation |
|
|
35
34
|
| `--help` | Print help |
|
|
36
35
|
|
|
37
36
|
> The target must be empty. A `.git/` directory or other harmless dotfiles (`.gitignore`, `.gitkeep`, `.DS_Store`) are ignored — common when scaffolding into a fresh repo.
|
|
38
37
|
|
|
39
|
-
To use an opinionated starter, install a skill and let the agent
|
|
38
|
+
To use an opinionated starter, install a skill and let the agent copy that starter's `press/` files into the workspace:
|
|
40
39
|
|
|
41
40
|
```bash
|
|
42
41
|
npx -y skills@latest add quan0715/openpress-social-card-skill
|
|
@@ -46,16 +45,16 @@ npx -y skills@latest add quan0715/openpress-social-card-skill
|
|
|
46
45
|
|
|
47
46
|
A self-contained workspace with:
|
|
48
47
|
|
|
49
|
-
- `
|
|
50
|
-
-
|
|
51
|
-
- `
|
|
52
|
-
- `
|
|
48
|
+
- `package.json` with `@open-press/core`, `@open-press/cli`, and `open-press ...` scripts
|
|
49
|
+
- `press/index.tsx` — the workspace document entry
|
|
50
|
+
- `press/theme/`, `press/media/`, `press/components/` — user-owned authoring files
|
|
51
|
+
- `press/design.md` — working design notes for agents and maintainers
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
It does **not** create `engine/`, `src/openpress/`, `index.html`, or `vite.config.ts` in your project. Those are package-owned runtime internals.
|
|
55
54
|
|
|
56
55
|
## After init
|
|
57
56
|
|
|
58
|
-
Workspace commands (run via `npm run` or `
|
|
57
|
+
Workspace commands (run via `npm run` or `open-press`):
|
|
59
58
|
|
|
60
59
|
```
|
|
61
60
|
npm run dev # start workbench
|
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
+
import { spawn as spawn2 } from "child_process";
|
|
5
|
+
import { createRequire } from "module";
|
|
6
|
+
import path2 from "path";
|
|
4
7
|
import process2 from "process";
|
|
5
8
|
|
|
6
9
|
// src/init.ts
|
|
7
10
|
import { spawn } from "child_process";
|
|
8
11
|
import { existsSync } from "fs";
|
|
9
|
-
import {
|
|
12
|
+
import { mkdir, readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
10
13
|
import path from "path";
|
|
11
14
|
import process from "process";
|
|
12
15
|
import { fileURLToPath } from "url";
|
|
@@ -43,63 +46,36 @@ async function patchPressTitle(entryPath, title) {
|
|
|
43
46
|
function escapeStringForJs(value) {
|
|
44
47
|
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
45
48
|
}
|
|
46
|
-
async function patchPackageJsonName(packagePath, newName) {
|
|
47
|
-
const text = await readFile(packagePath, "utf8");
|
|
48
|
-
const pkg = JSON.parse(text);
|
|
49
|
-
const prevName = typeof pkg.name === "string" ? pkg.name : "";
|
|
50
|
-
pkg.name = newName;
|
|
51
|
-
pkg.version = "0.0.0";
|
|
52
|
-
pkg.private = true;
|
|
53
|
-
pkg.description = `open-press workspace: ${newName}`;
|
|
54
|
-
for (const field of [
|
|
55
|
-
"publishConfig",
|
|
56
|
-
"files",
|
|
57
|
-
"bin",
|
|
58
|
-
"main",
|
|
59
|
-
"types",
|
|
60
|
-
"exports",
|
|
61
|
-
"homepage",
|
|
62
|
-
"repository",
|
|
63
|
-
"bugs",
|
|
64
|
-
"keywords",
|
|
65
|
-
"license",
|
|
66
|
-
"author"
|
|
67
|
-
]) {
|
|
68
|
-
delete pkg[field];
|
|
69
|
-
}
|
|
70
|
-
await writeFile(packagePath, JSON.stringify(pkg, null, 2) + "\n");
|
|
71
|
-
return prevName;
|
|
72
|
-
}
|
|
73
49
|
|
|
74
50
|
// src/init.ts
|
|
75
51
|
var FRAMEWORK_SKILLS_SOURCE = "quan0715/open-press";
|
|
76
52
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
77
|
-
var
|
|
78
|
-
var TEMPLATE_CORE = path.join(TEMPLATE_ROOT, "core");
|
|
53
|
+
var CLI_PACKAGE_JSON = path.resolve(__dirname, "..", "package.json");
|
|
79
54
|
async function init(options) {
|
|
80
|
-
ensureTemplateBundled();
|
|
81
55
|
const target = path.resolve(process.cwd(), options.target);
|
|
82
56
|
await ensureTarget(target);
|
|
57
|
+
const workspaceName = path.basename(target);
|
|
58
|
+
const title = options.title ?? "OpenPress Document";
|
|
59
|
+
const version = await readCliVersion();
|
|
83
60
|
log(`Creating open-press workspace at ${target}`);
|
|
84
|
-
|
|
85
|
-
await
|
|
86
|
-
|
|
87
|
-
if (existsSync(pkgPath)) {
|
|
88
|
-
await patchPackageJsonName(pkgPath, path.basename(target));
|
|
89
|
-
}
|
|
61
|
+
await writeWorkspacePackageJson(target, workspaceName, version);
|
|
62
|
+
await writeWorkspaceGitignore(target);
|
|
63
|
+
await writeStarterPress(target, title);
|
|
90
64
|
if (options.title) {
|
|
91
65
|
const pressEntry = path.join(target, "press", "index.tsx");
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
await patchPressTitle(pressEntry, options.title);
|
|
95
|
-
}
|
|
66
|
+
log("Writing title into <Press> in press/index.tsx");
|
|
67
|
+
await patchPressTitle(pressEntry, options.title);
|
|
96
68
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
69
|
+
if (options.skills) {
|
|
70
|
+
log(`Installing framework skills via \`open-press skills add\`\u2026`);
|
|
71
|
+
try {
|
|
72
|
+
await runInTarget(target, "npx", ["-y", "skills@latest", "add", FRAMEWORK_SKILLS_SOURCE]);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
log(`(framework skills install failed; retry later: open-press skills add)`);
|
|
75
|
+
log(` reason: ${err instanceof Error ? err.message : String(err)}`);
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
log("Skipping agent skills (--no-skills)");
|
|
103
79
|
}
|
|
104
80
|
if (options.install) {
|
|
105
81
|
log("Installing dependencies (npm install)\u2026");
|
|
@@ -121,13 +97,6 @@ async function init(options) {
|
|
|
121
97
|
}
|
|
122
98
|
printNextSteps(target, options);
|
|
123
99
|
}
|
|
124
|
-
function ensureTemplateBundled() {
|
|
125
|
-
if (!existsSync(TEMPLATE_CORE)) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
`Template not bundled at ${TEMPLATE_ROOT}. If running from source, run \`pnpm sync:template\` in packages/cli first.`
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
100
|
async function ensureTarget(target) {
|
|
132
101
|
if (existsSync(target)) {
|
|
133
102
|
const empty = await pathIsEmpty(target, { ignoreHarmless: true });
|
|
@@ -140,6 +109,189 @@ async function ensureTarget(target) {
|
|
|
140
109
|
}
|
|
141
110
|
await mkdir(target, { recursive: true });
|
|
142
111
|
}
|
|
112
|
+
async function readCliVersion() {
|
|
113
|
+
const pkg = JSON.parse(await readFile2(CLI_PACKAGE_JSON, "utf8"));
|
|
114
|
+
return typeof pkg.version === "string" && pkg.version ? pkg.version : "latest";
|
|
115
|
+
}
|
|
116
|
+
async function writeWorkspacePackageJson(target, workspaceName, version) {
|
|
117
|
+
const pkg = {
|
|
118
|
+
name: workspaceName,
|
|
119
|
+
version: "0.0.0",
|
|
120
|
+
private: true,
|
|
121
|
+
type: "module",
|
|
122
|
+
description: `open-press workspace: ${workspaceName}`,
|
|
123
|
+
scripts: {
|
|
124
|
+
dev: "open-press dev . --renderer react",
|
|
125
|
+
build: "open-press render . --renderer react",
|
|
126
|
+
preview: "open-press preview . --renderer react",
|
|
127
|
+
typecheck: "open-press typecheck .",
|
|
128
|
+
"openpress:image": "open-press image .",
|
|
129
|
+
"openpress:pdf": "open-press pdf .",
|
|
130
|
+
"openpress:deploy": "open-press deploy .",
|
|
131
|
+
"openpress:deploy:dry-run": "open-press deploy . --confirm --dry-run",
|
|
132
|
+
"openpress:skills": "open-press skills update"
|
|
133
|
+
},
|
|
134
|
+
dependencies: {
|
|
135
|
+
"@open-press/core": version
|
|
136
|
+
},
|
|
137
|
+
devDependencies: {
|
|
138
|
+
"@open-press/cli": version,
|
|
139
|
+
"@types/node": "^25.8.0",
|
|
140
|
+
"@types/react": "^19.2.14",
|
|
141
|
+
"@types/react-dom": "^19.2.3",
|
|
142
|
+
typescript: "^6.0.3"
|
|
143
|
+
},
|
|
144
|
+
openpress: {
|
|
145
|
+
pdf: {
|
|
146
|
+
filename: "document.pdf"
|
|
147
|
+
},
|
|
148
|
+
deploy: {
|
|
149
|
+
adapter: "cloudflare-pages",
|
|
150
|
+
source: ".deploy/openpress",
|
|
151
|
+
projectName: null,
|
|
152
|
+
commitDirty: false,
|
|
153
|
+
requiresConfirmation: true
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
await writeFile2(path.join(target, "package.json"), `${JSON.stringify(pkg, null, 2)}
|
|
158
|
+
`, "utf8");
|
|
159
|
+
}
|
|
160
|
+
async function writeWorkspaceGitignore(target) {
|
|
161
|
+
const content = [
|
|
162
|
+
"node_modules/",
|
|
163
|
+
".DS_Store",
|
|
164
|
+
"*.log",
|
|
165
|
+
"",
|
|
166
|
+
"# OpenPress generated artifacts",
|
|
167
|
+
".openpress/",
|
|
168
|
+
".deploy/",
|
|
169
|
+
".turbo/",
|
|
170
|
+
"dist/",
|
|
171
|
+
"dist-react/",
|
|
172
|
+
"public/openpress/",
|
|
173
|
+
"output/",
|
|
174
|
+
""
|
|
175
|
+
].join("\n");
|
|
176
|
+
await writeFile2(path.join(target, ".gitignore"), content, "utf8");
|
|
177
|
+
}
|
|
178
|
+
async function writeStarterPress(target, title) {
|
|
179
|
+
const pressRoot = path.join(target, "press");
|
|
180
|
+
await mkdir(path.join(pressRoot, "components"), { recursive: true });
|
|
181
|
+
await mkdir(path.join(pressRoot, "media"), { recursive: true });
|
|
182
|
+
await mkdir(path.join(pressRoot, "theme", "base"), { recursive: true });
|
|
183
|
+
await mkdir(path.join(pressRoot, "theme", "page-surfaces"), { recursive: true });
|
|
184
|
+
await mkdir(path.join(pressRoot, "theme", "shell"), { recursive: true });
|
|
185
|
+
await writeFile2(path.join(pressRoot, "design.md"), `# ${title}
|
|
186
|
+
|
|
187
|
+
Starter OpenPress workspace.
|
|
188
|
+
`, "utf8");
|
|
189
|
+
await writeFile2(path.join(pressRoot, "media", "README.md"), "# Media\n\nPlace project media here.\n", "utf8");
|
|
190
|
+
await writeFile2(
|
|
191
|
+
path.join(pressRoot, "theme", "base", "page-contract.css"),
|
|
192
|
+
`* {
|
|
193
|
+
box-sizing: border-box;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
html,
|
|
197
|
+
body {
|
|
198
|
+
margin: 0;
|
|
199
|
+
background: #181818;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
body {
|
|
203
|
+
color: #171717;
|
|
204
|
+
font-family: var(--openpress-font-body, system-ui, sans-serif);
|
|
205
|
+
-webkit-print-color-adjust: exact;
|
|
206
|
+
print-color-adjust: exact;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.reader-page {
|
|
210
|
+
background: #ffffff;
|
|
211
|
+
}
|
|
212
|
+
`,
|
|
213
|
+
"utf8"
|
|
214
|
+
);
|
|
215
|
+
await writeFile2(
|
|
216
|
+
path.join(pressRoot, "theme", "base", "typography.css"),
|
|
217
|
+
`h1,
|
|
218
|
+
h2,
|
|
219
|
+
h3,
|
|
220
|
+
p {
|
|
221
|
+
margin: 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
h1 {
|
|
225
|
+
font-family: var(--openpress-font-serif, Georgia, serif);
|
|
226
|
+
font-size: clamp(42px, 8cqw, 72px);
|
|
227
|
+
line-height: 1;
|
|
228
|
+
font-weight: 500;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
p {
|
|
232
|
+
font-size: clamp(16px, 2cqw, 22px);
|
|
233
|
+
line-height: 1.5;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
code {
|
|
237
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
238
|
+
}
|
|
239
|
+
`,
|
|
240
|
+
"utf8"
|
|
241
|
+
);
|
|
242
|
+
await writeFile2(
|
|
243
|
+
path.join(pressRoot, "theme", "base", "print.css"),
|
|
244
|
+
`@media print {
|
|
245
|
+
html,
|
|
246
|
+
body {
|
|
247
|
+
background: #ffffff;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
`,
|
|
251
|
+
"utf8"
|
|
252
|
+
);
|
|
253
|
+
await writeFile2(path.join(pressRoot, "theme", "page-surfaces", "cover.css"), "/* Starter cover surface. */\n", "utf8");
|
|
254
|
+
await writeFile2(path.join(pressRoot, "theme", "page-surfaces", "back-cover.css"), "/* Starter back-cover surface. */\n", "utf8");
|
|
255
|
+
await writeFile2(path.join(pressRoot, "theme", "page-surfaces", "toc.css"), "/* Starter TOC surface. */\n", "utf8");
|
|
256
|
+
await writeFile2(path.join(pressRoot, "theme", "shell", "reader-controls.css"), "/* Starter reader controls surface. */\n", "utf8");
|
|
257
|
+
await writeFile2(
|
|
258
|
+
path.join(pressRoot, "theme", "tokens.css"),
|
|
259
|
+
`:root {
|
|
260
|
+
--openpress-font-body: system-ui, sans-serif;
|
|
261
|
+
--openpress-font-serif: Georgia, serif;
|
|
262
|
+
}
|
|
263
|
+
`,
|
|
264
|
+
"utf8"
|
|
265
|
+
);
|
|
266
|
+
await writeFile2(
|
|
267
|
+
path.join(pressRoot, "index.tsx"),
|
|
268
|
+
`import { Frame, Press, Workspace } from "@open-press/core";
|
|
269
|
+
|
|
270
|
+
export default function OpenPressDocument() {
|
|
271
|
+
return (
|
|
272
|
+
<Workspace name="${escapeJsxAttribute(title)}">
|
|
273
|
+
<Press title="${escapeJsxAttribute(title)}">
|
|
274
|
+
<Frame frameKey="cover" role="manuscript.cover">
|
|
275
|
+
<main style={{ padding: "72px", fontFamily: "var(--openpress-font-serif, Georgia, serif)" }}>
|
|
276
|
+
<p style={{ letterSpacing: "0.12em", textTransform: "uppercase" }}>OpenPress</p>
|
|
277
|
+
<h1>${escapeText(title)}</h1>
|
|
278
|
+
<p>Edit <code>press/index.tsx</code>, then run <code>npm run dev</code>.</p>
|
|
279
|
+
</main>
|
|
280
|
+
</Frame>
|
|
281
|
+
</Press>
|
|
282
|
+
</Workspace>
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
`,
|
|
286
|
+
"utf8"
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
function escapeJsxAttribute(value) {
|
|
290
|
+
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<");
|
|
291
|
+
}
|
|
292
|
+
function escapeText(value) {
|
|
293
|
+
return value.replace(/{/g, "{").replace(/}/g, "}").replace(/</g, "<");
|
|
294
|
+
}
|
|
143
295
|
async function runInTarget(cwd, command, args, opts = {}) {
|
|
144
296
|
return new Promise((resolve, reject) => {
|
|
145
297
|
const child = spawn(command, args, {
|
|
@@ -170,6 +322,9 @@ function printNextSteps(target, options) {
|
|
|
170
322
|
if (!options.install) {
|
|
171
323
|
lines.push(" npm install");
|
|
172
324
|
}
|
|
325
|
+
if (!options.skills) {
|
|
326
|
+
lines.push(" npm run openpress:skills");
|
|
327
|
+
}
|
|
173
328
|
lines.push(
|
|
174
329
|
"",
|
|
175
330
|
" # start the workbench:",
|
|
@@ -177,30 +332,49 @@ function printNextSteps(target, options) {
|
|
|
177
332
|
"",
|
|
178
333
|
"Then open the local URL printed by Vite (typically http://127.0.0.1:5173/?dev=1).",
|
|
179
334
|
"",
|
|
180
|
-
"
|
|
181
|
-
`Cursor, Codex, Gemini CLI, etc.). Update later with: npx skills upgrade`,
|
|
182
|
-
"",
|
|
183
|
-
"Use an OpenPress-ready skill to add or adapt the press/document source tree.",
|
|
335
|
+
"Use an OpenPress-ready skill to add or adapt the press source tree.",
|
|
184
336
|
""
|
|
185
337
|
);
|
|
186
338
|
process.stdout.write(lines.join("\n"));
|
|
187
339
|
}
|
|
188
340
|
|
|
189
341
|
// src/cli.ts
|
|
342
|
+
var require2 = createRequire(import.meta.url);
|
|
190
343
|
var HELP = `open-press \u2014 AI-first fixed-layout document workspaces.
|
|
191
344
|
|
|
192
345
|
Usage:
|
|
193
|
-
|
|
346
|
+
open-press init <target> [flags]
|
|
347
|
+
open-press <command> [path] [options]
|
|
348
|
+
open-press skills <add|update> [--source <owner/repo>]
|
|
194
349
|
|
|
195
|
-
|
|
350
|
+
Init flags:
|
|
196
351
|
--title <s> Document title (written into <Press title="..."> in press/index.tsx)
|
|
197
352
|
--no-git Skip git init
|
|
198
353
|
--no-install Skip npm install
|
|
354
|
+
--skills Install OpenPress agent skills after scaffolding
|
|
355
|
+
--no-skills Skip agent skill installation
|
|
199
356
|
--help Show this help
|
|
200
357
|
|
|
358
|
+
Runtime commands:
|
|
359
|
+
dev Start the local OpenPress workbench
|
|
360
|
+
render Build the static reader
|
|
361
|
+
preview Preview the static reader
|
|
362
|
+
image Export pages to PNG
|
|
363
|
+
pdf Export pages to PDF
|
|
364
|
+
validate Validate source structure
|
|
365
|
+
inspect Inspect rendered output
|
|
366
|
+
search Search workspace source
|
|
367
|
+
replace Replace workspace source text
|
|
368
|
+
doctor Check package and skill freshness
|
|
369
|
+
upgrade Update workspace dependencies and skills
|
|
370
|
+
migrate Alias for upgrade
|
|
371
|
+
skills Install or update OpenPress agent skills
|
|
372
|
+
|
|
201
373
|
Examples:
|
|
202
374
|
npx @open-press/cli init my-doc
|
|
203
375
|
npx @open-press/cli init my-brief --title "Q2 Brief"
|
|
376
|
+
npx open-press dev .
|
|
377
|
+
npx open-press image .
|
|
204
378
|
`;
|
|
205
379
|
async function main(argv) {
|
|
206
380
|
if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
|
|
@@ -208,27 +382,26 @@ async function main(argv) {
|
|
|
208
382
|
return 0;
|
|
209
383
|
}
|
|
210
384
|
const [subcommand, ...rest] = argv;
|
|
211
|
-
if (subcommand
|
|
212
|
-
|
|
213
|
-
|
|
385
|
+
if (subcommand === "init") {
|
|
386
|
+
const options = parseInitArgs(rest);
|
|
387
|
+
if (!options) {
|
|
388
|
+
process2.stderr.write(HELP);
|
|
389
|
+
return 1;
|
|
390
|
+
}
|
|
391
|
+
try {
|
|
392
|
+
await init(options);
|
|
393
|
+
return 0;
|
|
394
|
+
} catch (err) {
|
|
395
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
396
|
+
process2.stderr.write(`open-press init failed: ${msg}
|
|
214
397
|
`);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
const options = parseInitArgs(rest);
|
|
219
|
-
if (!options) {
|
|
220
|
-
process2.stderr.write(HELP);
|
|
221
|
-
return 1;
|
|
398
|
+
return 1;
|
|
399
|
+
}
|
|
222
400
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
return 0;
|
|
226
|
-
} catch (err) {
|
|
227
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
228
|
-
process2.stderr.write(`open-press init failed: ${msg}
|
|
229
|
-
`);
|
|
230
|
-
return 1;
|
|
401
|
+
if (subcommand === "skills") {
|
|
402
|
+
return delegateToCore(normalizeSkillsArgs(rest));
|
|
231
403
|
}
|
|
404
|
+
return delegateToCore([subcommand, ...rest]);
|
|
232
405
|
}
|
|
233
406
|
function parseInitArgs(args) {
|
|
234
407
|
if (args.length === 0) {
|
|
@@ -239,7 +412,8 @@ function parseInitArgs(args) {
|
|
|
239
412
|
target: "",
|
|
240
413
|
title: void 0,
|
|
241
414
|
git: true,
|
|
242
|
-
install: true
|
|
415
|
+
install: true,
|
|
416
|
+
skills: false
|
|
243
417
|
};
|
|
244
418
|
for (let i = 0; i < args.length; i++) {
|
|
245
419
|
const arg = args[i];
|
|
@@ -253,12 +427,18 @@ function parseInitArgs(args) {
|
|
|
253
427
|
case "--no-install":
|
|
254
428
|
options.install = false;
|
|
255
429
|
break;
|
|
430
|
+
case "--no-skills":
|
|
431
|
+
options.skills = false;
|
|
432
|
+
break;
|
|
256
433
|
case "--git":
|
|
257
434
|
options.git = true;
|
|
258
435
|
break;
|
|
259
436
|
case "--install":
|
|
260
437
|
options.install = true;
|
|
261
438
|
break;
|
|
439
|
+
case "--skills":
|
|
440
|
+
options.skills = true;
|
|
441
|
+
break;
|
|
262
442
|
default:
|
|
263
443
|
if (arg.startsWith("--")) {
|
|
264
444
|
process2.stderr.write(`Unknown flag: ${arg}
|
|
@@ -281,6 +461,45 @@ function parseInitArgs(args) {
|
|
|
281
461
|
}
|
|
282
462
|
return options;
|
|
283
463
|
}
|
|
464
|
+
function normalizeSkillsArgs(args) {
|
|
465
|
+
const [subcommand, ...rest] = args;
|
|
466
|
+
if (!subcommand || subcommand === "add" || subcommand === "update") {
|
|
467
|
+
return ["skills:sync", ...rest];
|
|
468
|
+
}
|
|
469
|
+
return ["skills:sync", subcommand, ...rest];
|
|
470
|
+
}
|
|
471
|
+
async function delegateToCore(args) {
|
|
472
|
+
const coreCli = resolveCoreCli();
|
|
473
|
+
return new Promise((resolve, reject) => {
|
|
474
|
+
const child = spawn2(process2.execPath, [coreCli, ...args], {
|
|
475
|
+
cwd: process2.cwd(),
|
|
476
|
+
stdio: "inherit"
|
|
477
|
+
});
|
|
478
|
+
child.once("error", reject);
|
|
479
|
+
child.once("close", (code) => resolve(code ?? 1));
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
function resolveCoreCli() {
|
|
483
|
+
const coreEntry = require2.resolve("@open-press/core");
|
|
484
|
+
const coreRoot = findPackageRoot(coreEntry, "@open-press/core");
|
|
485
|
+
return path2.join(coreRoot, "engine", "cli.mjs");
|
|
486
|
+
}
|
|
487
|
+
function findPackageRoot(startPath, packageName) {
|
|
488
|
+
let dir = path2.dirname(startPath);
|
|
489
|
+
while (true) {
|
|
490
|
+
const pkgPath = path2.join(dir, "package.json");
|
|
491
|
+
try {
|
|
492
|
+
const pkg = require2(pkgPath);
|
|
493
|
+
if (pkg.name === packageName) return dir;
|
|
494
|
+
} catch {
|
|
495
|
+
}
|
|
496
|
+
const parent = path2.dirname(dir);
|
|
497
|
+
if (parent === dir) {
|
|
498
|
+
throw new Error(`Could not find ${packageName} package root from ${startPath}`);
|
|
499
|
+
}
|
|
500
|
+
dir = parent;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
284
503
|
main(process2.argv.slice(2)).then((code) => process2.exit(code)).catch((err) => {
|
|
285
504
|
process2.stderr.write(`${err instanceof Error ? err.stack ?? err.message : String(err)}
|
|
286
505
|
`);
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-press/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Command line interface for OpenPress workspaces.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "quan0715",
|
|
8
8
|
"homepage": "https://github.com/quan0715/open-press#readme",
|
|
@@ -24,14 +24,15 @@
|
|
|
24
24
|
"ai-first",
|
|
25
25
|
"scaffold",
|
|
26
26
|
"init",
|
|
27
|
-
"cli"
|
|
27
|
+
"cli",
|
|
28
|
+
"render",
|
|
29
|
+
"pdf"
|
|
28
30
|
],
|
|
29
31
|
"bin": {
|
|
30
32
|
"open-press": "dist/cli.js"
|
|
31
33
|
},
|
|
32
34
|
"files": [
|
|
33
35
|
"dist",
|
|
34
|
-
"template",
|
|
35
36
|
"README.md"
|
|
36
37
|
],
|
|
37
38
|
"publishConfig": {
|
|
@@ -40,15 +41,16 @@
|
|
|
40
41
|
"engines": {
|
|
41
42
|
"node": ">=20"
|
|
42
43
|
},
|
|
43
|
-
"dependencies": {
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@open-press/core": "1.1.0"
|
|
46
|
+
},
|
|
44
47
|
"devDependencies": {
|
|
45
48
|
"@types/node": "^25.8.0",
|
|
46
49
|
"tsup": "^8.5.0",
|
|
47
50
|
"typescript": "^6.0.3"
|
|
48
51
|
},
|
|
49
52
|
"scripts": {
|
|
50
|
-
"
|
|
51
|
-
"build": "pnpm sync:template && tsup",
|
|
53
|
+
"build": "tsup",
|
|
52
54
|
"dev": "tsup --watch",
|
|
53
55
|
"typecheck": "tsc --noEmit",
|
|
54
56
|
"test": "pnpm build && node --test tests/*.test.mjs"
|