@open-press/cli 0.8.0 → 1.0.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 +25 -14
- package/dist/cli.js +44 -195
- package/package.json +4 -5
- package/template/core/AGENTS.md +18 -14
- package/template/core/CHANGELOG.md +12 -9
- package/template/core/README.md +6 -3
- package/template/core/engine/cli.mjs +8 -8
- package/template/core/engine/commands/_shared.mjs +37 -15
- package/template/core/engine/commands/image.mjs +29 -0
- package/template/core/engine/commands/skills-sync.mjs +71 -0
- package/template/core/engine/commands/typecheck.mjs +63 -1
- package/template/core/engine/commands/upgrade.mjs +3 -3
- package/template/core/engine/document-export.mjs +1 -1
- package/template/core/engine/output/chrome-pdf.mjs +92 -0
- package/template/core/engine/output/static-server.mjs +48 -9
- package/template/core/engine/react/comment-marker.mjs +13 -13
- package/template/core/engine/react/document-entry.mjs +35 -28
- package/template/core/engine/react/document-export.mjs +309 -170
- package/template/core/engine/react/mdx-compile.mjs +30 -0
- package/template/core/engine/react/measurement-css.mjs +21 -0
- package/template/core/engine/react/object-entities.mjs +85 -0
- package/template/core/engine/react/pagination/allocator.mjs +48 -3
- package/template/core/engine/react/pagination.mjs +1 -1
- package/template/core/engine/react/pipeline/allocate.mjs +31 -65
- package/template/core/engine/react/pipeline/frame-measurement.mjs +4 -0
- package/template/core/engine/react/press-tree-inspection.mjs +172 -0
- package/template/core/engine/react/sources/mdx-resolver.mjs +1 -1
- package/template/core/engine/react/style-discovery.mjs +22 -4
- package/template/core/engine/runtime/config.d.mts +8 -0
- package/template/core/engine/runtime/config.mjs +57 -60
- package/template/core/engine/runtime/file-utils.mjs +9 -1
- package/template/core/engine/runtime/page-geometry.mjs +131 -0
- package/template/core/engine/runtime/source-text-tools.mjs +1 -1
- package/template/core/engine/runtime/source-workspace.mjs +12 -3
- package/template/core/engine/runtime/validation.mjs +19 -10
- package/template/core/openpress.config.mjs +3 -7
- package/template/core/package.json +3 -5
- package/template/core/src/openpress/app/OpenPressApp.tsx +173 -17
- package/template/core/src/openpress/app/OpenPressRuntime.tsx +10 -2
- package/template/core/src/openpress/app/WorkspaceGalleryPage.tsx +219 -0
- package/template/core/src/openpress/core/Frame.tsx +20 -7
- package/template/core/src/openpress/core/FrameContext.tsx +2 -0
- package/template/core/src/openpress/core/Press.tsx +25 -4
- package/template/core/src/openpress/core/Workspace.tsx +36 -0
- package/template/core/src/openpress/core/index.tsx +10 -3
- package/template/core/src/openpress/core/primitives.tsx +48 -1
- package/template/core/src/openpress/core/types.ts +86 -41
- package/template/core/src/openpress/core/useSource.ts +1 -1
- package/template/core/src/openpress/document-model/documentTypes.ts +9 -0
- package/template/core/src/openpress/document-model/index.ts +1 -0
- package/template/core/src/openpress/document-model/objectEntityModel.ts +4 -0
- package/template/core/src/openpress/document-model/workspaceManifestModel.ts +57 -0
- package/template/core/src/openpress/mdx/index.ts +15 -7
- package/template/core/src/openpress/reader/PageThumbnailsPanel.tsx +168 -0
- package/template/core/src/openpress/reader/index.ts +1 -0
- package/template/core/src/openpress/workbench/Workbench.tsx +120 -21
- package/template/core/src/openpress/workbench/actions/ExportImageControl.tsx +96 -0
- package/template/core/src/openpress/workbench/actions/SearchControl.tsx +3 -3
- package/template/core/src/openpress/workbench/actions/index.ts +1 -0
- package/template/core/src/openpress/workbench/inspector/useInspectorComments.ts +7 -1
- package/template/core/src/openpress/workbench/panels/PendingCommentsPanel.tsx +5 -1
- package/template/core/src/openpress/workbench/project/ProjectEntryPanel.tsx +4 -2
- package/template/core/src/openpress/workbench/workbenchFormatters.ts +2 -2
- package/template/core/src/styles/openpress/reader-runtime.css +9 -0
- package/template/core/src/styles/openpress/workbench-panels.css +113 -0
- package/template/core/src/styles/openpress/workspace-gallery.css +300 -0
- package/template/core/src/styles/openpress.css +1 -0
- package/template/core/tsconfig.json +1 -1
- package/template/core/engine/commands/init.mjs +0 -24
- package/template/core/engine/init.mjs +0 -90
- package/template/packs/academic-paper/document/chapters/01-introduction/content/01-introduction.mdx +0 -35
- package/template/packs/academic-paper/document/chapters/02-methods/content/01-methods.mdx +0 -50
- package/template/packs/academic-paper/document/chapters/03-results-and-discussion/content/01-results.mdx +0 -47
- package/template/packs/academic-paper/document/chapters/04-acknowledgment/content/01-acknowledgment.mdx +0 -26
- package/template/packs/academic-paper/document/chapters/05-references/content/01-references.mdx +0 -32
- package/template/packs/academic-paper/document/components/ChapterOpenerVisual/index.tsx +0 -76
- package/template/packs/academic-paper/document/components/Page.tsx +0 -60
- package/template/packs/academic-paper/document/components/TokenSwatchGrid/index.tsx +0 -46
- package/template/packs/academic-paper/document/components/TokenSwatchGrid/style.css +0 -63
- package/template/packs/academic-paper/document/components/TypeSpecimen/index.tsx +0 -38
- package/template/packs/academic-paper/document/components/TypeSpecimen/style.css +0 -111
- package/template/packs/academic-paper/document/design.md +0 -279
- package/template/packs/academic-paper/document/index.tsx +0 -123
- package/template/packs/academic-paper/document/media/README.md +0 -13
- package/template/packs/academic-paper/document/media/figure-placeholder.svg +0 -9
- package/template/packs/academic-paper/document/openpress.config.mjs +0 -26
- package/template/packs/academic-paper/document/theme/README.md +0 -11
- package/template/packs/academic-paper/document/theme/base/page-contract.css +0 -522
- package/template/packs/academic-paper/document/theme/base/print.css +0 -93
- package/template/packs/academic-paper/document/theme/base/typography.css +0 -333
- package/template/packs/academic-paper/document/theme/fonts.css +0 -3
- package/template/packs/academic-paper/document/theme/page-surfaces/back-cover.css +0 -43
- package/template/packs/academic-paper/document/theme/page-surfaces/chapter-opener.css +0 -205
- package/template/packs/academic-paper/document/theme/page-surfaces/cover.css +0 -294
- package/template/packs/academic-paper/document/theme/page-surfaces/toc.css +0 -149
- package/template/packs/academic-paper/document/theme/patterns/_chart-frame.css +0 -49
- package/template/packs/academic-paper/document/theme/patterns/figure-grid.css +0 -68
- package/template/packs/academic-paper/document/theme/patterns/table-utilities.css +0 -66
- package/template/packs/academic-paper/document/theme/shell/reader-controls.css +0 -761
- package/template/packs/academic-paper/document/theme/tokens.css +0 -80
- package/template/packs/academic-paper/openpress.config.mjs +0 -5
- package/template/packs/claude-document/document/chapters/01-document-shape/content/01-document-shape.mdx +0 -51
- package/template/packs/claude-document/document/chapters/02-review-loop/content/01-review-loop.mdx +0 -31
- package/template/packs/claude-document/document/components/ChapterOpenerVisual.tsx +0 -96
- package/template/packs/claude-document/document/components/Page.tsx +0 -37
- package/template/packs/claude-document/document/design.md +0 -142
- package/template/packs/claude-document/document/index.tsx +0 -94
- package/template/packs/claude-document/document/media/README.md +0 -13
- package/template/packs/claude-document/document/openpress.config.mjs +0 -26
- package/template/packs/claude-document/document/theme/README.md +0 -15
- package/template/packs/claude-document/document/theme/base/page-contract.css +0 -525
- package/template/packs/claude-document/document/theme/base/print.css +0 -93
- package/template/packs/claude-document/document/theme/base/typography.css +0 -612
- package/template/packs/claude-document/document/theme/fonts.css +0 -4
- package/template/packs/claude-document/document/theme/page-surfaces/back-cover.css +0 -72
- package/template/packs/claude-document/document/theme/page-surfaces/chapter-opener.css +0 -236
- package/template/packs/claude-document/document/theme/page-surfaces/cover.css +0 -309
- package/template/packs/claude-document/document/theme/page-surfaces/toc.css +0 -225
- package/template/packs/claude-document/document/theme/patterns/_chart-frame.css +0 -53
- package/template/packs/claude-document/document/theme/patterns/figure-grid.css +0 -68
- package/template/packs/claude-document/document/theme/patterns/table-utilities.css +0 -66
- package/template/packs/claude-document/document/theme/shell/reader-controls.css +0 -789
- package/template/packs/claude-document/document/theme/tokens.css +0 -89
- package/template/packs/claude-document/openpress.config.mjs +0 -5
- package/template/packs/editorial-monograph/document/chapters/01-product-and-use-cases/content/01-product-and-use-cases.mdx +0 -31
- package/template/packs/editorial-monograph/document/chapters/02-workflow/content/01-workflow.mdx +0 -89
- package/template/packs/editorial-monograph/document/chapters/03-agent-skills-contributors/content/01-agent-skills-contributors.mdx +0 -51
- package/template/packs/editorial-monograph/document/chapters/04-validation-deploy/content/01-validation-deploy.mdx +0 -39
- package/template/packs/editorial-monograph/document/components/ChapterOpenerVisual/index.tsx +0 -76
- package/template/packs/editorial-monograph/document/components/Page.tsx +0 -37
- package/template/packs/editorial-monograph/document/components/TokenSwatchGrid/index.tsx +0 -46
- package/template/packs/editorial-monograph/document/components/TokenSwatchGrid/style.css +0 -63
- package/template/packs/editorial-monograph/document/components/TypeSpecimen/index.tsx +0 -38
- package/template/packs/editorial-monograph/document/components/TypeSpecimen/style.css +0 -111
- package/template/packs/editorial-monograph/document/design.md +0 -279
- package/template/packs/editorial-monograph/document/index.tsx +0 -97
- package/template/packs/editorial-monograph/document/media/README.md +0 -13
- package/template/packs/editorial-monograph/document/openpress.config.mjs +0 -26
- package/template/packs/editorial-monograph/document/theme/README.md +0 -11
- package/template/packs/editorial-monograph/document/theme/base/page-contract.css +0 -505
- package/template/packs/editorial-monograph/document/theme/base/print.css +0 -93
- package/template/packs/editorial-monograph/document/theme/base/typography.css +0 -336
- package/template/packs/editorial-monograph/document/theme/fonts.css +0 -3
- package/template/packs/editorial-monograph/document/theme/page-surfaces/back-cover.css +0 -43
- package/template/packs/editorial-monograph/document/theme/page-surfaces/chapter-opener.css +0 -205
- package/template/packs/editorial-monograph/document/theme/page-surfaces/cover.css +0 -147
- package/template/packs/editorial-monograph/document/theme/page-surfaces/toc.css +0 -149
- package/template/packs/editorial-monograph/document/theme/patterns/_chart-frame.css +0 -49
- package/template/packs/editorial-monograph/document/theme/patterns/figure-grid.css +0 -68
- package/template/packs/editorial-monograph/document/theme/patterns/table-utilities.css +0 -66
- package/template/packs/editorial-monograph/document/theme/shell/reader-controls.css +0 -761
- package/template/packs/editorial-monograph/document/theme/tokens.css +0 -80
- package/template/packs/editorial-monograph/openpress.config.mjs +0 -5
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
const TONES = new Set(["sage", "lavender", "mint", "amber"]);
|
|
2
|
-
|
|
3
|
-
const VISUALS = {
|
|
4
|
-
"linked-list": `<svg viewBox="0 0 520 330" focusable="false" aria-hidden="true">
|
|
5
|
-
<rect class="chapter-opener-illustration__paper" x="42" y="96" width="116" height="82" rx="4" />
|
|
6
|
-
<rect class="chapter-opener-illustration__paper" x="204" y="96" width="116" height="82" rx="4" />
|
|
7
|
-
<rect class="chapter-opener-illustration__paper" x="366" y="96" width="116" height="82" rx="4" />
|
|
8
|
-
<path class="chapter-opener-illustration__stroke" d="M158 137 H204" />
|
|
9
|
-
<path class="chapter-opener-illustration__stroke" d="M320 137 H366" />
|
|
10
|
-
<path class="chapter-opener-illustration__arrow" d="M190 122 206 137 190 152" />
|
|
11
|
-
<path class="chapter-opener-illustration__arrow" d="M352 122 368 137 352 152" />
|
|
12
|
-
<path class="chapter-opener-illustration__thin" d="M72 128 H118 M72 150 H128 M234 128 H280 M234 150 H286 M396 128 H442 M396 150 H452" />
|
|
13
|
-
<circle class="chapter-opener-illustration__node" cx="144" cy="137" r="13" />
|
|
14
|
-
<circle class="chapter-opener-illustration__node" cx="306" cy="137" r="13" />
|
|
15
|
-
<circle class="chapter-opener-illustration__node" cx="468" cy="137" r="13" />
|
|
16
|
-
<path class="chapter-opener-illustration__stroke" d="M262 178 C262 222 220 244 158 244 C98 244 68 222 68 190" />
|
|
17
|
-
<path class="chapter-opener-illustration__arrow" d="M52 204 68 188 84 204" />
|
|
18
|
-
</svg>`,
|
|
19
|
-
tree: `<svg viewBox="0 0 520 330" focusable="false" aria-hidden="true">
|
|
20
|
-
<path class="chapter-opener-illustration__paper" d="M232 40 316 40 352 86 330 132 218 132 194 86Z" />
|
|
21
|
-
<path class="chapter-opener-illustration__paper" d="M88 198 170 178 228 218 204 288 100 288 58 240Z" />
|
|
22
|
-
<path class="chapter-opener-illustration__paper" d="M314 198 400 176 466 224 450 292 328 292 282 238Z" />
|
|
23
|
-
<path class="chapter-opener-illustration__stroke" d="M262 118 160 214 M270 118 374 214" />
|
|
24
|
-
<path class="chapter-opener-illustration__stroke" d="M160 214 122 258 M160 214 204 258 M374 214 330 258 M374 214 420 258" />
|
|
25
|
-
<circle class="chapter-opener-illustration__node" cx="266" cy="100" r="24" />
|
|
26
|
-
<circle class="chapter-opener-illustration__node" cx="160" cy="214" r="22" />
|
|
27
|
-
<circle class="chapter-opener-illustration__node" cx="374" cy="214" r="22" />
|
|
28
|
-
<circle class="chapter-opener-illustration__dot" cx="122" cy="258" r="13" />
|
|
29
|
-
<circle class="chapter-opener-illustration__dot" cx="204" cy="258" r="13" />
|
|
30
|
-
<circle class="chapter-opener-illustration__dot" cx="330" cy="258" r="13" />
|
|
31
|
-
<circle class="chapter-opener-illustration__dot" cx="420" cy="258" r="13" />
|
|
32
|
-
</svg>`,
|
|
33
|
-
code: `<svg viewBox="0 0 520 330" focusable="false" aria-hidden="true">
|
|
34
|
-
<path class="chapter-opener-illustration__paper" d="M92 52 338 52 386 104 386 286 92 286Z" />
|
|
35
|
-
<path class="chapter-opener-illustration__paper" d="M348 82 438 82 476 122 452 226 356 226 326 154Z" />
|
|
36
|
-
<path class="chapter-opener-illustration__thin" d="M132 112 H250 M132 146 H292 M132 180 H238 M132 214 H276" />
|
|
37
|
-
<path class="chapter-opener-illustration__stroke" d="M308 114 C340 122 356 148 356 180 C356 220 332 244 292 250" />
|
|
38
|
-
<path class="chapter-opener-illustration__arrow" d="M304 226 288 250 316 260" />
|
|
39
|
-
<path class="chapter-opener-illustration__stroke" d="M406 124 V202" />
|
|
40
|
-
<circle class="chapter-opener-illustration__node" cx="406" cy="124" r="17" />
|
|
41
|
-
<circle class="chapter-opener-illustration__node" cx="406" cy="202" r="17" />
|
|
42
|
-
</svg>`,
|
|
43
|
-
answers: `<svg viewBox="0 0 520 330" focusable="false" aria-hidden="true">
|
|
44
|
-
<path class="chapter-opener-illustration__paper" d="M128 44 396 44 440 90 418 292 104 292 82 86Z" />
|
|
45
|
-
<path class="chapter-opener-illustration__thin" d="M178 116 H350 M178 168 H350 M178 220 H322" />
|
|
46
|
-
<path class="chapter-opener-illustration__stroke" d="M128 112 148 134 190 88" />
|
|
47
|
-
<path class="chapter-opener-illustration__stroke" d="M128 164 148 186 190 140" />
|
|
48
|
-
<path class="chapter-opener-illustration__stroke" d="M128 216 148 238 190 192" />
|
|
49
|
-
<circle class="chapter-opener-illustration__node" cx="386" cy="92" r="18" />
|
|
50
|
-
<path class="chapter-opener-illustration__stroke" d="M386 92 C420 126 424 172 394 208" />
|
|
51
|
-
<path class="chapter-opener-illustration__arrow" d="M380 186 394 210 420 200" />
|
|
52
|
-
</svg>`,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export type ChapterOpenerVisualVariant = keyof typeof VISUALS;
|
|
56
|
-
|
|
57
|
-
export interface ChapterOpenerVisualProps {
|
|
58
|
-
variant?: ChapterOpenerVisualVariant;
|
|
59
|
-
tone?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export default function ChapterOpenerVisual({
|
|
63
|
-
variant = "linked-list",
|
|
64
|
-
tone = "sage",
|
|
65
|
-
}: ChapterOpenerVisualProps) {
|
|
66
|
-
const visual = VISUALS[variant] ?? VISUALS["linked-list"];
|
|
67
|
-
const safeTone = TONES.has(tone) ? tone : "sage";
|
|
68
|
-
|
|
69
|
-
return (
|
|
70
|
-
<figure
|
|
71
|
-
className={`chapter-opener-illustration chapter-opener-illustration--${variant} chapter-opener-tone--${safeTone}`}
|
|
72
|
-
aria-hidden="true"
|
|
73
|
-
dangerouslySetInnerHTML={{ __html: visual }}
|
|
74
|
-
/>
|
|
75
|
-
);
|
|
76
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { Frame, MdxArea } from "@open-press/core";
|
|
2
|
-
import type { SectionsPageProps } from "@open-press/core/manuscript";
|
|
3
|
-
import { useEffect, useRef } from "react";
|
|
4
|
-
|
|
5
|
-
export default function Page({
|
|
6
|
-
frameKey,
|
|
7
|
-
chainId,
|
|
8
|
-
pageIndex,
|
|
9
|
-
totalPages,
|
|
10
|
-
sectionSlug,
|
|
11
|
-
sectionTitle,
|
|
12
|
-
sectionTone,
|
|
13
|
-
}: SectionsPageProps) {
|
|
14
|
-
const pageBodyRef = useRef<HTMLElement | null>(null);
|
|
15
|
-
|
|
16
|
-
const runningHeader =
|
|
17
|
-
"This is a non-peer reviewed Express letter submitted to J SEDI";
|
|
18
|
-
const runningRight = "Your short title goes here";
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
const area = pageBodyRef.current?.querySelector(".openpress-mdx-area");
|
|
22
|
-
if (!area) return;
|
|
23
|
-
|
|
24
|
-
area.querySelectorAll<HTMLElement>("h2[data-chapter]").forEach((heading) => {
|
|
25
|
-
const chapterValue = heading.getAttribute("data-chapter");
|
|
26
|
-
if (!chapterValue) return;
|
|
27
|
-
if (!/^\d+$/.test(chapterValue)) return;
|
|
28
|
-
const normalized = String(Number.parseInt(chapterValue, 10));
|
|
29
|
-
heading.setAttribute("data-chapter", normalized);
|
|
30
|
-
});
|
|
31
|
-
}, [chainId]);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<Frame
|
|
35
|
-
frameKey={frameKey}
|
|
36
|
-
role="manuscript.content"
|
|
37
|
-
className="reader-page--content"
|
|
38
|
-
data-page-index={pageIndex}
|
|
39
|
-
data-total-pages={totalPages}
|
|
40
|
-
data-section-id={sectionSlug}
|
|
41
|
-
data-chapter-tone={sectionTone}
|
|
42
|
-
>
|
|
43
|
-
<div className="page-frame">
|
|
44
|
-
<header className="page-header" aria-hidden="true">
|
|
45
|
-
<span className="running-head-left">{runningHeader}</span>
|
|
46
|
-
<span className="running-head-right">{runningRight}</span>
|
|
47
|
-
</header>
|
|
48
|
-
<main className="page-body" ref={pageBodyRef}>
|
|
49
|
-
<MdxArea chainId={chainId} overflow="extend" />
|
|
50
|
-
</main>
|
|
51
|
-
<footer className="page-footer" aria-hidden="true">
|
|
52
|
-
<span className="footer-left">{sectionTitle}</span>
|
|
53
|
-
<span className="footer-right">
|
|
54
|
-
{totalPages > 1 ? `${pageIndex + 1}/${totalPages}` : pageIndex + 1}
|
|
55
|
-
</span>
|
|
56
|
-
</footer>
|
|
57
|
-
</div>
|
|
58
|
-
</Frame>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { CSSProperties } from "react";
|
|
2
|
-
|
|
3
|
-
export interface TokenSwatch {
|
|
4
|
-
name: string;
|
|
5
|
-
hex: string;
|
|
6
|
-
summary: string;
|
|
7
|
-
swatchVar: string;
|
|
8
|
-
swatchBorderVar?: string;
|
|
9
|
-
dark?: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface TokenSwatchGridProps {
|
|
13
|
-
ariaLabel?: string;
|
|
14
|
-
swatches: TokenSwatch[];
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default function TokenSwatchGrid({
|
|
18
|
-
ariaLabel = "Color specimen",
|
|
19
|
-
swatches,
|
|
20
|
-
}: TokenSwatchGridProps) {
|
|
21
|
-
return (
|
|
22
|
-
<section className="token-swatch-grid" data-openpress-component="TokenSwatchGrid" aria-label={ariaLabel}>
|
|
23
|
-
{swatches.map((swatch) => (
|
|
24
|
-
<article
|
|
25
|
-
key={swatch.name}
|
|
26
|
-
className={swatch.dark ? "token-swatch token-swatch--dark" : "token-swatch"}
|
|
27
|
-
style={swatchStyle(swatch)}
|
|
28
|
-
>
|
|
29
|
-
<div className="token-swatch__sample" />
|
|
30
|
-
<div className="token-swatch__body">
|
|
31
|
-
<h4>{swatch.name}</h4>
|
|
32
|
-
<code>{swatch.hex}</code>
|
|
33
|
-
<p>{swatch.summary}</p>
|
|
34
|
-
</div>
|
|
35
|
-
</article>
|
|
36
|
-
))}
|
|
37
|
-
</section>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function swatchStyle(swatch: TokenSwatch): CSSProperties {
|
|
42
|
-
return {
|
|
43
|
-
"--swatch": swatch.swatchVar,
|
|
44
|
-
...(swatch.swatchBorderVar ? { "--swatch-border": swatch.swatchBorderVar } : {}),
|
|
45
|
-
} as CSSProperties;
|
|
46
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
/* token-swatch-grid
|
|
2
|
-
* Color specimen grid referenced by design.md to display each color token with
|
|
3
|
-
* its sample, hex, and usage note.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
.token-swatch-grid {
|
|
7
|
-
display: grid;
|
|
8
|
-
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
9
|
-
gap: 3mm;
|
|
10
|
-
margin: var(--openpress-space-3) 0 var(--openpress-space-4);
|
|
11
|
-
break-inside: avoid;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.token-swatch {
|
|
15
|
-
min-height: 42mm;
|
|
16
|
-
overflow: hidden;
|
|
17
|
-
border: 1px solid var(--openpress-color-line);
|
|
18
|
-
border-radius: 6px;
|
|
19
|
-
background: var(--openpress-color-document);
|
|
20
|
-
box-sizing: border-box;
|
|
21
|
-
break-inside: avoid;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.token-swatch__sample {
|
|
25
|
-
height: 17mm;
|
|
26
|
-
background: var(--swatch);
|
|
27
|
-
border-bottom: 1px solid var(--swatch-border, var(--openpress-color-line));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
.token-swatch__body {
|
|
31
|
-
padding: 3mm;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.token-swatch h4 {
|
|
35
|
-
margin: 0;
|
|
36
|
-
color: var(--openpress-color-ink);
|
|
37
|
-
font-family: var(--openpress-font-body);
|
|
38
|
-
font-size: 9pt;
|
|
39
|
-
font-weight: 600;
|
|
40
|
-
line-height: 1.25;
|
|
41
|
-
letter-spacing: 0;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.token-swatch code {
|
|
45
|
-
display: block;
|
|
46
|
-
margin-top: 1mm;
|
|
47
|
-
color: var(--openpress-color-muted);
|
|
48
|
-
font-size: 8pt;
|
|
49
|
-
line-height: 1.35;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.token-swatch p {
|
|
53
|
-
margin: 2mm 0 0;
|
|
54
|
-
color: #333333;
|
|
55
|
-
font-size: 8.4pt;
|
|
56
|
-
line-height: 1.45;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
@media (max-width: 899px) {
|
|
60
|
-
.token-swatch-grid {
|
|
61
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export type TypeSpecimenVariant =
|
|
2
|
-
| "metric"
|
|
3
|
-
| "cover-title"
|
|
4
|
-
| "chapter-title"
|
|
5
|
-
| "section-title"
|
|
6
|
-
| "body"
|
|
7
|
-
| "caption";
|
|
8
|
-
|
|
9
|
-
export interface TypeSpecimenRow {
|
|
10
|
-
name: string;
|
|
11
|
-
spec: string;
|
|
12
|
-
sample: string;
|
|
13
|
-
sampleVariant: TypeSpecimenVariant;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface TypeSpecimenProps {
|
|
17
|
-
ariaLabel?: string;
|
|
18
|
-
rows: TypeSpecimenRow[];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default function TypeSpecimen({
|
|
22
|
-
ariaLabel = "Typography specimen",
|
|
23
|
-
rows,
|
|
24
|
-
}: TypeSpecimenProps) {
|
|
25
|
-
return (
|
|
26
|
-
<section className="type-specimen" data-openpress-component="TypeSpecimen" aria-label={ariaLabel}>
|
|
27
|
-
{rows.map((row) => (
|
|
28
|
-
<div className="type-specimen__row" key={row.name}>
|
|
29
|
-
<div className="type-specimen__meta">
|
|
30
|
-
<strong>{row.name}</strong>
|
|
31
|
-
<span>{row.spec}</span>
|
|
32
|
-
</div>
|
|
33
|
-
<p className={`type-specimen__sample type-specimen__sample--${row.sampleVariant}`}>{row.sample}</p>
|
|
34
|
-
</div>
|
|
35
|
-
))}
|
|
36
|
-
</section>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/* type-specimen
|
|
2
|
-
* Typography specimen block referenced by design.md to display each typography
|
|
3
|
-
* token alongside a sample in document context.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
.type-specimen {
|
|
7
|
-
margin: var(--openpress-space-3) 0 var(--openpress-space-4);
|
|
8
|
-
border-top: 1px solid var(--openpress-color-line);
|
|
9
|
-
break-inside: avoid;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.type-specimen__row {
|
|
13
|
-
display: grid;
|
|
14
|
-
grid-template-columns: minmax(30mm, 38mm) minmax(0, 1fr);
|
|
15
|
-
gap: var(--openpress-space-3);
|
|
16
|
-
align-items: center;
|
|
17
|
-
min-height: 20mm;
|
|
18
|
-
padding: 3mm 0;
|
|
19
|
-
border-bottom: 1px solid var(--openpress-color-line);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.type-specimen__meta strong {
|
|
23
|
-
display: block;
|
|
24
|
-
font-size: 8.8pt;
|
|
25
|
-
font-weight: 600;
|
|
26
|
-
line-height: 1.35;
|
|
27
|
-
letter-spacing: 0;
|
|
28
|
-
color: var(--openpress-color-ink);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.type-specimen__meta span {
|
|
32
|
-
display: block;
|
|
33
|
-
margin-top: 1mm;
|
|
34
|
-
color: var(--openpress-color-muted);
|
|
35
|
-
font-size: 8pt;
|
|
36
|
-
line-height: 1.45;
|
|
37
|
-
font-variant-numeric: tabular-nums;
|
|
38
|
-
letter-spacing: 0;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.type-specimen__sample {
|
|
42
|
-
margin: 0 !important;
|
|
43
|
-
color: var(--openpress-color-ink);
|
|
44
|
-
text-align: center;
|
|
45
|
-
overflow-wrap: anywhere;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.type-specimen__sample--metric {
|
|
49
|
-
font-family: var(--openpress-font-body);
|
|
50
|
-
font-size: 34pt;
|
|
51
|
-
font-weight: 700;
|
|
52
|
-
line-height: 1;
|
|
53
|
-
font-variant-numeric: tabular-nums;
|
|
54
|
-
letter-spacing: 0;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.type-specimen__sample--cover-title {
|
|
58
|
-
font-family: var(--openpress-font-serif);
|
|
59
|
-
font-size: 30pt;
|
|
60
|
-
font-weight: 300;
|
|
61
|
-
line-height: 1.05;
|
|
62
|
-
letter-spacing: 0.01em;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.type-specimen__sample--chapter-title {
|
|
66
|
-
font-family: var(--openpress-font-serif);
|
|
67
|
-
font-size: 17pt;
|
|
68
|
-
font-weight: 300;
|
|
69
|
-
line-height: 1.35;
|
|
70
|
-
letter-spacing: 0.04em;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.type-specimen__sample--section-title {
|
|
74
|
-
font-family: var(--openpress-font-serif);
|
|
75
|
-
font-size: 13pt;
|
|
76
|
-
font-weight: 400;
|
|
77
|
-
line-height: 1.45;
|
|
78
|
-
letter-spacing: 0.03em;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.type-specimen__sample--body {
|
|
82
|
-
max-width: 112mm;
|
|
83
|
-
margin-right: auto !important;
|
|
84
|
-
margin-left: auto !important;
|
|
85
|
-
font-family: var(--openpress-font-body);
|
|
86
|
-
font-size: 10pt;
|
|
87
|
-
font-weight: 400;
|
|
88
|
-
line-height: 1.75;
|
|
89
|
-
letter-spacing: 0;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.type-specimen__sample--caption {
|
|
93
|
-
font-family: var(--openpress-font-body);
|
|
94
|
-
font-size: 8pt;
|
|
95
|
-
font-weight: 400;
|
|
96
|
-
line-height: 1.5;
|
|
97
|
-
color: var(--openpress-color-muted);
|
|
98
|
-
letter-spacing: 0.02em;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
@media (max-width: 899px) {
|
|
102
|
-
.type-specimen__row {
|
|
103
|
-
grid-template-columns: 1fr;
|
|
104
|
-
gap: 2mm;
|
|
105
|
-
align-items: start;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.type-specimen__sample {
|
|
109
|
-
text-align: left;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
# open-press 樣式規格
|
|
2
|
-
|
|
3
|
-
> 一份合併的設計說明,給內容作者、AI Agent 與 style pack contributor 共用。
|
|
4
|
-
> Editorial-monograph starter 從這份檔案複製到 `document/design.md`;之後請依專案需要改寫,維持單一檔案結構。
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## 1. 風格目標與使用場景
|
|
9
|
-
|
|
10
|
-
open-press 初始模板面向長文件,而不是單頁網站或 dashboard。它要支援課程講義、提案、報告、白皮書、產品文件與公開說明文件,重點是穩定閱讀、可輸出、可被 AI 持續修改。
|
|
11
|
-
|
|
12
|
-
這套風格的基調是「安靜、可信、可交付」。文件使用白底、近黑文字、細線分隔、低彩度輔助資訊與少量暖色圖表色。章節標題保留 editorial 感,但正文、表格與圖表仍優先服務資訊密度。
|
|
13
|
-
|
|
14
|
-
### 設計原則
|
|
15
|
-
|
|
16
|
-
| 原則 | 規則 | Agent 操作提醒 |
|
|
17
|
-
| --- | --- | --- |
|
|
18
|
-
| 文件優先 | 第一眼應該像可交付的 A4 文件,不像 landing page | 不要加入 hero marketing section、浮動卡片或裝飾性背景 |
|
|
19
|
-
| 規格透明 | User 看到的 Design page 就是 Agent 依循的 design source | 修改風格時先更新 `document/design.md`,再更新 `document/theme/` |
|
|
20
|
-
| 來源可改 | 內容從 MDX、React props 與 media assets 產生 | 不把關鍵文字或數據鎖死在截圖或手寫 SVG |
|
|
21
|
-
| 輸出穩定 | 所有樣式要支援 reader、mobile preview 與 PDF | 避免 uncontrolled overflow、孤立 caption 與跨 footer 元件 |
|
|
22
|
-
|
|
23
|
-
### 使用場景
|
|
24
|
-
|
|
25
|
-
| 場景 | 適合原因 | 不適合方向 |
|
|
26
|
-
| --- | --- | --- |
|
|
27
|
-
| 提案與商業報告 | 需要清楚章節、數據、圖表與結論 | 過度銷售語氣、滿版裝飾 |
|
|
28
|
-
| 課程講義與白皮書 | 需要長文閱讀與穩定分頁 | 插畫密集或社群貼文式排版 |
|
|
29
|
-
| 產品文件與說明書 | 需要流程、規格、表格與檢查清單 | Dashboard-like 操作面板 |
|
|
30
|
-
| Design System Manual | 需要 user 與 Agent 看到同一份規格 | 另一套 token gallery 或 demo source |
|
|
31
|
-
|
|
32
|
-
### User 與 Agent 的分工
|
|
33
|
-
|
|
34
|
-
User 檢查這份文件時,主要判斷「這是不是我要的文件風格」。Agent 閱讀這份文件時,主要判斷「接下來生成正式文件時要遵守哪些規格」。
|
|
35
|
-
|
|
36
|
-
| 角色 | 讀這份文件時要取得的資訊 |
|
|
37
|
-
| --- | --- |
|
|
38
|
-
| User | 風格是否符合品牌、文件是否易讀、輸出是否可信 |
|
|
39
|
-
| Agent | 語氣、字級、色彩、元件規則、驗收清單 |
|
|
40
|
-
| open-press renderer | source mapping、bookmarks、page state、PDF-safe preview |
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## 2. Tokens
|
|
45
|
-
|
|
46
|
-
### Typography Scale
|
|
47
|
-
|
|
48
|
-
open-press 初始模板使用兩組字體:正文與介面使用無襯線,封面與章節標題使用襯線,讓文件在資訊密度與 editorial 氣質之間取得平衡。
|
|
49
|
-
|
|
50
|
-
| 用途 | CSS selector / token | 字體 | 大小 | 字重 | 行高 / 字距 | 使用規則 |
|
|
51
|
-
| --- | --- | --- | --- | --- | --- | --- |
|
|
52
|
-
| Metric display | `.metric-display`, chart figure number | `--openpress-font-body` | `34pt` | 700 | line-height `1`, letter `0` | 只用於資料圖表或單一重點數字 |
|
|
53
|
-
| Cover title | `.cover-title` | `--openpress-font-serif` | `clamp(36px, 8.5cqw, 64px)` | 300 | line-height `1`, letter `0.01em` | 文件名稱或產品名,整份文件只在封面使用 |
|
|
54
|
-
| Cover tagline | `.cover-tagline` | `--openpress-font-serif` | `clamp(14px, 2.4cqw, 20px)` | 300 | letter `0.08em` | 封面一句話定位,不承載長句 |
|
|
55
|
-
| Cover subtitle | `.cover-subtitle` | `--openpress-font-body` | `10.5pt-12.5pt` | 400 | line-height `1.55` | 封面主說明,最多一段 |
|
|
56
|
-
| Chapter title | `h2` | `--openpress-font-serif` | `14pt-17pt` | 300 | line-height `1.45`, letter `0.04em` | 每個 `##` 產生一個章節 bookmark |
|
|
57
|
-
| Section title | `h3` | `--openpress-font-serif` | `11pt-13pt` | 400 | line-height `1.55`, letter `0.03em` | 用於章節內小節,不要過度切碎 |
|
|
58
|
-
| Minor heading | `h4` | `--openpress-font-body` | `10pt-11pt` | 500 | muted, letter `0.04em` | 表格前提示或局部標題 |
|
|
59
|
-
| Body text | `p`, `li` | `--openpress-font-body` | `9.5pt-10.5pt` | 400 | line-height `1.85` | 長文閱讀基準;不要用過短行距 |
|
|
60
|
-
| Table text | `table` | `--openpress-font-body` | `8pt-9pt` | 400 / th 500 | line-height `1.45` | 密集資料,保持掃讀 |
|
|
61
|
-
| Caption | `figcaption`, `caption` | `--openpress-font-body` | `7.5pt-8.5pt` | 400 | line-height `1.5`, letter `0.02em` | 圖表下方置中,需可自動編號 |
|
|
62
|
-
|
|
63
|
-
Agent 寫作時不應用「字變大」解決層級問題。若章節不清楚,先調整內容結構與 heading;若仍不足,再調整 token。
|
|
64
|
-
|
|
65
|
-
### Color Tokens
|
|
66
|
-
|
|
67
|
-
色票是視覺驗收工具,不取代表格規格。User 可以用視覺對照判斷文件氣質;Agent 應依照每張色票的 usage 決定是否使用。
|
|
68
|
-
|
|
69
|
-
| Token | Value | 用途 |
|
|
70
|
-
| --- | --- | --- |
|
|
71
|
-
| `--openpress-color-document` | `#ffffff` | A4 文件紙面、表格與圖表背景 |
|
|
72
|
-
| `--openpress-color-ink` | `#161616` | 主文字、標題、主要線條 |
|
|
73
|
-
| `--openpress-color-muted` | `#6f6f6f` | caption、頁碼、章節編號、輔助說明 |
|
|
74
|
-
| `--openpress-color-line` | `#e0e0e0` | 表格列線、細分隔線 |
|
|
75
|
-
| `--openpress-color-soft-line` | `#f4f4f4` | 輕量分隔、flow stage 內部線 |
|
|
76
|
-
| `--openpress-color-app-bg` | `#161616` | Workbench 外層深色 chrome |
|
|
77
|
-
| `--openpress-chart-gold` | `#FFB000` | 主要 chart accent、current / starting point |
|
|
78
|
-
| `--openpress-chart-coral` | `#FF6A4D` | chart 第二層強調 |
|
|
79
|
-
| `--openpress-chart-coral-deep` | `#C9522B` | chart 深層強調 |
|
|
80
|
-
| `--openpress-chart-dark` | `#1F2328` | chart anchor / mature state |
|
|
81
|
-
| `--openpress-status-warn` | `#C9522B` | 行內語意強調:風險、警示、注意(`.status-warn`) |
|
|
82
|
-
| `--openpress-status-success` | `#5C8C4F` | 行內語意強調:達標、通過、確認(`.status-success`) |
|
|
83
|
-
| `--openpress-status-info` | `#4A6B8A` | 行內語意強調:補充說明、註腳(`.status-info`) |
|
|
84
|
-
|
|
85
|
-
文件頁面以黑白灰為主,暖色只用在圖表與少量 emphasis。不要把整份文件改成單一強烈品牌色,也不要用大面積漸層當背景。
|
|
86
|
-
|
|
87
|
-
Starter 可以用 React 元件建立視覺對照頁,例如 `document/components/TypeSpecimen/`(typography)與 `document/components/TokenSwatchGrid/`(color)。
|
|
88
|
-
|
|
89
|
-
### Inline Emphasis
|
|
90
|
-
|
|
91
|
-
Markdown 內的文字強調走兩條路徑:
|
|
92
|
-
|
|
93
|
-
1. **MD 原生語法**:`**bold**` → `<strong>`,`*italic*` → `<em>`,`~~strike~~` → `<del>`,`` `code` `` → `<code>`,`[text](url)` → `<a>`,`<mark>text</mark>` → highlight。每個都已綁 token 樣式,不用手動加 class。
|
|
94
|
-
2. **語意強調色**:在 markdown 內以 `<span class="status-warn|status-success|status-info">` 標註。class 限制在三色 status,避免按色相命名(如 `.accent-gold`)破壞語意系統。
|
|
95
|
-
|
|
96
|
-
| Selector | 預設樣式來源 | 使用時機 |
|
|
97
|
-
| --- | --- | --- |
|
|
98
|
-
| `strong` | `font-weight: 600` + ink color | 段落內關鍵詞、列表 key term |
|
|
99
|
-
| `em` | serif italic + ink color | 引用、術語、書名 |
|
|
100
|
-
| `del` / `s` | muted + strike | 刪除、修正前後對照 |
|
|
101
|
-
| `code` | mono font + 淺背景 + padding | 路徑、識別字、命令 |
|
|
102
|
-
| `a` | ink + dotted underline | 超連結;underline 避免實線以區隔印刷正文 |
|
|
103
|
-
| `mark` | gold tint 背景 + ink | 「primary highlight」——一份文件只挑少量重點數字或關鍵句 |
|
|
104
|
-
| `.status-warn` | `--openpress-status-warn` + 600 | 風險、延遲、警示語境 |
|
|
105
|
-
| `.status-success` | `--openpress-status-success` + 600 | 已達標、通過、完成 |
|
|
106
|
-
| `.status-info` | `--openpress-status-info` + 600 | 補充、註記、輔助資訊 |
|
|
107
|
-
| `.text-muted` | `--openpress-color-muted` | 非語意性「再弱一級」 |
|
|
108
|
-
|
|
109
|
-
不提供 `<u>` underline 樣式——印刷上跟 `<a>` 撞,反而降低可讀性。若要強調,改用 `<strong>` 或 `<mark>`。
|
|
110
|
-
|
|
111
|
-
Block-level 強調(callout / warning / note)目前不在 design system 範圍;若文件需要區塊式提示,先評估是否能用既有 figure 或 table 表達。
|
|
112
|
-
|
|
113
|
-
### Chapter & Section Numbering
|
|
114
|
-
|
|
115
|
-
Engine 不在 h2/h3 內容前注入任何編號或前綴;export pipeline 會在 build-time 寫入 `data-chapter` / `data-section` attribute(值是 `01`、`1.1` 這種兩位數阿拉伯格式)。實際顯示樣式由 theme 的 `::before content` 決定,這讓不同文件能挑不同 numbering vocabulary 而不動 reader runtime。
|
|
116
|
-
|
|
117
|
-
預設(editorial-monograph 起手樣式):
|
|
118
|
-
|
|
119
|
-
```css
|
|
120
|
-
/* document/theme/base/typography.css */
|
|
121
|
-
.reader-page--content .page-body > h2:first-child::before {
|
|
122
|
-
content: attr(data-chapter); /* 顯示「02」 */
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.reader-page--content h3[data-section]::before {
|
|
126
|
-
content: attr(data-section); /* 顯示「2.1」 */
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
要換成「一、二、(一)(二)」風格,**不動 engine、不動 pagination**,只改 `typography.css` 的 `::before content`:
|
|
131
|
-
|
|
132
|
-
```css
|
|
133
|
-
@counter-style qj-cjk-decimal {
|
|
134
|
-
system: cyclic;
|
|
135
|
-
symbols: "一" "二" "三" "四" "五" "六" "七" "八" "九" "十";
|
|
136
|
-
suffix: "、";
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
@counter-style qj-cjk-section {
|
|
140
|
-
system: cyclic;
|
|
141
|
-
symbols: "(一)" "(二)" "(三)" "(四)" "(五)"
|
|
142
|
-
"(六)" "(七)" "(八)" "(九)" "(十)";
|
|
143
|
-
suffix: "";
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* Chapter h2: 一、 */
|
|
147
|
-
.reader-page--content .page-body > h2:first-child {
|
|
148
|
-
counter-reset: qj-chapter calc(attr(data-chapter type(<integer>), 0));
|
|
149
|
-
}
|
|
150
|
-
.reader-page--content .page-body > h2:first-child::before {
|
|
151
|
-
content: counter(qj-chapter, qj-cjk-decimal);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/* Section h3: (一) */
|
|
155
|
-
.reader-page--content h3[data-section] {
|
|
156
|
-
counter-reset: qj-section calc(attr(data-section, "0") * 10);
|
|
157
|
-
}
|
|
158
|
-
.reader-page--content h3[data-section]::before {
|
|
159
|
-
content: counter(qj-section, qj-cjk-section);
|
|
160
|
-
}
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
或更簡單:用 `attr()` 不做 counter,直接在 attribute 做字串映射(CSS 沒這能力時就回到 `@counter-style`)。要 `Chapter 1` / `§1.1` / 純數字無前綴等等,都改一條 `content:` 即可。
|
|
164
|
-
|
|
165
|
-
要點:
|
|
166
|
-
- engine 只給 raw counter(`data-chapter="02"`、`data-section="2.1"`)
|
|
167
|
-
- 顯示是 theme 的責任
|
|
168
|
-
- 換樣式不需要改 markdown、不需要動 engine、不需要 rebuild pagination
|
|
169
|
-
|
|
170
|
-
### Spacing 與 Page Rhythm
|
|
171
|
-
|
|
172
|
-
Spacing 定義頁面節奏,不是用來硬塞內容。若一頁過密,優先拆成新的 `##` 頁面,而不是縮小字級或移除留白。
|
|
173
|
-
|
|
174
|
-
| Token | Value | 用途 |
|
|
175
|
-
| --- | --- | --- |
|
|
176
|
-
| `--openpress-space-1` | `2mm` | caption、局部小間距 |
|
|
177
|
-
| `--openpress-space-2` | `4mm` | 段落、封面小區塊間距 |
|
|
178
|
-
| `--openpress-space-3` | `6mm` | h3 前後、figure margin |
|
|
179
|
-
| `--openpress-space-4` | `9mm` | h2 後、TOC 與大區塊 |
|
|
180
|
-
| `--openpress-space-5` | `13mm` | 少數需要更大呼吸的頁面區塊 |
|
|
181
|
-
|
|
182
|
-
頁面節奏應該由 heading、paragraph、table、figure 的固定 spacing 自然形成,不用額外插入空白段落。固定版面中,寧可拆章節,也不要把過多內容硬塞在同一頁。
|
|
183
|
-
|
|
184
|
-
### Page Geometry
|
|
185
|
-
|
|
186
|
-
文件實體尺寸由三個 token 共同決定,page-contract 的 `@page`、reader runtime、shell measurement、PDF print route 都讀同一組值。要從 A4 換到 Letter / B5 / 16:9 投影片,改這三條即可,其他 CSS 不用動。
|
|
187
|
-
|
|
188
|
-
| Token | Value | 用途 |
|
|
189
|
-
| --- | --- | --- |
|
|
190
|
-
| `--openpress-page-width` | `210mm` | 紙張寬;`@page size` 第一參數、`.reader-page` width、PDF 印出寬 |
|
|
191
|
-
| `--openpress-page-height` | `297mm` | 紙張高;`@page size` 第二參數、`.reader-page` height、PDF 印出高 |
|
|
192
|
-
| `--openpress-page-margin` | `18mm` | `@page margin`(CSS print 邊距,不是 body 內容 padding) |
|
|
193
|
-
|
|
194
|
-
切到非 A4 的範例:
|
|
195
|
-
|
|
196
|
-
```css
|
|
197
|
-
/* Letter (8.5 × 11 in) */
|
|
198
|
-
--openpress-page-width: 215.9mm;
|
|
199
|
-
--openpress-page-height: 279.4mm;
|
|
200
|
-
|
|
201
|
-
/* B5 */
|
|
202
|
-
--openpress-page-width: 176mm;
|
|
203
|
-
--openpress-page-height: 250mm;
|
|
204
|
-
|
|
205
|
-
/* 16:9 投影片(landscape) */
|
|
206
|
-
--openpress-page-width: 297mm;
|
|
207
|
-
--openpress-page-height: 167mm;
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
body 內容區的 page padding(content margin)由 `.reader-page` 內的 `--page-margin-*` 變數控制,與 `--openpress-page-margin` 是兩件事。前者是「內容到頁面邊緣的距離」,後者是「@page CSS 邊距」(PDF 印出時的物理邊距)。
|
|
211
|
-
|
|
212
|
-
---
|
|
213
|
-
|
|
214
|
-
## 3. Components
|
|
215
|
-
|
|
216
|
-
這一節定義 open-press 生成文件時可以使用的核心元件。Agent 新增內容時,應先判斷資訊類型,再選擇 paragraph、table、figure、chart 或 checklist,而不是為了視覺豐富度任意加入卡片。
|
|
217
|
-
|
|
218
|
-
### Page Surfaces
|
|
219
|
-
|
|
220
|
-
| 元件 | Source 寫法 | 視覺規則 | Agent 使用時機 |
|
|
221
|
-
| --- | --- | --- | --- |
|
|
222
|
-
| Cover | `kind: cover` + HTML cover block | logo 左上、meta 右上、serif 大標、短 subtitle、可選 hero image | 文件開場,建立文件身份 |
|
|
223
|
-
| TOC | `kind: toc` 或 exporter 插入 | 自動收集 `##`,顯示章節頁碼;不顯示 footer | 不手寫目錄內容 |
|
|
224
|
-
| Chapter opener | `kind: chapter-opener` | H2 主題入口 mini cover,只保留大標、副標與一句 summary;不顯示 footer、不進正式目錄 | 書籍、教材、手冊等章節相對獨立的文件;只放在 `##` 全新主題之前 |
|
|
225
|
-
| Chapter page | `##` heading | h2 產生章節頁與 bookmark,章節號由 renderer 注入 | 每個主要概念一個 `##` |
|
|
226
|
-
| Back cover | `kind: back-cover` | 大 kicker、收束 statement、短 summary | 文件結尾與品牌收束 |
|
|
227
|
-
|
|
228
|
-
### Text Components
|
|
229
|
-
|
|
230
|
-
- **Paragraph**:處理脈絡、判斷、說明與轉折。單段不宜過長;若同段超過三個概念,改成列表或表格。
|
|
231
|
-
- **Ordered list**:表示流程、階段、優先順序。
|
|
232
|
-
- **Unordered list**:表示同層級規則、注意事項或檢查項。
|
|
233
|
-
- **Table**:比較角色、token、component、狀態與輸出規則。Markdown table 前使用 `<TableCaption>...</TableCaption>`,讓 renderer 自動編號。
|
|
234
|
-
- **Caption**:必須能獨立說明圖表用途,不只寫「示意圖」。
|
|
235
|
-
|
|
236
|
-
### Tables
|
|
237
|
-
|
|
238
|
-
表格使用 thin-rule style:上方主線、header 底線、row hairline、偶數列淡背景。密集表格的文字比正文小一級,但仍要保留足夠行高。
|
|
239
|
-
|
|
240
|
-
<TableCaption>表格使用規則</TableCaption>
|
|
241
|
-
|
|
242
|
-
| 表格類型 | 欄位建議 | 注意事項 |
|
|
243
|
-
| --- | --- | --- |
|
|
244
|
-
| 規格表 | token / value / usage | value 保持短,usage 說明使用情境 |
|
|
245
|
-
| 比較表 | item / rule / agent action | 避免超過四欄;長說明移到段落 |
|
|
246
|
-
| 檢查表 | check / pass condition / risk | 適合放在章末或封底 |
|
|
247
|
-
|
|
248
|
-
### Figures 與 Charts
|
|
249
|
-
|
|
250
|
-
圖片與圖表都要有 caption,並避免孤立在頁尾。一般圖片使用 `figure`;資料視覺化與大段可重用 HTML 都抽成 PascalCase React component,每個 component 是 `document/components/ComponentName.tsx` 或 `document/components/ComponentName/index.tsx`。
|
|
251
|
-
|
|
252
|
-
> **示範元件未隨 starter 提供完整 chart。** editorial-monograph 不預設打包任何 chart 或 bespoke component;專案需要時自己在 `document/components/` 下建立。
|
|
253
|
-
|
|
254
|
-
### Chart Rules
|
|
255
|
-
|
|
256
|
-
| 規則 | 說明 |
|
|
257
|
-
| --- | --- |
|
|
258
|
-
| 資料歸資料 | chart data 透過 React props 或鄰近的 typed data module 傳入,不寫死在 CSS |
|
|
259
|
-
| 樣式歸樣式 | chart frame 等通用規則放在 `document/theme/patterns/`;變體 CSS 放在元件自己的 `style.css` |
|
|
260
|
-
| 元件歸元件 | 一個視覺 = 一個 `document/components/ComponentName/` 包;MDX 只保留 `<ComponentName />` 呼叫 |
|
|
261
|
-
| Caption 必填 | caption 只寫說明文字,不手寫圖號或表號;export pipeline 會替 content pages 的 figure/table 自動編號 |
|
|
262
|
-
| PDF-safe | 圖表需 `break-inside: avoid`,高度不可壓到 footer |
|
|
263
|
-
|
|
264
|
-
如果使用者要求新的視覺元件,Agent 應先更新本檔說明,再改對應的 `document/components/<name>/style.css` 或 `document/theme/` CSS,最後用 reader 預覽檢查 PDF 輸出。
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## 4. CSS 權責
|
|
269
|
-
|
|
270
|
-
| 層級 | 位置 | 責任 |
|
|
271
|
-
| --- | --- | --- |
|
|
272
|
-
| open-press core | package runtime / `engine/` / `src/openpress/` | Pagination、export、validation、React reader runtime |
|
|
273
|
-
| Theme tokens | `document/theme/tokens.css` | CSS variables:color、font、spacing、chart token,不放 selector |
|
|
274
|
-
| Theme base | `document/theme/base/` | A4 page contract、cover、TOC、heading、paragraph、figure、table、caption、print |
|
|
275
|
-
| Theme patterns | `document/theme/patterns/` | Markdown/HTML class pattern:chart frame、色票、typography specimen、image grid |
|
|
276
|
-
| Component-owned CSS | `document/components/ComponentName/style.css` | React component 專用樣式 |
|
|
277
|
-
| Theme shell | `document/theme/shell/` | Exported reader controls,不放文件 typography |
|
|
278
|
-
| Design Document | `document/design.md` | 說明目前 theme 的規格、取捨與驗收方式 |
|
|
279
|
-
| Generated output | `public/openpress/`, `dist-react/` | export/render 產物,不手動修改 |
|