@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
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24h
|
|
6
|
+
const CORE_PACKAGE = "@open-press/core";
|
|
7
|
+
|
|
8
|
+
export async function run({ root, options }) {
|
|
9
|
+
const json = Boolean(options?.json);
|
|
10
|
+
const noCache = Boolean(options?.noCache);
|
|
11
|
+
|
|
12
|
+
const report = await diagnose(root, { noCache });
|
|
13
|
+
|
|
14
|
+
if (json) {
|
|
15
|
+
process.stdout.write(JSON.stringify(report, null, 2) + "\n");
|
|
16
|
+
} else {
|
|
17
|
+
printHumanReport(report);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Exit 0 even when stale — doctor is informational, not a gate.
|
|
21
|
+
// Agents / CI can check report.stale or report.coreUpdateAvailable.
|
|
22
|
+
return 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Diagnose workspace against latest framework state.
|
|
27
|
+
* Result shape:
|
|
28
|
+
* {
|
|
29
|
+
* coreVersion: "0.4.0", // installed
|
|
30
|
+
* coreLatest: "0.5.0" | null, // null on network failure
|
|
31
|
+
* coreUpdateAvailable: boolean,
|
|
32
|
+
* skillsInstalled: ["openpress", ...],
|
|
33
|
+
* skillsLockSource: "quan0715/open-press" | null,
|
|
34
|
+
* pendingMigrations: ["0.5.0"], // versions with docs/migrations notes
|
|
35
|
+
* stale: boolean, // either core or skills behind
|
|
36
|
+
* cachedAt: ISO timestamp
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
export async function diagnose(root, { noCache = false } = {}) {
|
|
40
|
+
const cachePath = path.join(root, ".openpress", "cache", "doctor.json");
|
|
41
|
+
|
|
42
|
+
if (!noCache) {
|
|
43
|
+
const cached = await readCached(cachePath);
|
|
44
|
+
if (cached) return cached;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const coreVersion = await readCoreVersion(root);
|
|
48
|
+
const coreLatest = await fetchCoreLatest();
|
|
49
|
+
const skillsInstalled = await listInstalledSkills(root);
|
|
50
|
+
const skillsLockSource = await readSkillsLockSource(root);
|
|
51
|
+
const pendingMigrations = await listPendingMigrations(root, coreVersion, coreLatest);
|
|
52
|
+
|
|
53
|
+
const coreUpdateAvailable = Boolean(
|
|
54
|
+
coreVersion && coreLatest && coreVersion !== coreLatest && semverLt(coreVersion, coreLatest),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const report = {
|
|
58
|
+
coreVersion,
|
|
59
|
+
coreLatest,
|
|
60
|
+
coreUpdateAvailable,
|
|
61
|
+
skillsInstalled,
|
|
62
|
+
skillsLockSource,
|
|
63
|
+
pendingMigrations,
|
|
64
|
+
stale: coreUpdateAvailable || pendingMigrations.length > 0,
|
|
65
|
+
cachedAt: new Date().toISOString(),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
await writeCached(cachePath, report).catch(() => {});
|
|
69
|
+
return report;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function readCached(cachePath) {
|
|
73
|
+
try {
|
|
74
|
+
const stats = await stat(cachePath);
|
|
75
|
+
if (Date.now() - stats.mtimeMs > CACHE_TTL_MS) return null;
|
|
76
|
+
return JSON.parse(await readFile(cachePath, "utf8"));
|
|
77
|
+
} catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function writeCached(cachePath, report) {
|
|
83
|
+
await mkdir(path.dirname(cachePath), { recursive: true });
|
|
84
|
+
await writeFile(cachePath, JSON.stringify(report, null, 2) + "\n", "utf8");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function readCoreVersion(root) {
|
|
88
|
+
// Try workspace package.json deps first; fall back to installed package.
|
|
89
|
+
try {
|
|
90
|
+
const pkg = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
|
|
91
|
+
const range = pkg.dependencies?.[CORE_PACKAGE] ?? pkg.devDependencies?.[CORE_PACKAGE];
|
|
92
|
+
if (range) {
|
|
93
|
+
// Try the installed version (more accurate than the range).
|
|
94
|
+
try {
|
|
95
|
+
const installed = JSON.parse(
|
|
96
|
+
await readFile(path.join(root, "node_modules", CORE_PACKAGE, "package.json"), "utf8"),
|
|
97
|
+
);
|
|
98
|
+
return installed.version;
|
|
99
|
+
} catch {
|
|
100
|
+
return range.replace(/^[\^~>=<\s]+/, "");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
} catch {}
|
|
104
|
+
|
|
105
|
+
// Self-bundled framework (cli scaffolded workspace): pkg.version is the framework version.
|
|
106
|
+
try {
|
|
107
|
+
const pkg = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
|
|
108
|
+
if (pkg.name === CORE_PACKAGE) return pkg.version;
|
|
109
|
+
} catch {}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function fetchCoreLatest() {
|
|
115
|
+
try {
|
|
116
|
+
const res = await fetch(`https://registry.npmjs.org/${CORE_PACKAGE}/latest`, {
|
|
117
|
+
headers: { Accept: "application/json" },
|
|
118
|
+
signal: AbortSignal.timeout(5000),
|
|
119
|
+
});
|
|
120
|
+
if (!res.ok) return null;
|
|
121
|
+
const data = await res.json();
|
|
122
|
+
return typeof data.version === "string" ? data.version : null;
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function listInstalledSkills(root) {
|
|
129
|
+
const skillsDir = path.join(root, ".agents", "skills");
|
|
130
|
+
try {
|
|
131
|
+
const { readdir } = await import("node:fs/promises");
|
|
132
|
+
const entries = await readdir(skillsDir, { withFileTypes: true });
|
|
133
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
134
|
+
} catch {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function readSkillsLockSource(root) {
|
|
140
|
+
try {
|
|
141
|
+
const lock = JSON.parse(await readFile(path.join(root, "skills-lock.json"), "utf8"));
|
|
142
|
+
const sources = lock?.sources;
|
|
143
|
+
if (Array.isArray(sources) && sources.length > 0) return sources[0]?.source ?? null;
|
|
144
|
+
return null;
|
|
145
|
+
} catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function listPendingMigrations(root, currentVersion, latestVersion) {
|
|
151
|
+
if (!currentVersion || !latestVersion || !semverLt(currentVersion, latestVersion)) return [];
|
|
152
|
+
// Look for docs/migrations/<version>.md files for versions in (current, latest].
|
|
153
|
+
const migrationsDir = path.join(root, "docs", "migrations");
|
|
154
|
+
try {
|
|
155
|
+
const { readdir } = await import("node:fs/promises");
|
|
156
|
+
const files = await readdir(migrationsDir);
|
|
157
|
+
return files
|
|
158
|
+
.filter((f) => /^\d+\.\d+\.\d+\.md$/.test(f))
|
|
159
|
+
.map((f) => f.replace(/\.md$/, ""))
|
|
160
|
+
.filter((v) => semverGt(v, currentVersion) && !semverGt(v, latestVersion))
|
|
161
|
+
.sort(semverCompare);
|
|
162
|
+
} catch {
|
|
163
|
+
return [];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function semverParse(v) {
|
|
168
|
+
const m = /^(\d+)\.(\d+)\.(\d+)/.exec(v);
|
|
169
|
+
if (!m) return [0, 0, 0];
|
|
170
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
171
|
+
}
|
|
172
|
+
function semverCompare(a, b) {
|
|
173
|
+
const A = semverParse(a);
|
|
174
|
+
const B = semverParse(b);
|
|
175
|
+
for (let i = 0; i < 3; i++) if (A[i] !== B[i]) return A[i] - B[i];
|
|
176
|
+
return 0;
|
|
177
|
+
}
|
|
178
|
+
function semverLt(a, b) { return semverCompare(a, b) < 0; }
|
|
179
|
+
function semverGt(a, b) { return semverCompare(a, b) > 0; }
|
|
180
|
+
|
|
181
|
+
function printHumanReport(report) {
|
|
182
|
+
const lines = [];
|
|
183
|
+
lines.push("○ open-press doctor");
|
|
184
|
+
lines.push("");
|
|
185
|
+
lines.push("framework");
|
|
186
|
+
if (report.coreVersion) {
|
|
187
|
+
if (report.coreLatest === null) {
|
|
188
|
+
lines.push(` ? @open-press/core: ${report.coreVersion} installed (couldn't check latest — offline?)`);
|
|
189
|
+
} else if (report.coreUpdateAvailable) {
|
|
190
|
+
lines.push(` ⚠ @open-press/core: ${report.coreVersion} installed → ${report.coreLatest} available`);
|
|
191
|
+
} else {
|
|
192
|
+
lines.push(` ✓ @open-press/core: ${report.coreVersion} (latest)`);
|
|
193
|
+
}
|
|
194
|
+
} else {
|
|
195
|
+
lines.push(" ? @open-press/core: not detected in this workspace");
|
|
196
|
+
}
|
|
197
|
+
lines.push("");
|
|
198
|
+
lines.push("skills");
|
|
199
|
+
if (report.skillsInstalled.length === 0) {
|
|
200
|
+
lines.push(" ? no skills installed under .agents/skills/");
|
|
201
|
+
lines.push(" run: npx skills add quan0715/open-press");
|
|
202
|
+
} else {
|
|
203
|
+
lines.push(` ✓ ${report.skillsInstalled.length} skills installed`);
|
|
204
|
+
if (report.skillsLockSource) {
|
|
205
|
+
lines.push(` source: ${report.skillsLockSource}`);
|
|
206
|
+
lines.push(" refresh: npx skills upgrade");
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
lines.push("");
|
|
210
|
+
lines.push("migrations");
|
|
211
|
+
if (report.pendingMigrations.length === 0) {
|
|
212
|
+
if (report.coreUpdateAvailable) {
|
|
213
|
+
lines.push(` ✓ no breaking migrations documented for the ${report.coreLatest} window`);
|
|
214
|
+
} else {
|
|
215
|
+
lines.push(" ✓ up to date");
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
lines.push(` ⚠ ${report.pendingMigrations.length} migration note(s) since your version:`);
|
|
219
|
+
for (const v of report.pendingMigrations) lines.push(` - docs/migrations/${v}.md`);
|
|
220
|
+
}
|
|
221
|
+
lines.push("");
|
|
222
|
+
if (report.stale) {
|
|
223
|
+
lines.push("next");
|
|
224
|
+
lines.push(" npx open-press upgrade # apply all updates (agent-driven)");
|
|
225
|
+
lines.push(" npx open-press doctor --json # machine-readable output");
|
|
226
|
+
lines.push("");
|
|
227
|
+
}
|
|
228
|
+
process.stdout.write(lines.join("\n"));
|
|
229
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import { buildReactPdf } from "./_shared.mjs";
|
|
2
|
+
import { CLI_ENTRY, STATIC_SERVER, buildReactPdf, formatNodeScriptCommand } from "./_shared.mjs";
|
|
3
3
|
|
|
4
4
|
export async function run({ root, config, options, recurse }) {
|
|
5
5
|
const outputPath = options.output ? path.resolve(root, options.output) : undefined;
|
|
@@ -7,8 +7,8 @@ export async function run({ root, config, options, recurse }) {
|
|
|
7
7
|
const relOutput = path.relative(root, outputPath ?? config.paths.pdf);
|
|
8
8
|
const host = options.host ?? "127.0.0.1";
|
|
9
9
|
const port = options.port ?? "5185";
|
|
10
|
-
console.log(
|
|
11
|
-
console.log(`Command:
|
|
10
|
+
console.log(`Command: ${formatNodeScriptCommand(root, CLI_ENTRY)} render . --renderer react`);
|
|
11
|
+
console.log(`Command: ${formatNodeScriptCommand(root, STATIC_SERVER)} ${config.outputDir} --host ${host} --port ${port} --workspace .`);
|
|
12
12
|
console.log(`Command: Chrome --print-to-pdf=${relOutput} http://${host}:${port}/?print=1`);
|
|
13
13
|
return 0;
|
|
14
14
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { runCommand } from "./_shared.mjs";
|
|
1
|
+
import { CLI_ENTRY, STATIC_SERVER, formatNodeScriptCommand, runCommand } from "./_shared.mjs";
|
|
2
2
|
|
|
3
3
|
export async function run({ root, config, options, recurse }) {
|
|
4
4
|
const renderer = options.renderer ?? "react";
|
|
@@ -12,9 +12,9 @@ export async function run({ root, config, options, recurse }) {
|
|
|
12
12
|
if (options.dryRun) {
|
|
13
13
|
console.log(`OpenPress preview URL: ${url}`);
|
|
14
14
|
if (!options.noBuild) {
|
|
15
|
-
console.log(
|
|
15
|
+
console.log(`Command: ${formatNodeScriptCommand(root, CLI_ENTRY)} render . --renderer react`);
|
|
16
16
|
}
|
|
17
|
-
console.log(`Command:
|
|
17
|
+
console.log(`Command: ${formatNodeScriptCommand(root, STATIC_SERVER)} ${config.outputDir} --host ${host} --port ${port} --workspace .`);
|
|
18
18
|
return 0;
|
|
19
19
|
}
|
|
20
20
|
if (!options.noBuild) {
|
|
@@ -22,5 +22,5 @@ export async function run({ root, config, options, recurse }) {
|
|
|
22
22
|
if (renderCode !== 0) return renderCode;
|
|
23
23
|
}
|
|
24
24
|
console.log(`OpenPress preview: ${url}`);
|
|
25
|
-
return runCommand("node", [
|
|
25
|
+
return runCommand("node", [STATIC_SERVER, config.outputDir, "--host", host, "--port", port, "--workspace", "."], root);
|
|
26
26
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { diagnose } from "./doctor.mjs";
|
|
5
|
+
import { runCommand } from "./_shared.mjs";
|
|
6
|
+
|
|
7
|
+
export async function run({ root, options }) {
|
|
8
|
+
const dryRun = Boolean(options?.dryRun);
|
|
9
|
+
const skipSkills = Boolean(options?.noSkills);
|
|
10
|
+
const skipDeps = Boolean(options?.noDeps);
|
|
11
|
+
const json = Boolean(options?.json);
|
|
12
|
+
|
|
13
|
+
// 1. Fresh diagnose (force re-check, ignore cache).
|
|
14
|
+
const before = await diagnose(root, { noCache: true });
|
|
15
|
+
|
|
16
|
+
if (!before.stale) {
|
|
17
|
+
const message = "open-press is already up to date.";
|
|
18
|
+
if (json) {
|
|
19
|
+
process.stdout.write(JSON.stringify({ status: "noop", before }, null, 2) + "\n");
|
|
20
|
+
} else {
|
|
21
|
+
process.stdout.write(`✓ ${message}\n`);
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!json) {
|
|
27
|
+
process.stdout.write("○ open-press upgrade\n\n");
|
|
28
|
+
if (before.coreUpdateAvailable) {
|
|
29
|
+
process.stdout.write(
|
|
30
|
+
` @open-press/core: ${before.coreVersion} → ${before.coreLatest}\n`,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (before.pendingMigrations.length > 0) {
|
|
34
|
+
process.stdout.write(` migration notes: ${before.pendingMigrations.join(", ")}\n`);
|
|
35
|
+
}
|
|
36
|
+
process.stdout.write("\n");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (dryRun) {
|
|
40
|
+
if (!json) {
|
|
41
|
+
process.stdout.write("dry run — nothing changed. The agent should:\n");
|
|
42
|
+
process.stdout.write(" 1. read each docs/migrations/<version>.md for document-level changes\n");
|
|
43
|
+
process.stdout.write(" 2. apply edits to document/ where needed\n");
|
|
44
|
+
process.stdout.write(" 3. re-run: npx open-press upgrade (without --dry-run)\n");
|
|
45
|
+
} else {
|
|
46
|
+
process.stdout.write(JSON.stringify({ status: "dry-run", before }, null, 2) + "\n");
|
|
47
|
+
}
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. Refresh framework dep (only when workspace declares @open-press/core).
|
|
52
|
+
if (!skipDeps && (await hasCoreDep(root))) {
|
|
53
|
+
if (!json) process.stdout.write("▸ updating @open-press/core via npm…\n");
|
|
54
|
+
const code = runCommand("npm", ["update", "@open-press/core"], root);
|
|
55
|
+
if (code !== 0) {
|
|
56
|
+
if (!json) process.stdout.write(" ⚠ npm update returned non-zero; continuing\n");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 3. Refresh skills (npx skills upgrade respects skills-lock.json).
|
|
61
|
+
if (!skipSkills) {
|
|
62
|
+
if (!json) process.stdout.write("▸ refreshing skills via npx skills upgrade…\n");
|
|
63
|
+
runCommand("npx", ["-y", "skills@latest", "upgrade"], root);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// 4. Surface migration notes for the agent to read.
|
|
67
|
+
const migrationContents = await loadMigrations(root, before.pendingMigrations);
|
|
68
|
+
|
|
69
|
+
// 5. Re-diagnose to confirm the move.
|
|
70
|
+
const after = await diagnose(root, { noCache: true });
|
|
71
|
+
|
|
72
|
+
if (json) {
|
|
73
|
+
process.stdout.write(
|
|
74
|
+
JSON.stringify(
|
|
75
|
+
{ status: "applied", before, after, migrationContents: migrationContents.map((m) => m.path) },
|
|
76
|
+
null,
|
|
77
|
+
2,
|
|
78
|
+
) + "\n",
|
|
79
|
+
);
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
process.stdout.write("\n✓ upgrade applied. Now read these migration notes:\n\n");
|
|
84
|
+
if (migrationContents.length === 0) {
|
|
85
|
+
process.stdout.write(" (no migration docs in this version range)\n\n");
|
|
86
|
+
} else {
|
|
87
|
+
for (const m of migrationContents) {
|
|
88
|
+
process.stdout.write(` ─ ${m.path}\n`);
|
|
89
|
+
}
|
|
90
|
+
process.stdout.write(
|
|
91
|
+
"\nAgent: open each file, identify document-level changes, grep document/ for affected patterns, propose edits before applying.\n",
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
process.stdout.write("\nVerify with:\n npm run openpress:validate\n npm run openpress:render\n\n");
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function hasCoreDep(root) {
|
|
100
|
+
try {
|
|
101
|
+
const pkg = JSON.parse(await readFile(path.join(root, "package.json"), "utf8"));
|
|
102
|
+
return Boolean(pkg.dependencies?.["@open-press/core"] || pkg.devDependencies?.["@open-press/core"]);
|
|
103
|
+
} catch {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function loadMigrations(root, versions) {
|
|
109
|
+
const results = [];
|
|
110
|
+
for (const v of versions) {
|
|
111
|
+
const p = path.join(root, "docs", "migrations", `${v}.md`);
|
|
112
|
+
if (existsSync(p)) {
|
|
113
|
+
results.push({ version: v, path: path.relative(root, p) });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return results;
|
|
117
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-press/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "open-press core — runtime primitives, CLI, and render pipeline for AI-first fixed-layout documents.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,6 +65,8 @@
|
|
|
65
65
|
"js-yaml": "^4.1.1",
|
|
66
66
|
"katex": "^0.16.47",
|
|
67
67
|
"lucide-react": "^1.16.0",
|
|
68
|
+
"playwright": "^1.60.0",
|
|
69
|
+
"postcss": "^8.5.6",
|
|
68
70
|
"react": "^19.2.6",
|
|
69
71
|
"react-dom": "^19.2.6",
|
|
70
72
|
"rehype-katex": "^7.0.1",
|
|
@@ -9,13 +9,18 @@ import { loadConfig, publicPdfHref } from "./engine/config.mjs";
|
|
|
9
9
|
import { handleCommentRequest } from "./engine/react/comment-endpoint.mjs";
|
|
10
10
|
import { handleProjectAssetRequest } from "./engine/react/project-asset-endpoint.mjs";
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
const workspaceRoot =
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
const frameworkRoot = fileURLToPath(new URL("./", import.meta.url));
|
|
13
|
+
const workspaceRoot = process.env.OPENPRESS_WORKSPACE_ROOT
|
|
14
|
+
? path.resolve(process.env.OPENPRESS_WORKSPACE_ROOT)
|
|
15
|
+
: frameworkRoot;
|
|
16
|
+
const sourceRoot = path.join(frameworkRoot, "src");
|
|
17
|
+
const openpressCliPath = path.join(frameworkRoot, "engine", "cli.mjs");
|
|
18
|
+
const staticServerPath = path.join(frameworkRoot, "engine", "static-server.mjs");
|
|
19
|
+
const openpressCoreEntry = path.join(frameworkRoot, "src", "openpress", "core", "index.tsx");
|
|
16
20
|
const openpressConfig = await loadConfig(workspaceRoot);
|
|
17
21
|
const outputDir = openpressConfig.paths.outputDir;
|
|
18
|
-
const reactDocumentRoot =
|
|
22
|
+
const reactDocumentRoot = openpressConfig.paths.documentRoot;
|
|
23
|
+
const reactDocumentComponentsRoot = openpressConfig.paths.componentsDir;
|
|
19
24
|
const reactDocumentEntry = path.join(reactDocumentRoot, "index.tsx");
|
|
20
25
|
const activeContentDir = await fileExists(reactDocumentEntry)
|
|
21
26
|
? path.join(reactDocumentRoot, "chapters")
|
|
@@ -48,6 +53,7 @@ export default defineConfig({
|
|
|
48
53
|
plugins: [openpressLocalDeployPlugin(), react()],
|
|
49
54
|
define: workspaceDefines,
|
|
50
55
|
resolve: {
|
|
56
|
+
dedupe: ["react", "react-dom", "@mdx-js/react"],
|
|
51
57
|
alias: {
|
|
52
58
|
"@openpress/core": openpressCoreEntry,
|
|
53
59
|
"@/components": reactDocumentComponentsRoot,
|
|
@@ -69,6 +75,9 @@ export default defineConfig({
|
|
|
69
75
|
server: {
|
|
70
76
|
host: "127.0.0.1",
|
|
71
77
|
port: 5173,
|
|
78
|
+
fs: {
|
|
79
|
+
allow: Array.from(new Set([frameworkRoot, workspaceRoot])),
|
|
80
|
+
},
|
|
72
81
|
watch: {
|
|
73
82
|
ignored: ["**/.openpress/tmp/**", `**/${openpressConfig.outputDir}/**`],
|
|
74
83
|
},
|
|
@@ -201,7 +210,7 @@ async function handleLocalPdfExportRequest(req: IncomingMessage, res: ServerResp
|
|
|
201
210
|
ok: result.code === 0 && exists,
|
|
202
211
|
code: result.code,
|
|
203
212
|
pdf: `/__openpress/local-pdf-file?ts=${Date.now()}`,
|
|
204
|
-
command: "
|
|
213
|
+
command: openpressCliCommand(["pdf", "."]),
|
|
205
214
|
stdout: result.stdout,
|
|
206
215
|
stderr: result.stderr,
|
|
207
216
|
});
|
|
@@ -266,7 +275,7 @@ async function handleLocalDeployRequest(req: IncomingMessage, res: ServerRespons
|
|
|
266
275
|
deploy_adapter: openpressConfig.deploy.adapter,
|
|
267
276
|
deploy_source: openpressConfig.deploy.source,
|
|
268
277
|
deploy_project_name: openpressConfig.deploy.projectName,
|
|
269
|
-
command: "
|
|
278
|
+
command: openpressCliCommand(["deploy", ".", "--confirm"]),
|
|
270
279
|
});
|
|
271
280
|
return;
|
|
272
281
|
}
|
|
@@ -285,7 +294,7 @@ async function handleLocalDeployRequest(req: IncomingMessage, res: ServerRespons
|
|
|
285
294
|
pdf: deployedUrl ? `${deployedUrl}/${openpressConfig.pdf.filename}` : deploymentInfo.pdf,
|
|
286
295
|
public_url: publicUrl,
|
|
287
296
|
dirty: false,
|
|
288
|
-
command: "
|
|
297
|
+
command: openpressCliCommand(["deploy", ".", "--confirm"]),
|
|
289
298
|
stdout: result.stdout,
|
|
290
299
|
stderr: result.stderr,
|
|
291
300
|
});
|
|
@@ -293,7 +302,7 @@ async function handleLocalDeployRequest(req: IncomingMessage, res: ServerRespons
|
|
|
293
302
|
|
|
294
303
|
function runLocalPdfExport() {
|
|
295
304
|
return new Promise<{ code: number; stdout: string; stderr: string }>((resolve) => {
|
|
296
|
-
const child = spawn("node", [
|
|
305
|
+
const child = spawn("node", [openpressCliPath, "pdf", "."], {
|
|
297
306
|
cwd: workspaceRoot,
|
|
298
307
|
shell: false,
|
|
299
308
|
});
|
|
@@ -316,7 +325,7 @@ function runLocalPdfExport() {
|
|
|
316
325
|
|
|
317
326
|
function runLocalDeploy() {
|
|
318
327
|
return new Promise<{ code: number; stdout: string; stderr: string }>((resolve) => {
|
|
319
|
-
const child = spawn("node", [
|
|
328
|
+
const child = spawn("node", [openpressCliPath, "deploy", ".", "--confirm"], {
|
|
320
329
|
cwd: workspaceRoot,
|
|
321
330
|
shell: false,
|
|
322
331
|
});
|
|
@@ -405,7 +414,7 @@ function getLocalDeploymentSourcePaths() {
|
|
|
405
414
|
openpressConfig.paths.themeDir,
|
|
406
415
|
openpressConfig.paths.designDoc,
|
|
407
416
|
openpressConfig.paths.componentsDir,
|
|
408
|
-
path.join(
|
|
417
|
+
path.join(frameworkRoot, "src"),
|
|
409
418
|
path.join(workspaceRoot, "index.html"),
|
|
410
419
|
path.join(workspaceRoot, "package.json"),
|
|
411
420
|
path.join(workspaceRoot, "openpress.config.mjs"),
|
|
@@ -414,6 +423,12 @@ function getLocalDeploymentSourcePaths() {
|
|
|
414
423
|
];
|
|
415
424
|
}
|
|
416
425
|
|
|
426
|
+
function openpressCliCommand(args: string[]) {
|
|
427
|
+
const relativeCliPath = path.relative(workspaceRoot, openpressCliPath).replaceAll("\\", "/");
|
|
428
|
+
const displayCliPath = relativeCliPath && !relativeCliPath.startsWith("../") ? relativeCliPath : openpressCliPath;
|
|
429
|
+
return `node ${displayCliPath} ${args.join(" ")}`;
|
|
430
|
+
}
|
|
431
|
+
|
|
417
432
|
async function findNewestLocalSourceMtime(paths: string[]) {
|
|
418
433
|
const times = await Promise.all(paths.map((sourcePath) => findNewestLocalMtime(sourcePath)));
|
|
419
434
|
return Math.max(0, ...times);
|
package/template/packs/academic-paper/document/chapters/01-introduction/content/01-introduction.mdx
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Introduction
|
|
2
|
+
|
|
3
|
+
This document is a model and starting point for an academic paper drafted in open-press. The structure follows the IEEE conference template conventions where they make sense for screen-first reading: numbered sections, italic sub-sections, an abstract block, and a numbered references list. The two-column body of IEEEtran is not yet supported — single-column will land as the v0.8 paged.js migration arrives.
|
|
4
|
+
|
|
5
|
+
Use this pack for **drafting, iteration, and preprint distribution**. When the paper is ready for venue submission, export the prose into the publisher's required LaTeX class (`IEEEtran`, `acmart`, etc.). The pack does not replace LaTeX for camera-ready submission; it replaces the awkward iteration loop *before* submission.
|
|
6
|
+
|
|
7
|
+
### Where to start
|
|
8
|
+
|
|
9
|
+
Each chapter directory under `document/chapters/` is one paper section:
|
|
10
|
+
|
|
11
|
+
- `01-introduction/` — motivate the work, state the contribution, summarise the structure.
|
|
12
|
+
- `02-methods/` — describe what you did, with enough detail to reproduce.
|
|
13
|
+
- `03-results-and-discussion/` — present results with figures and tables; interpret what they mean.
|
|
14
|
+
- `04-acknowledgment/` — acknowledge funding, collaborators, reviewers.
|
|
15
|
+
- `05-references/` — numbered `[1]`, `[2]` references.
|
|
16
|
+
|
|
17
|
+
Replace each chapter's MDX content with your own. The skeleton text below each `##` heading is illustrative — overwrite it.
|
|
18
|
+
|
|
19
|
+
### Abstract and Index Terms
|
|
20
|
+
|
|
21
|
+
Edit the abstract and index terms inside `document/index.tsx` (the `cover` JSX export). They render on the title page above the body. Keep the abstract under 250 words and avoid abbreviations, symbols, or math in it.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Methods
|
|
2
|
+
|
|
3
|
+
Describe the materials, instruments, datasets, models, or procedures you used. Anyone familiar with the field should be able to reproduce your work from this section.
|
|
4
|
+
|
|
5
|
+
### Apparatus and Materials
|
|
6
|
+
|
|
7
|
+
Specify hardware, software versions, datasets, and any pre-processing. Cite reused work using `[N]` numeric references (e.g. "we trained the encoder following the procedure of [3]").
|
|
8
|
+
|
|
9
|
+
### Procedure
|
|
10
|
+
|
|
11
|
+
Describe the experimental procedure as steps a reader could follow:
|
|
12
|
+
|
|
13
|
+
1. State the input data and pre-processing.
|
|
14
|
+
2. State the model / algorithm / instrument settings.
|
|
15
|
+
3. State the evaluation metric(s) and any held-out splits.
|
|
16
|
+
4. State randomness control (seeds, repeats, confidence reporting).
|
|
17
|
+
|
|
18
|
+
### Notation
|
|
19
|
+
|
|
20
|
+
Define notation early. Italicise Roman symbols for quantities and variables, but not Greek symbols. Use a long dash rather than a hyphen for a minus sign. Number equations consecutively:
|
|
21
|
+
|
|
22
|
+
$$a + b = \gamma \tag{1}$$
|
|
23
|
+
|
|
24
|
+
Refer to equations by `(1)`, not `Eq. (1)` or `equation (1)`, except at the start of a sentence: "Equation (1) shows ...".
|
|
25
|
+
|
|
26
|
+
### Reporting Units
|
|
27
|
+
|
|
28
|
+
- Use SI (MKS) as primary units; English units only as secondary (in parentheses).
|
|
29
|
+
- Don't mix complete spellings and abbreviations: "Wb/m²" or "webers per square meter", not "webers/m²".
|
|
30
|
+
- Use a zero before decimal points: `0.25`, not `.25`.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
## Results and Discussion
|
|
2
|
+
|
|
3
|
+
Present the findings of your study, then interpret what they mean for the research question stated in the introduction.
|
|
4
|
+
|
|
5
|
+
### Quantitative Results
|
|
6
|
+
|
|
7
|
+
Use a table to summarise results across conditions. Caption above the table.
|
|
8
|
+
|
|
9
|
+
<TableCaption>Sample comparison of conditions.</TableCaption>
|
|
10
|
+
|
|
11
|
+
| Condition | Metric A | Metric B | Notes |
|
|
12
|
+
| --- | --- | --- | --- |
|
|
13
|
+
| Baseline | 0.71 | 0.65 | Prior work [3] |
|
|
14
|
+
| Ours (v1) | 0.78 | 0.69 | This work |
|
|
15
|
+
| Ours (v2) | **0.83** | **0.72** | Best |
|
|
16
|
+
|
|
17
|
+
Cite figures and tables in the text the first time they appear: "Fig. 1 shows the architecture", "Table I summarises the conditions". Use `Fig.` even at the start of a sentence; spell out `Figure` only when it is the subject.
|
|
18
|
+
|
|
19
|
+
### Qualitative Discussion
|
|
20
|
+
|
|
21
|
+
Discuss what the results mean. State the limitations honestly — if the experiment doesn't cover a case you'd like to claim, say so. Avoid the word "essentially" when you mean "approximately" or "effectively".
|
|
22
|
+
|
|
23
|
+
### Threats to Validity
|
|
24
|
+
|
|
25
|
+
Briefly list what could invalidate the results: small sample size, single dataset, environmental drift, evaluator bias, etc. Reviewers will look for this section; pre-empt it.
|
|
26
|
+
|
|
27
|
+
### Future Work
|
|
28
|
+
|
|
29
|
+
Indicate where the work goes next. Keep this to one short paragraph — over-claiming future scope hurts more than it helps in review.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
## Acknowledgment
|
|
2
|
+
|
|
3
|
+
The preferred American spelling is *acknowledgment* without an "e" after the "g". Avoid stilted constructions like "one of us (R. B. G.) thanks ...". Prefer "R. B. G. thanks ...".
|
|
4
|
+
|
|
5
|
+
Acknowledge:
|
|
6
|
+
|
|
7
|
+
- Funding sources (with grant numbers if applicable).
|
|
8
|
+
- Collaborators who contributed materially but are not listed as authors.
|
|
9
|
+
- Anonymous reviewers whose comments improved the paper.
|
|
10
|
+
- Institutional or computational resources.
|
|
11
|
+
|
|
12
|
+
Place sponsor acknowledgments in the unnumbered footnote on the first page of the published version. In this draft pack, keep them here until you migrate to a publisher's class file at submission time.
|
package/template/packs/academic-paper/document/chapters/05-references/content/01-references.mdx
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## References
|
|
2
|
+
|
|
3
|
+
Number citations consecutively within square brackets `[1]`. Sentence punctuation follows the bracket. Refer simply to the reference number, as in `[3]` — do not use `Ref. [3]` or `reference [3]` except at the start of a sentence: "Reference [3] was the first ...".
|
|
4
|
+
|
|
5
|
+
Unless there are six authors or more, give all authors' names; do not use `et al.`. Papers not yet published should be cited as *unpublished*; accepted but not yet published as *in press*. Capitalize only the first word in a paper title, except for proper nouns and element symbols.
|
|
6
|
+
|
|
7
|
+
For papers published in translation journals, give the English citation first, followed by the original foreign-language citation.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
[1] G. Eason, B. Noble, and I. N. Sneddon, "On certain integrals of Lipschitz–Hankel type involving products of Bessel functions," *Phil. Trans. Roy. Soc. London*, vol. A247, pp. 529–551, April 1955.
|
|
12
|
+
|
|
13
|
+
[2] J. Clerk Maxwell, *A Treatise on Electricity and Magnetism*, 3rd ed., vol. 2. Oxford: Clarendon, 1892, pp. 68–73.
|
|
14
|
+
|
|
15
|
+
[3] I. S. Jacobs and C. P. Bean, "Fine particles, thin films and exchange anisotropy," in *Magnetism*, vol. III, G. T. Rado and H. Suhl, Eds. New York: Academic, 1963, pp. 271–350.
|
|
16
|
+
|
|
17
|
+
[4] K. Elissa, "Title of paper if known," unpublished.
|
|
18
|
+
|
|
19
|
+
[5] R. Nicole, "Title of paper with only first word capitalized," *J. Name Stand. Abbrev.*, in press.
|
|
20
|
+
|
|
21
|
+
[6] Y. Yorozu, M. Hirano, K. Oka, and Y. Tagawa, "Electron spectroscopy studies on magneto-optical media and plastic substrate interface," *IEEE Transl. J. Magn. Japan*, vol. 2, pp. 740–741, August 1987.
|
|
22
|
+
|
|
23
|
+
[7] M. Young, *The Technical Writer's Handbook*. Mill Valley, CA: University Science, 1989.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
> **Reminder**: replace the seven placeholder references above with your own bibliography before circulating the draft. They are the IEEE conference template's example citations and have nothing to do with your paper.
|