@open-press/cli 0.3.0 → 0.6.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/dist/cli.js +125 -51
- package/package.json +1 -1
- package/template/core/CHANGELOG.md +73 -0
- package/template/core/engine/cli.mjs +6 -0
- package/template/core/engine/commands/_shared.mjs +9 -2
- package/template/core/engine/commands/deploy.mjs +3 -3
- package/template/core/engine/commands/dev.mjs +25 -2
- package/template/core/engine/commands/doctor.mjs +229 -0
- package/template/core/engine/commands/pdf.mjs +3 -3
- package/template/core/engine/commands/preview.mjs +4 -4
- package/template/core/engine/commands/upgrade.mjs +117 -0
- package/template/core/package.json +3 -1
- package/template/core/vite.config.ts +26 -11
- package/template/packs/academic-paper/document/chapters/01-introduction/content/01-introduction.mdx +21 -0
- package/template/packs/academic-paper/document/chapters/02-methods/content/01-methods.mdx +30 -0
- package/template/packs/academic-paper/document/chapters/03-results-and-discussion/content/01-results.mdx +29 -0
- package/template/packs/academic-paper/document/chapters/04-acknowledgment/content/01-acknowledgment.mdx +12 -0
- package/template/packs/academic-paper/document/chapters/05-references/content/01-references.mdx +27 -0
- package/template/packs/academic-paper/document/index.tsx +107 -0
- package/template/packs/academic-paper/document/openpress.config.mjs +26 -0
- package/template/packs/academic-paper/document/theme/page-surfaces/cover.css +267 -0
- package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/chapters/03-agent-skills-contributors/content/01-agent-skills-contributors.mdx +2 -3
- package/template/packs/editorial-monograph/document/components/ChapterOpenerVisual/index.tsx +76 -0
- package/template/packs/editorial-monograph/document/components/Page.tsx +27 -0
- package/template/packs/editorial-monograph/document/components/TokenSwatchGrid/index.tsx +46 -0
- package/template/packs/editorial-monograph/document/components/TokenSwatchGrid/style.css +63 -0
- package/template/packs/editorial-monograph/document/components/TypeSpecimen/index.tsx +38 -0
- package/template/packs/editorial-monograph/document/components/TypeSpecimen/style.css +111 -0
- package/template/packs/editorial-monograph/document/design.md +279 -0
- package/template/packs/editorial-monograph/document/media/README.md +13 -0
- package/template/packs/editorial-monograph/document/theme/README.md +11 -0
- package/template/packs/editorial-monograph/document/theme/base/page-contract.css +505 -0
- package/template/packs/editorial-monograph/document/theme/base/print.css +93 -0
- package/template/packs/editorial-monograph/document/theme/base/typography.css +336 -0
- package/template/packs/editorial-monograph/document/theme/fonts.css +3 -0
- package/template/packs/editorial-monograph/document/theme/page-surfaces/back-cover.css +43 -0
- package/template/packs/editorial-monograph/document/theme/page-surfaces/chapter-opener.css +205 -0
- package/template/packs/editorial-monograph/document/theme/page-surfaces/toc.css +139 -0
- package/template/packs/editorial-monograph/document/theme/patterns/_chart-frame.css +49 -0
- package/template/packs/editorial-monograph/document/theme/patterns/figure-grid.css +68 -0
- package/template/packs/editorial-monograph/document/theme/patterns/table-utilities.css +66 -0
- package/template/packs/editorial-monograph/document/theme/shell/reader-controls.css +761 -0
- package/template/packs/editorial-monograph/document/theme/tokens.css +80 -0
- package/template/packs/editorial-monograph/openpress.config.mjs +5 -0
- package/template/core/.turbo/turbo-test.log +0 -341
- package/template/skills/chinese-ai-writing-polish/SKILL.md +0 -195
- package/template/skills/claude-document/SKILL.md +0 -66
- package/template/skills/editorial-monograph/SKILL.md +0 -73
- package/template/skills/openpress/SKILL.md +0 -114
- package/template/skills/openpress/references/cli-commands.md +0 -31
- package/template/skills/openpress/references/local-review.md +0 -43
- package/template/skills/openpress-deploy/SKILL.md +0 -69
- package/template/skills/openpress-deploy/references/cloudflare-pages.md +0 -51
- package/template/skills/openpress-design/SKILL.md +0 -51
- package/template/skills/openpress-design/references/pdf-safe-css.md +0 -29
- package/template/skills/openpress-design/references/responsive-fixed-layout.md +0 -48
- package/template/skills/openpress-design/references/theme-and-components.md +0 -77
- package/template/skills/openpress-diagram-drawing/SKILL.md +0 -44
- package/template/skills/openpress-diagram-drawing/references/diagram-patterns.md +0 -93
- package/template/skills/openpress-document-hierarchy/SKILL.md +0 -81
- package/template/skills/openpress-document-hierarchy/agents/openai.yaml +0 -4
- package/template/skills/openpress-document-hierarchy/references/data-structures-outline.md +0 -115
- package/template/skills/openpress-init/SKILL.md +0 -84
- package/template/skills/openpress-style-pack-contributor/SKILL.md +0 -62
- package/template/skills/openpress-style-pack-contributor/references/starter-contract.md +0 -49
- package/template/skills/openpress-update/SKILL.md +0 -88
- package/template/skills/openpress-writing/SKILL.md +0 -68
- package/template/skills/openpress-writing/references/source-and-writing-rules.md +0 -120
- package/template/skills/teaching-notes-writing/SKILL.md +0 -54
- package/template/skills/teaching-notes-writing/references/programming.md +0 -65
- package/template/skills/teaching-notes-writing/references/teaching-patterns.md +0 -60
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/components/ChapterOpenerVisual/index.tsx +0 -0
- /package/template/{skills/claude-document/starter → packs/academic-paper}/document/components/Page.tsx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/components/TokenSwatchGrid/index.tsx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/components/TokenSwatchGrid/style.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/components/TypeSpecimen/index.tsx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/components/TypeSpecimen/style.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/design.md +0 -0
- /package/template/{skills/claude-document/starter → packs/academic-paper}/document/media/README.md +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/README.md +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/base/page-contract.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/base/print.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/base/typography.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/fonts.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/page-surfaces/back-cover.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/page-surfaces/chapter-opener.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/page-surfaces/toc.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/patterns/_chart-frame.css +0 -0
- /package/template/{skills/claude-document/starter → packs/academic-paper}/document/theme/patterns/figure-grid.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/patterns/table-utilities.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/shell/reader-controls.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/document/theme/tokens.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/academic-paper}/openpress.config.mjs +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/chapters/01-document-shape/chapter.tsx +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/chapters/01-document-shape/content/01-document-shape.mdx +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/chapters/02-review-loop/chapter.tsx +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/chapters/02-review-loop/content/01-review-loop.mdx +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/components/ChapterOpenerVisual.tsx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/claude-document}/document/components/Page.tsx +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/design.md +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/index.tsx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/claude-document}/document/media/README.md +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/openpress.config.mjs +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/README.md +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/base/page-contract.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/base/print.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/base/typography.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/fonts.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/page-surfaces/back-cover.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/page-surfaces/chapter-opener.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/page-surfaces/cover.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/page-surfaces/toc.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/patterns/_chart-frame.css +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/claude-document}/document/theme/patterns/figure-grid.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/patterns/table-utilities.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/shell/reader-controls.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/document/theme/tokens.css +0 -0
- /package/template/{skills/claude-document/starter → packs/claude-document}/openpress.config.mjs +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/chapters/01-product-and-use-cases/content/01-product-and-use-cases.mdx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/chapters/02-workflow/content/01-workflow.mdx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/chapters/04-validation-deploy/content/01-validation-deploy.mdx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/index.tsx +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/openpress.config.mjs +0 -0
- /package/template/{skills/editorial-monograph/starter → packs/editorial-monograph}/document/theme/page-surfaces/cover.css +0 -0
package/dist/cli.js
CHANGED
|
@@ -6,7 +6,7 @@ import process2 from "process";
|
|
|
6
6
|
// src/init.ts
|
|
7
7
|
import { spawn } from "child_process";
|
|
8
8
|
import { existsSync } from "fs";
|
|
9
|
-
import { cp, mkdir as mkdir2,
|
|
9
|
+
import { cp, mkdir as mkdir2, rm as rm2 } from "fs/promises";
|
|
10
10
|
import path2 from "path";
|
|
11
11
|
import process from "process";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
@@ -19,12 +19,47 @@ import path from "path";
|
|
|
19
19
|
import { Readable } from "stream";
|
|
20
20
|
import { pipeline } from "stream/promises";
|
|
21
21
|
import { x as extract } from "tar";
|
|
22
|
+
async function degit({ owner, repo, ref = "main", dest, subdir }) {
|
|
23
|
+
const url = `https://codeload.github.com/${owner}/${repo}/tar.gz/refs/heads/${ref}`;
|
|
24
|
+
const tmpDir = await mkdir(path.join(tmpdir(), `open-press-degit-${Date.now()}`), { recursive: true });
|
|
25
|
+
const tarballPath = path.join(tmpDir, "repo.tar.gz");
|
|
26
|
+
try {
|
|
27
|
+
await fetchTo(url, tarballPath);
|
|
28
|
+
await mkdir(dest, { recursive: true });
|
|
29
|
+
const subdirSegments = subdir ? subdir.split("/").filter(Boolean).length : 0;
|
|
30
|
+
const totalStrip = 1 + subdirSegments;
|
|
31
|
+
const filterPrefix = subdir ? subdir.replace(/\/$/, "") + "/" : null;
|
|
32
|
+
await extract({
|
|
33
|
+
file: tarballPath,
|
|
34
|
+
cwd: dest,
|
|
35
|
+
strip: totalStrip,
|
|
36
|
+
filter: (filePath) => {
|
|
37
|
+
const segments = filePath.split("/");
|
|
38
|
+
const inside = segments.slice(1).join("/");
|
|
39
|
+
if (filterPrefix) {
|
|
40
|
+
return inside.startsWith(filterPrefix);
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
} finally {
|
|
46
|
+
await rm(tmpDir, { recursive: true, force: true }).catch(() => {
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async function fetchTo(url, destFile) {
|
|
51
|
+
const res = await fetch(url, { redirect: "follow" });
|
|
52
|
+
if (!res.ok || !res.body) {
|
|
53
|
+
throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
|
|
54
|
+
}
|
|
55
|
+
await pipeline(Readable.fromWeb(res.body), createWriteStream(destFile));
|
|
56
|
+
}
|
|
22
57
|
async function pathIsEmpty(target) {
|
|
23
58
|
try {
|
|
24
59
|
const s = await stat(target);
|
|
25
60
|
if (!s.isDirectory()) return false;
|
|
26
|
-
const { readdir
|
|
27
|
-
const entries = await
|
|
61
|
+
const { readdir } = await import("fs/promises");
|
|
62
|
+
const entries = await readdir(target);
|
|
28
63
|
return entries.length === 0;
|
|
29
64
|
} catch {
|
|
30
65
|
return true;
|
|
@@ -80,13 +115,14 @@ async function patchPackageJsonName(packagePath, newName) {
|
|
|
80
115
|
}
|
|
81
116
|
|
|
82
117
|
// src/init.ts
|
|
83
|
-
var
|
|
118
|
+
var BUNDLED_PACKS = ["editorial-monograph", "claude-document", "academic-paper"];
|
|
119
|
+
var FRAMEWORK_SKILLS_SOURCE = "quan0715/open-press";
|
|
84
120
|
var __dirname = path2.dirname(fileURLToPath(import.meta.url));
|
|
85
121
|
var TEMPLATE_ROOT = path2.resolve(__dirname, "..", "template");
|
|
86
122
|
var TEMPLATE_CORE = path2.join(TEMPLATE_ROOT, "core");
|
|
87
|
-
var
|
|
123
|
+
var TEMPLATE_PACKS = path2.join(TEMPLATE_ROOT, "packs");
|
|
88
124
|
async function init(options) {
|
|
89
|
-
|
|
125
|
+
const packSpec = options.pack ? parsePackSpec(options.pack) : null;
|
|
90
126
|
ensureTemplateBundled();
|
|
91
127
|
const target = path2.resolve(process.cwd(), options.target);
|
|
92
128
|
await ensureTarget(target, options.force);
|
|
@@ -94,20 +130,41 @@ async function init(options) {
|
|
|
94
130
|
log("Copying framework (engine + runtime + config)\u2026");
|
|
95
131
|
await cp(TEMPLATE_CORE, target, { recursive: true });
|
|
96
132
|
const docDest = path2.join(target, "document");
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const packStarter = path2.join(
|
|
133
|
+
await rm2(docDest, { recursive: true, force: true });
|
|
134
|
+
await mkdir2(docDest, { recursive: true });
|
|
135
|
+
if (packSpec?.kind === "bundled") {
|
|
136
|
+
log(`Applying bundled style pack: ${packSpec.name}`);
|
|
137
|
+
const packStarter = path2.join(TEMPLATE_PACKS, packSpec.name, "document");
|
|
102
138
|
if (!existsSync(packStarter)) {
|
|
103
|
-
throw new Error(`
|
|
139
|
+
throw new Error(`Bundled style pack starter not found: ${packStarter}`);
|
|
104
140
|
}
|
|
105
141
|
await cp(packStarter, docDest, { recursive: true });
|
|
106
|
-
} else {
|
|
107
|
-
|
|
142
|
+
} else if (packSpec?.kind === "github") {
|
|
143
|
+
log(`Fetching style pack from github:${packSpec.owner}/${packSpec.repo}${packSpec.ref ? `#${packSpec.ref}` : ""}\u2026`);
|
|
144
|
+
try {
|
|
145
|
+
await degit({
|
|
146
|
+
owner: packSpec.owner,
|
|
147
|
+
repo: packSpec.repo,
|
|
148
|
+
ref: packSpec.ref,
|
|
149
|
+
dest: docDest,
|
|
150
|
+
subdir: "starter/document"
|
|
151
|
+
});
|
|
152
|
+
} catch (err) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Failed to fetch pack from github:${packSpec.owner}/${packSpec.repo}: ${err instanceof Error ? err.message : String(err)}`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
if (await pathIsEmpty(docDest)) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`github:${packSpec.owner}/${packSpec.repo} doesn't contain starter/document/ at the repo root.
|
|
160
|
+
Third-party pack repos should follow this layout:
|
|
161
|
+
<repo>/
|
|
162
|
+
\u251C\u2500\u2500 starter/
|
|
163
|
+
\u2502 \u2514\u2500\u2500 document/ \u2190 cli copies this into your workspace's document/
|
|
164
|
+
\u2514\u2500\u2500 skills/<pack>/SKILL.md \u2190 npx skills add picks this up`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
108
167
|
}
|
|
109
|
-
log("Installing SKILL files\u2026");
|
|
110
|
-
await installSkills(target);
|
|
111
168
|
const pkgPath = path2.join(target, "package.json");
|
|
112
169
|
if (existsSync(pkgPath)) {
|
|
113
170
|
await patchPackageJsonName(pkgPath, path2.basename(target));
|
|
@@ -122,6 +179,23 @@ async function init(options) {
|
|
|
122
179
|
author: options.author
|
|
123
180
|
});
|
|
124
181
|
}
|
|
182
|
+
log(`Installing framework skills via \`npx skills add ${FRAMEWORK_SKILLS_SOURCE}\`\u2026`);
|
|
183
|
+
try {
|
|
184
|
+
await runInTarget(target, "npx", ["-y", "skills@latest", "add", FRAMEWORK_SKILLS_SOURCE]);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
log(`(framework skills install failed; retry: npx skills add ${FRAMEWORK_SKILLS_SOURCE})`);
|
|
187
|
+
log(` reason: ${err instanceof Error ? err.message : String(err)}`);
|
|
188
|
+
}
|
|
189
|
+
if (packSpec?.kind === "github") {
|
|
190
|
+
const packSource = `${packSpec.owner}/${packSpec.repo}`;
|
|
191
|
+
log(`Installing pack skills via \`npx skills add ${packSource}\`\u2026`);
|
|
192
|
+
try {
|
|
193
|
+
await runInTarget(target, "npx", ["-y", "skills@latest", "add", packSource]);
|
|
194
|
+
} catch (err) {
|
|
195
|
+
log(`(pack skills install failed; retry: npx skills add ${packSource})`);
|
|
196
|
+
log(` reason: ${err instanceof Error ? err.message : String(err)}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
125
199
|
if (options.install) {
|
|
126
200
|
log("Installing dependencies (npm install)\u2026");
|
|
127
201
|
await runInTarget(target, "npm", ["install"]);
|
|
@@ -142,44 +216,33 @@ async function init(options) {
|
|
|
142
216
|
}
|
|
143
217
|
printNextSteps(target, options);
|
|
144
218
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
await copySkillFiles(source, agentsTarget);
|
|
219
|
+
function parsePackSpec(spec) {
|
|
220
|
+
if (spec.startsWith("github:")) {
|
|
221
|
+
const rest = spec.slice("github:".length);
|
|
222
|
+
const [pathPart, ref] = rest.split("#");
|
|
223
|
+
const segments = pathPart.split("/").filter(Boolean);
|
|
224
|
+
if (segments.length !== 2) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
`Invalid --pack spec: "${spec}". Use github:owner/repo or github:owner/repo#ref.`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
const [owner, repo] = segments;
|
|
230
|
+
return { kind: "github", owner, repo, ref: ref?.trim() || void 0 };
|
|
158
231
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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 });
|
|
232
|
+
if (!BUNDLED_PACKS.includes(spec)) {
|
|
233
|
+
throw new Error(
|
|
234
|
+
`Unknown style pack: "${spec}". Bundled packs: ${BUNDLED_PACKS.join(", ")}. For third-party packs use github:owner/repo (e.g. github:quan0715/openpress-pack-nycu-thesis).`
|
|
235
|
+
);
|
|
168
236
|
}
|
|
237
|
+
return { kind: "bundled", name: spec };
|
|
169
238
|
}
|
|
170
239
|
function ensureTemplateBundled() {
|
|
171
|
-
if (!existsSync(TEMPLATE_CORE) || !existsSync(
|
|
240
|
+
if (!existsSync(TEMPLATE_CORE) || !existsSync(TEMPLATE_PACKS)) {
|
|
172
241
|
throw new Error(
|
|
173
242
|
`Template not bundled at ${TEMPLATE_ROOT}. If running from source, run \`pnpm sync:template\` in packages/cli first.`
|
|
174
243
|
);
|
|
175
244
|
}
|
|
176
245
|
}
|
|
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
246
|
async function ensureTarget(target, force) {
|
|
184
247
|
if (existsSync(target)) {
|
|
185
248
|
if (force) return;
|
|
@@ -216,7 +279,7 @@ function printNextSteps(target, options) {
|
|
|
216
279
|
const rel = path2.relative(process.cwd(), target) || ".";
|
|
217
280
|
const lines = [
|
|
218
281
|
"",
|
|
219
|
-
"\u2713 Done
|
|
282
|
+
"\u2713 Done. Your open-press workspace is ready.",
|
|
220
283
|
"",
|
|
221
284
|
"Next steps:",
|
|
222
285
|
` cd ${rel}`
|
|
@@ -229,9 +292,11 @@ function printNextSteps(target, options) {
|
|
|
229
292
|
" # start the workbench:",
|
|
230
293
|
" npm run dev",
|
|
231
294
|
"",
|
|
232
|
-
"Then open the local URL printed by
|
|
295
|
+
"Then open the local URL printed by Vite (typically http://127.0.0.1:5173/?dev=1).",
|
|
296
|
+
"",
|
|
297
|
+
"Agent skills installed under .agents/skills/ (universal \u2014 read by Claude Code,",
|
|
298
|
+
`Cursor, Codex, Gemini CLI, etc.). Update later with: npx skills upgrade`,
|
|
233
299
|
"",
|
|
234
|
-
"AI agent skills are installed under .claude/skills/ and .agents/skills/.",
|
|
235
300
|
"Edit content under document/chapters/, or ask your AI agent to help.",
|
|
236
301
|
""
|
|
237
302
|
);
|
|
@@ -245,19 +310,28 @@ Usage:
|
|
|
245
310
|
npx @open-press/cli init <target> [flags]
|
|
246
311
|
|
|
247
312
|
Flags:
|
|
248
|
-
--pack <
|
|
313
|
+
--pack <spec> Style pack source. Either:
|
|
314
|
+
\u2022 a bundled name \u2014 editorial-monograph | claude-document | academic-paper
|
|
315
|
+
\u2022 github:owner/repo (third-party pack)
|
|
316
|
+
\u2022 github:owner/repo#branch-or-tag
|
|
249
317
|
--title <s> Document title (written to openpress.config.mjs)
|
|
250
318
|
--subtitle <s> Document subtitle
|
|
251
319
|
--organization <s> Organization name
|
|
252
|
-
--author <s> Author name
|
|
320
|
+
--author <s> Author name
|
|
253
321
|
--no-git Skip git init
|
|
254
322
|
--no-install Skip npm install
|
|
255
323
|
--force Allow non-empty target
|
|
256
324
|
--help Show this help
|
|
257
325
|
|
|
258
326
|
Examples:
|
|
327
|
+
# Bundled
|
|
259
328
|
npx @open-press/cli init my-doc --pack editorial-monograph
|
|
260
|
-
npx @open-press/cli init my-
|
|
329
|
+
npx @open-press/cli init my-brief --pack claude-document --title "Q2 Brief" --author Quan
|
|
330
|
+
npx @open-press/cli init my-paper --pack academic-paper --title "Paper Title" --author "First Author"
|
|
331
|
+
|
|
332
|
+
# Third-party (any GitHub repo with starter/document/ at the root)
|
|
333
|
+
npx @open-press/cli init my-thesis --pack github:quan0715/openpress-pack-nycu-thesis
|
|
334
|
+
npx @open-press/cli init my-paper --pack github:foo/their-pack#v1.2
|
|
261
335
|
`;
|
|
262
336
|
async function main(argv) {
|
|
263
337
|
if (argv.length === 0 || argv.includes("--help") || argv.includes("-h")) {
|
package/package.json
CHANGED
|
@@ -1,5 +1,78 @@
|
|
|
1
1
|
# @open-press/core
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- f8fdecd: Third bundled pack: `academic-paper`.
|
|
8
|
+
|
|
9
|
+
A single-column A4 academic / research paper starter — serif title block, abstract band, index terms, numbered sections (I, II, III), italic sub-sections (A, B, C), `[N]` numeric references, sample chapters derived from the IEEE conference template structure (Introduction, Methods, Results & Discussion, Acknowledgment, References).
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npx @open-press/cli init my-paper --pack academic-paper
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Suitable for: draft / preprint / iteration. Not suitable for camera-ready IEEE / ACM submission — those still need LaTeX with the publisher's class file.
|
|
16
|
+
|
|
17
|
+
Two-column body and other paged-document features (footnotes, cross-references with page numbers, running headers) are intentionally **out of scope for this release**. They'll be designed as a self-maintained engine evolution + multi-mode architecture in a separate spec round, rather than depending on a third-party pagination polyfill.
|
|
18
|
+
|
|
19
|
+
- c490653: `@open-press/cli init` accepts third-party style packs via `--pack github:owner/repo`.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# bundled (unchanged)
|
|
23
|
+
npx @open-press/cli init my-doc --pack editorial-monograph
|
|
24
|
+
|
|
25
|
+
# third-party (new)
|
|
26
|
+
npx @open-press/cli init my-thesis --pack github:quan0715/openpress-pack-nycu-thesis
|
|
27
|
+
npx @open-press/cli init my-paper --pack github:foo/their-pack#v1.2
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The cli fetches `starter/document/` from the named repo (default branch, or `#ref` for a specific branch/tag) and copies it into the new workspace. If the pack repo also publishes SKILL files at `skills/<name>/`, they're installed via `npx skills add <owner>/<repo>` after the framework skills, so the agent picks them up automatically.
|
|
31
|
+
|
|
32
|
+
Repo layout convention for third-party packs is documented in `docs/style-pack-authoring.md`. Empty-result extraction (the named repo exists but has no `starter/document/` at root) fails with a clear error pointing at the expected layout.
|
|
33
|
+
|
|
34
|
+
The two bundled packs (`editorial-monograph`, `claude-document`) keep their current short-name behaviour; only the cli's validator widened to accept the `github:` prefix.
|
|
35
|
+
|
|
36
|
+
## 0.5.0
|
|
37
|
+
|
|
38
|
+
### Minor Changes
|
|
39
|
+
|
|
40
|
+
- 0169cba: Agent-driven upgrade flow.
|
|
41
|
+
|
|
42
|
+
**New commands:**
|
|
43
|
+
- `npx open-press doctor` — diagnose workspace against latest framework state. Reports `@open-press/core` version vs npm latest, installed skill count, and any pending `docs/migrations/<version>.md` notes between current and latest. `--json` for machine-readable output, `--no-cache` to bypass the 24h cache. Always exits 0 (informational only).
|
|
44
|
+
|
|
45
|
+
- `npx open-press upgrade` — orchestrate the upgrade. Runs `npm update @open-press/core` (when the workspace declares the dep) and `npx skills upgrade`, then surfaces the list of migration notes for the agent to read. **Does not auto-edit `document/` content** — the agent reads the surfaced `docs/migrations/<version>.md` notes and proposes edits to the user with confirmation. Use `--dry-run` to preview, `--no-deps` / `--no-skills` to target one layer.
|
|
46
|
+
|
|
47
|
+
**Dev startup notice:**
|
|
48
|
+
|
|
49
|
+
`open-press dev` now runs `doctor` before starting Vite. When the workspace is behind, a single line prints: `○ open-press: @open-press/core 0.4.0 → 0.5.0 · 1 migration note(s) — run npx open-press doctor for details.` Cached for 24h, network failure is silent, never blocks dev.
|
|
50
|
+
|
|
51
|
+
**Migration docs:**
|
|
52
|
+
- New `docs/migrations/_template.md` — each release with breaking changes ships a `docs/migrations/<version>.md` file with sections the agent reads.
|
|
53
|
+
- New `docs/migrations/0.4.0.md` — backfilled. Documents the SKILL fold (no document or CLI changes).
|
|
54
|
+
|
|
55
|
+
**SKILL update:**
|
|
56
|
+
|
|
57
|
+
`openpress` skill's "Updating An Existing Workspace" section rewritten around the new commands: detect (`doctor`), apply (`upgrade`), interpret migration notes, propose document edits with user confirmation. Concrete agent workflow + breaking-change reference table.
|
|
58
|
+
|
|
59
|
+
### Patch Changes
|
|
60
|
+
|
|
61
|
+
- 931d4ac: Support framework root dogfood workspaces and correct CLI script paths outside the core package root.
|
|
62
|
+
|
|
63
|
+
## 0.4.0
|
|
64
|
+
|
|
65
|
+
### Minor Changes
|
|
66
|
+
|
|
67
|
+
- 3cb4939: Consolidate internal skills (13 → 11).
|
|
68
|
+
- `openpress-update` folded into `openpress` as an "Updating An Existing Workspace" section. The release-upgrade flow, pre-flight checks, breaking-change reference, and do-not list are now part of the system-operation skill where they naturally belong.
|
|
69
|
+
- `openpress-document-hierarchy` folded into `openpress-writing` as a "Hierarchy" section. Hierarchy decisions (H2/H3/H4 model, TOC depth, appendix placement, H4 granularity) and prose decisions happen in the same workflow; one skill, one routing decision.
|
|
70
|
+
- `references/data-structures-outline.md` moved from the hierarchy skill into `openpress-writing/references/`.
|
|
71
|
+
|
|
72
|
+
Lower maintenance surface: 2 fewer SKILL.md files to keep in sync, ~5 fewer cross-references to police. No content lost — same rules, fewer files.
|
|
73
|
+
|
|
74
|
+
User impact: agents already in workspaces with `openpress-update` or `openpress-document-hierarchy` SKILL files installed should run `npx skills upgrade` to refresh the catalog.
|
|
75
|
+
|
|
3
76
|
## 0.3.0
|
|
4
77
|
|
|
5
78
|
### Minor Changes
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as deployCmd from "./commands/deploy.mjs";
|
|
4
4
|
import * as devCmd from "./commands/dev.mjs";
|
|
5
|
+
import * as doctorCmd from "./commands/doctor.mjs";
|
|
5
6
|
import * as exportCmd from "./commands/export.mjs";
|
|
6
7
|
import * as initCmd from "./commands/init.mjs";
|
|
7
8
|
import * as inspectCmd from "./commands/inspect.mjs";
|
|
@@ -12,6 +13,7 @@ import * as replaceCmd from "./commands/replace.mjs";
|
|
|
12
13
|
import * as renderCmd from "./commands/render.mjs";
|
|
13
14
|
import * as searchCmd from "./commands/search.mjs";
|
|
14
15
|
import * as typecheckCmd from "./commands/typecheck.mjs";
|
|
16
|
+
import * as upgradeCmd from "./commands/upgrade.mjs";
|
|
15
17
|
import * as validateCmd from "./commands/validate.mjs";
|
|
16
18
|
import { parseOptions } from "./commands/_shared.mjs";
|
|
17
19
|
import { loadConfig } from "./config.mjs";
|
|
@@ -32,6 +34,8 @@ const COMMANDS = {
|
|
|
32
34
|
typecheck: typecheckCmd,
|
|
33
35
|
pdf: pdfCmd,
|
|
34
36
|
deploy: deployCmd,
|
|
37
|
+
doctor: doctorCmd,
|
|
38
|
+
upgrade: upgradeCmd,
|
|
35
39
|
};
|
|
36
40
|
|
|
37
41
|
const args = process.argv.slice(2);
|
|
@@ -87,6 +91,8 @@ Commands:
|
|
|
87
91
|
typecheck
|
|
88
92
|
pdf [--output <outputDir>/<pdf.filename>] [--no-build] [--dry-run]
|
|
89
93
|
deploy --confirm [--dry-run]
|
|
94
|
+
doctor [--json] [--no-cache] # version + skill staleness check
|
|
95
|
+
upgrade [--dry-run] [--no-deps] [--no-skills] [--json] # apply updates; agent-driven
|
|
90
96
|
|
|
91
97
|
Style packs available for \`init --skill\`: ${skillList}
|
|
92
98
|
`);
|
|
@@ -7,8 +7,9 @@ import { loadConfig, publicPdfHref } from "../config.mjs";
|
|
|
7
7
|
import { exportDocument } from "../document-export.mjs";
|
|
8
8
|
import { optimizePdfMediaForStaticRoot } from "../pdf-media.mjs";
|
|
9
9
|
|
|
10
|
-
const ENGINE_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
-
const
|
|
10
|
+
export const ENGINE_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
11
|
+
export const CLI_ENTRY = path.join(ENGINE_DIR, "cli.mjs");
|
|
12
|
+
export const STATIC_SERVER = path.join(ENGINE_DIR, "static-server.mjs");
|
|
12
13
|
|
|
13
14
|
export function parseOptions(argv) {
|
|
14
15
|
const options = {};
|
|
@@ -62,6 +63,12 @@ export function runCommand(commandName, commandArgs, cwd) {
|
|
|
62
63
|
return result.status ?? 1;
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
export function formatNodeScriptCommand(root, scriptPath) {
|
|
67
|
+
const relative = path.relative(root, scriptPath).replaceAll("\\", "/");
|
|
68
|
+
const displayPath = relative && !relative.startsWith("../") ? relative : scriptPath;
|
|
69
|
+
return `node ${displayPath}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
export async function buildReactStatic({ root, noBuild = false, recurse, silent = false }) {
|
|
66
73
|
if (noBuild) return 0;
|
|
67
74
|
if (!silent) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { deploySync } from "../deploy-sync.mjs";
|
|
3
|
-
import { buildReactPdf, runCommand, writePdfStageDeployConfig } from "./_shared.mjs";
|
|
3
|
+
import { CLI_ENTRY, buildReactPdf, formatNodeScriptCommand, runCommand, writePdfStageDeployConfig } from "./_shared.mjs";
|
|
4
4
|
|
|
5
5
|
export async function run({ root, config, options, recurse }) {
|
|
6
6
|
if (config.deploy.requiresConfirmation === true && !options.confirm) {
|
|
@@ -12,9 +12,9 @@ export async function run({ root, config, options, recurse }) {
|
|
|
12
12
|
const commitDirty = config.deploy.commitDirty;
|
|
13
13
|
if (options.dryRun) {
|
|
14
14
|
console.log("OpenPress deploy dry run");
|
|
15
|
-
console.log(
|
|
15
|
+
console.log(`Command: ${formatNodeScriptCommand(root, CLI_ENTRY)} render . --renderer react`);
|
|
16
16
|
console.log(`Step: deploy-sync (copy ${config.outputDir} → ${source})`);
|
|
17
|
-
console.log(`Command:
|
|
17
|
+
console.log(`Command: ${formatNodeScriptCommand(root, CLI_ENTRY)} pdf . --output ${source}/${config.pdf.filename}`);
|
|
18
18
|
console.log(`Step: write ${source}/openpress/deploy.json with deployment metadata`);
|
|
19
19
|
console.log(`Command: npx wrangler pages deploy ${source}${projectName ? ` --project-name=${projectName}` : ""}${commitDirty ? " --commit-dirty=true" : ""}`);
|
|
20
20
|
return 0;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { exportDocument } from "../document-export.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { diagnose } from "./doctor.mjs";
|
|
3
|
+
import { CLI_ENTRY, formatNodeScriptCommand, runCommand } from "./_shared.mjs";
|
|
3
4
|
|
|
4
5
|
export async function run({ root, options }) {
|
|
5
6
|
const renderer = options.renderer ?? "react";
|
|
@@ -13,7 +14,7 @@ export async function run({ root, options }) {
|
|
|
13
14
|
if (options.dryRun) {
|
|
14
15
|
console.log(`OpenPress dev URL: ${url}`);
|
|
15
16
|
if (!options.noBuild) {
|
|
16
|
-
console.log(
|
|
17
|
+
console.log(`Command: ${formatNodeScriptCommand(root, CLI_ENTRY)} export .`);
|
|
17
18
|
}
|
|
18
19
|
console.log(`Command: npx vite --config vite.config.ts --host ${host} --port ${port}`);
|
|
19
20
|
return 0;
|
|
@@ -21,6 +22,28 @@ export async function run({ root, options }) {
|
|
|
21
22
|
if (!options.noBuild) {
|
|
22
23
|
await exportDocument(root);
|
|
23
24
|
}
|
|
25
|
+
|
|
26
|
+
// One-line update notice (24h cached, network failure is silent).
|
|
27
|
+
await printDoctorNoticeIfStale(root);
|
|
28
|
+
|
|
24
29
|
console.log(`OpenPress dev: ${url}`);
|
|
25
30
|
return runCommand("npx", ["vite", "--config", "vite.config.ts", "--host", host, "--port", port], root);
|
|
26
31
|
}
|
|
32
|
+
|
|
33
|
+
async function printDoctorNoticeIfStale(root) {
|
|
34
|
+
try {
|
|
35
|
+
const report = await diagnose(root);
|
|
36
|
+
if (!report.stale) return;
|
|
37
|
+
const parts = [];
|
|
38
|
+
if (report.coreUpdateAvailable) {
|
|
39
|
+
parts.push(`@open-press/core ${report.coreVersion} → ${report.coreLatest}`);
|
|
40
|
+
}
|
|
41
|
+
if (report.pendingMigrations.length > 0) {
|
|
42
|
+
parts.push(`${report.pendingMigrations.length} migration note(s)`);
|
|
43
|
+
}
|
|
44
|
+
if (parts.length === 0) return;
|
|
45
|
+
console.log(`○ open-press: ${parts.join(" · ")} — run \`npx open-press doctor\` for details.`);
|
|
46
|
+
} catch {
|
|
47
|
+
// Doctor is informational only; never block dev.
|
|
48
|
+
}
|
|
49
|
+
}
|