@open-press/cli 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/README.md +11 -12
  2. package/dist/cli.js +298 -79
  3. package/package.json +9 -7
  4. package/template/core/AGENTS.md +0 -130
  5. package/template/core/CHANGELOG.md +0 -218
  6. package/template/core/README.md +0 -43
  7. package/template/core/engine/cli.mjs +0 -96
  8. package/template/core/engine/commands/_shared.mjs +0 -199
  9. package/template/core/engine/commands/deploy.mjs +0 -31
  10. package/template/core/engine/commands/dev.mjs +0 -49
  11. package/template/core/engine/commands/doctor.mjs +0 -229
  12. package/template/core/engine/commands/export.mjs +0 -8
  13. package/template/core/engine/commands/image.mjs +0 -29
  14. package/template/core/engine/commands/inspect.mjs +0 -35
  15. package/template/core/engine/commands/pdf.mjs +0 -26
  16. package/template/core/engine/commands/preview.mjs +0 -26
  17. package/template/core/engine/commands/render.mjs +0 -17
  18. package/template/core/engine/commands/replace.mjs +0 -41
  19. package/template/core/engine/commands/search.mjs +0 -33
  20. package/template/core/engine/commands/skills-sync.mjs +0 -71
  21. package/template/core/engine/commands/typecheck.mjs +0 -67
  22. package/template/core/engine/commands/upgrade.mjs +0 -159
  23. package/template/core/engine/commands/validate.mjs +0 -17
  24. package/template/core/engine/document-export.mjs +0 -15
  25. package/template/core/engine/output/chrome-pdf.d.mts +0 -34
  26. package/template/core/engine/output/chrome-pdf.mjs +0 -450
  27. package/template/core/engine/output/deploy-sync.mjs +0 -15
  28. package/template/core/engine/output/fonts.mjs +0 -62
  29. package/template/core/engine/output/katex-assets.mjs +0 -45
  30. package/template/core/engine/output/page-block.mjs +0 -30
  31. package/template/core/engine/output/pdf-media.mjs +0 -45
  32. package/template/core/engine/output/public-assets.mjs +0 -19
  33. package/template/core/engine/output/static-server.mjs +0 -571
  34. package/template/core/engine/react/caption-numbering.mjs +0 -73
  35. package/template/core/engine/react/comment-endpoint.d.mts +0 -11
  36. package/template/core/engine/react/comment-endpoint.mjs +0 -102
  37. package/template/core/engine/react/comment-marker.mjs +0 -374
  38. package/template/core/engine/react/document-entry.mjs +0 -331
  39. package/template/core/engine/react/document-export.mjs +0 -512
  40. package/template/core/engine/react/http-json.mjs +0 -24
  41. package/template/core/engine/react/mdx-compile.mjs +0 -629
  42. package/template/core/engine/react/measurement-css.mjs +0 -157
  43. package/template/core/engine/react/object-entities.mjs +0 -204
  44. package/template/core/engine/react/pagination/allocator.mjs +0 -167
  45. package/template/core/engine/react/pagination/regions.mjs +0 -81
  46. package/template/core/engine/react/pagination-constants.mjs +0 -3
  47. package/template/core/engine/react/pagination.mjs +0 -9
  48. package/template/core/engine/react/pipeline/allocate.mjs +0 -217
  49. package/template/core/engine/react/pipeline/final-render.mjs +0 -94
  50. package/template/core/engine/react/pipeline/frame-measurement.mjs +0 -306
  51. package/template/core/engine/react/pipeline/press-tree.mjs +0 -135
  52. package/template/core/engine/react/press-tree-inspection.mjs +0 -172
  53. package/template/core/engine/react/project-asset-endpoint.d.mts +0 -10
  54. package/template/core/engine/react/project-asset-endpoint.mjs +0 -361
  55. package/template/core/engine/react/section-css.mjs +0 -56
  56. package/template/core/engine/react/source-edit-endpoint.d.mts +0 -10
  57. package/template/core/engine/react/source-edit-endpoint.mjs +0 -75
  58. package/template/core/engine/react/sources/heading-numbering.mjs +0 -132
  59. package/template/core/engine/react/sources/mdx-resolver.mjs +0 -439
  60. package/template/core/engine/react/style-discovery.mjs +0 -160
  61. package/template/core/engine/runtime/config.d.mts +0 -48
  62. package/template/core/engine/runtime/config.mjs +0 -172
  63. package/template/core/engine/runtime/file-utils.mjs +0 -114
  64. package/template/core/engine/runtime/file-walk.mjs +0 -22
  65. package/template/core/engine/runtime/inspection.mjs +0 -328
  66. package/template/core/engine/runtime/issue-report.mjs +0 -44
  67. package/template/core/engine/runtime/page-geometry.mjs +0 -131
  68. package/template/core/engine/runtime/path-utils.mjs +0 -20
  69. package/template/core/engine/runtime/source-text-tools.d.mts +0 -102
  70. package/template/core/engine/runtime/source-text-tools.mjs +0 -832
  71. package/template/core/engine/runtime/source-workspace.mjs +0 -168
  72. package/template/core/engine/runtime/validation.mjs +0 -183
  73. package/template/core/index.html +0 -13
  74. package/template/core/openpress.config.mjs +0 -8
  75. package/template/core/package.json +0 -89
  76. package/template/core/src/main.tsx +0 -16
  77. package/template/core/src/openpress/app/OpenPressApp.tsx +0 -296
  78. package/template/core/src/openpress/app/OpenPressRuntime.tsx +0 -102
  79. package/template/core/src/openpress/app/WorkspaceGalleryPage.tsx +0 -219
  80. package/template/core/src/openpress/app/index.ts +0 -2
  81. package/template/core/src/openpress/core/Frame.tsx +0 -91
  82. package/template/core/src/openpress/core/FrameContext.tsx +0 -26
  83. package/template/core/src/openpress/core/MdxArea.tsx +0 -34
  84. package/template/core/src/openpress/core/Press.tsx +0 -55
  85. package/template/core/src/openpress/core/Workspace.tsx +0 -36
  86. package/template/core/src/openpress/core/cn.ts +0 -4
  87. package/template/core/src/openpress/core/index.tsx +0 -47
  88. package/template/core/src/openpress/core/primitives.tsx +0 -91
  89. package/template/core/src/openpress/core/types.ts +0 -236
  90. package/template/core/src/openpress/core/useSource.ts +0 -28
  91. package/template/core/src/openpress/document-model/anchorMapModel.ts +0 -27
  92. package/template/core/src/openpress/document-model/documentIndexes.ts +0 -329
  93. package/template/core/src/openpress/document-model/documentTypes.ts +0 -147
  94. package/template/core/src/openpress/document-model/index.ts +0 -7
  95. package/template/core/src/openpress/document-model/objectEntityModel.ts +0 -55
  96. package/template/core/src/openpress/document-model/projectIdentityModel.ts +0 -15
  97. package/template/core/src/openpress/document-model/reactDocumentMetadataModel.ts +0 -27
  98. package/template/core/src/openpress/document-model/workspaceManifestModel.ts +0 -57
  99. package/template/core/src/openpress/manuscript/index.tsx +0 -238
  100. package/template/core/src/openpress/mdx/index.ts +0 -96
  101. package/template/core/src/openpress/numbering/index.ts +0 -294
  102. package/template/core/src/openpress/reader/PageThumbnailsPanel.tsx +0 -168
  103. package/template/core/src/openpress/reader/PublicReaderPage.tsx +0 -267
  104. package/template/core/src/openpress/reader/ReaderNavigationPanel.tsx +0 -123
  105. package/template/core/src/openpress/reader/index.ts +0 -11
  106. package/template/core/src/openpress/reader/pageViewportScaleModel.ts +0 -73
  107. package/template/core/src/openpress/reader/readerPageRegistry.ts +0 -41
  108. package/template/core/src/openpress/reader/readerPageRoute.ts +0 -21
  109. package/template/core/src/openpress/reader/readerScroll.ts +0 -92
  110. package/template/core/src/openpress/reader/readerStateModel.ts +0 -15
  111. package/template/core/src/openpress/reader/readerTypes.ts +0 -4
  112. package/template/core/src/openpress/reader/usePageViewportScale.ts +0 -119
  113. package/template/core/src/openpress/reader/usePanelState.ts +0 -56
  114. package/template/core/src/openpress/reader/useReaderHashSync.ts +0 -61
  115. package/template/core/src/openpress/reader/useReaderKeyboardNav.ts +0 -48
  116. package/template/core/src/openpress/reader/useReaderRuntime.ts +0 -146
  117. package/template/core/src/openpress/reader/useReaderScrollAnchor.ts +0 -64
  118. package/template/core/src/openpress/shared/Panel.tsx +0 -77
  119. package/template/core/src/openpress/shared/frameScheduler.ts +0 -32
  120. package/template/core/src/openpress/shared/index.ts +0 -4
  121. package/template/core/src/openpress/shared/numberUtils.ts +0 -3
  122. package/template/core/src/openpress/shared/runtimeMode.ts +0 -11
  123. package/template/core/src/openpress/workbench/Workbench.tsx +0 -506
  124. package/template/core/src/openpress/workbench/actions/DeploymentControl.tsx +0 -157
  125. package/template/core/src/openpress/workbench/actions/ExportImageControl.tsx +0 -96
  126. package/template/core/src/openpress/workbench/actions/PageZoomControl.tsx +0 -182
  127. package/template/core/src/openpress/workbench/actions/SearchControl.tsx +0 -345
  128. package/template/core/src/openpress/workbench/actions/deploymentStatusModel.ts +0 -112
  129. package/template/core/src/openpress/workbench/actions/index.ts +0 -6
  130. package/template/core/src/openpress/workbench/actions/useDeploymentWorkbench.ts +0 -136
  131. package/template/core/src/openpress/workbench/dialog/WorkbenchDialog.tsx +0 -72
  132. package/template/core/src/openpress/workbench/dialog/index.ts +0 -1
  133. package/template/core/src/openpress/workbench/document/components/DocumentPanel.tsx +0 -127
  134. package/template/core/src/openpress/workbench/document/components/InlineSourceEditorLayer.tsx +0 -207
  135. package/template/core/src/openpress/workbench/document/components/ReaderStage.tsx +0 -9
  136. package/template/core/src/openpress/workbench/document/hooks/useDocumentWorkbenchModel.ts +0 -34
  137. package/template/core/src/openpress/workbench/document/hooks/useInlineDocumentEditor.ts +0 -525
  138. package/template/core/src/openpress/workbench/document/index.ts +0 -10
  139. package/template/core/src/openpress/workbench/index.ts +0 -2
  140. package/template/core/src/openpress/workbench/inspector/InlineInspectorLayer.tsx +0 -459
  141. package/template/core/src/openpress/workbench/inspector/index.ts +0 -5
  142. package/template/core/src/openpress/workbench/inspector/inlineCommentModel.ts +0 -125
  143. package/template/core/src/openpress/workbench/inspector/inspectorGeometryModel.ts +0 -160
  144. package/template/core/src/openpress/workbench/inspector/inspectorModel.ts +0 -408
  145. package/template/core/src/openpress/workbench/inspector/useInspectorComments.ts +0 -254
  146. package/template/core/src/openpress/workbench/mentions/MentionSuggestionList.tsx +0 -41
  147. package/template/core/src/openpress/workbench/mentions/index.ts +0 -2
  148. package/template/core/src/openpress/workbench/mentions/useComposerMentions.ts +0 -185
  149. package/template/core/src/openpress/workbench/panels/Panel.tsx +0 -1
  150. package/template/core/src/openpress/workbench/panels/PendingCommentsPanel.tsx +0 -80
  151. package/template/core/src/openpress/workbench/panels/WorkbenchControlPanel.tsx +0 -29
  152. package/template/core/src/openpress/workbench/panels/index.ts +0 -3
  153. package/template/core/src/openpress/workbench/project/ProjectEntryPanel.tsx +0 -525
  154. package/template/core/src/openpress/workbench/project/ProjectPreviewDialog.tsx +0 -35
  155. package/template/core/src/openpress/workbench/project/index.ts +0 -2
  156. package/template/core/src/openpress/workbench/project/projectPreviewTypes.ts +0 -11
  157. package/template/core/src/openpress/workbench/project/projectSourceModel.ts +0 -24
  158. package/template/core/src/openpress/workbench/shell/WorkbenchShell.tsx +0 -167
  159. package/template/core/src/openpress/workbench/shell/index.ts +0 -1
  160. package/template/core/src/openpress/workbench/workbenchFormatters.ts +0 -120
  161. package/template/core/src/openpress/workbench/workbenchTypes.ts +0 -35
  162. package/template/core/src/styles/openpress/app-shell.css +0 -251
  163. package/template/core/src/styles/openpress/media-workspace.css +0 -230
  164. package/template/core/src/styles/openpress/print-route.css +0 -184
  165. package/template/core/src/styles/openpress/project-preview-panel.css +0 -924
  166. package/template/core/src/styles/openpress/public-viewer.css +0 -688
  167. package/template/core/src/styles/openpress/reader-runtime.css +0 -989
  168. package/template/core/src/styles/openpress/responsive.css +0 -245
  169. package/template/core/src/styles/openpress/workbench-panels.css +0 -707
  170. package/template/core/src/styles/openpress/workbench.css +0 -1255
  171. package/template/core/src/styles/openpress/workspace-gallery.css +0 -300
  172. package/template/core/src/styles/openpress.css +0 -15
  173. package/template/core/src/vite-env.d.ts +0 -9
  174. package/template/core/tsconfig.json +0 -40
  175. package/template/core/vite.config.ts +0 -584
@@ -1,91 +0,0 @@
1
- import { useContext } from "react";
2
- import { cn } from "./cn";
3
- import { FrameContext, type FrameContextValue } from "./FrameContext";
4
- import { PressContext } from "./Press";
5
- import type { FrameProps } from "./types";
6
- import { createFrameObjectEntityId, createPageObjectEntityId, createScopedObjectEntityId } from "../document-model/objectEntityModel";
7
-
8
- // Substring reserved for the overflow extension pipeline.
9
- const RESERVED_EXTENDED = ":extended:";
10
-
11
- export const FRAME_MARKER: unique symbol = Symbol.for("@open-press/core:Frame");
12
-
13
- export function Frame({
14
- frameKey,
15
- role,
16
- chrome = true,
17
- className,
18
- children,
19
- ...rest
20
- }: FrameProps) {
21
- if (!frameKey || !String(frameKey).trim()) {
22
- throw new Error("Frame requires a non-empty frameKey.");
23
- }
24
- if (frameKey && frameKey.includes(RESERVED_EXTENDED)) {
25
- throw new Error(
26
- `Frame frameKey="${frameKey}" contains reserved substring ":extended:". ` +
27
- `This pattern is reserved for the overflow-extension pipeline.`,
28
- );
29
- }
30
-
31
- const parentFrame = useContext(FrameContext);
32
- const press = useContext(PressContext);
33
- const allocation = press?.allocation ?? null;
34
- const frameAllocation = frameKey && allocation ? allocation[frameKey] : undefined;
35
- const pageId = parentFrame?.pageId ?? createPageObjectEntityId(frameKey);
36
- const objectId = parentFrame
37
- ? createScopedObjectEntityId("frame", parentFrame.objectId, frameKey)
38
- : createFrameObjectEntityId(frameKey);
39
-
40
- // Mutable per-render counter. SSR renders a Frame exactly once, so a plain
41
- // object is fine — no useRef needed.
42
- const areaCounts: Record<string, number> = {};
43
- const frameContextValue: FrameContextValue = {
44
- frameKey: frameKey ?? "",
45
- objectId,
46
- pageId,
47
- consumeArea(chainId: string) {
48
- const index = areaCounts[chainId] ?? 0;
49
- areaCounts[chainId] = index + 1;
50
- if (!frameAllocation) return { indexInFrame: index, blocks: null };
51
- const chainSlots = frameAllocation[chainId];
52
- if (!chainSlots) return { indexInFrame: index, blocks: null };
53
- return { indexInFrame: index, blocks: chainSlots[index] ?? null };
54
- },
55
- };
56
-
57
- const pageKind = derivePageKind(role);
58
- const isNestedFrame = Boolean(parentFrame);
59
-
60
- return (
61
- <FrameContext.Provider value={frameContextValue}>
62
- <section
63
- {...(rest as Record<string, unknown>)}
64
- className={cn(isNestedFrame ? undefined : "reader-page", className)}
65
- data-openpress-frame-key={isNestedFrame ? undefined : frameKey}
66
- data-openpress-region-frame-key={isNestedFrame ? frameKey : undefined}
67
- data-openpress-object-id={objectId}
68
- data-openpress-object-kind="frame"
69
- data-openpress-object-label={role ?? frameKey}
70
- data-openpress-object-parent-id={parentFrame?.objectId ?? (isNestedFrame ? undefined : pageId)}
71
- data-openpress-object-page-id={pageId}
72
- data-frame-role={role}
73
- data-page-kind={isNestedFrame ? undefined : pageKind}
74
- data-frame-chrome={isNestedFrame ? undefined : chrome ? "true" : "false"}
75
- data-page-footer={isNestedFrame ? undefined : chrome ? "true" : "false"}
76
- >
77
- {children}
78
- </section>
79
- </FrameContext.Provider>
80
- );
81
- }
82
-
83
- (Frame as unknown as { openpressMarker: typeof FRAME_MARKER }).openpressMarker = FRAME_MARKER;
84
-
85
- function derivePageKind(role: string | undefined): string | undefined {
86
- if (!role) return undefined;
87
- const trimmed = role.trim();
88
- if (!trimmed) return undefined;
89
- const lastDot = trimmed.lastIndexOf(".");
90
- return lastDot === -1 ? trimmed : trimmed.slice(lastDot + 1);
91
- }
@@ -1,26 +0,0 @@
1
- import { createContext, type ReactNode } from "react";
2
-
3
- // FrameContext is the runtime channel between Frame and its descendant
4
- // MdxArea instances. Frame creates one of these on each render; MdxArea
5
- // reads it to claim its slot of allocated content.
6
- //
7
- // "Claiming" is order-sensitive: the first <MdxArea chainId="X"> rendered
8
- // inside a Frame takes areaIndex 0 for chain X, the next takes index 1,
9
- // and so on. Empty Frames (no allocation) return null, which renders the
10
- // MdxArea as a measurement placeholder.
11
-
12
- export interface ConsumedMdxArea {
13
- indexInFrame: number;
14
- // Null when the frame has no allocation (measurement pass) or no blocks
15
- // for this chain at the claimed index.
16
- blocks: ReactNode | null;
17
- }
18
-
19
- export interface FrameContextValue {
20
- frameKey: string;
21
- objectId: string;
22
- pageId: string;
23
- consumeArea(chainId: string): ConsumedMdxArea;
24
- }
25
-
26
- export const FrameContext = createContext<FrameContextValue | null>(null);
@@ -1,34 +0,0 @@
1
- import { useContext, type ReactNode } from "react";
2
- import { cn } from "./cn";
3
- import { FrameContext } from "./FrameContext";
4
- import type { MdxAreaProps } from "./types";
5
- import { createMdxAreaObjectEntityId } from "../document-model/objectEntityModel";
6
-
7
- export function MdxArea({
8
- chainId,
9
- overflow = "extend",
10
- className,
11
- ...rest
12
- }: MdxAreaProps) {
13
- const frame = useContext(FrameContext);
14
- const consumed = frame?.consumeArea(chainId) ?? null;
15
- const blocks: ReactNode | null = consumed?.blocks ?? null;
16
- const objectId = frame && consumed
17
- ? createMdxAreaObjectEntityId(frame.frameKey, chainId, consumed.indexInFrame)
18
- : undefined;
19
-
20
- return (
21
- <div
22
- {...(rest as Record<string, unknown>)}
23
- className={cn("openpress-mdx-area", className)}
24
- data-openpress-mdx-area="true"
25
- data-openpress-mdx-area-chain={chainId}
26
- data-openpress-mdx-area-index={consumed?.indexInFrame}
27
- data-openpress-object-id={objectId}
28
- data-openpress-mdx-area-overflow={overflow}
29
- data-openpress-mdx-area-empty={blocks == null ? "true" : "false"}
30
- >
31
- {blocks}
32
- </div>
33
- );
34
- }
@@ -1,55 +0,0 @@
1
- import { createContext, Fragment } from "react";
2
- import type { FrameAllocation, PressProps, ResolvedSource, TocEntry } from "./types";
3
-
4
- // Marker the engine uses to distinguish a Press default export from any other
5
- // React component. Workspaces register a default export whose `type` is this
6
- // `Press` component; the engine identity-checks against it.
7
- export const PRESS_MARKER: unique symbol = Symbol.for("@open-press/core:Press");
8
-
9
- // Allocation hints feed Layer 4 results back to Layer 2 so helpers like
10
- // <Sections> can emit the correct number of pages per chain. Null during
11
- // the first pass; populated after the allocator has decided how many
12
- // frames each chain needs.
13
- export interface AllocationHints {
14
- totalPagesPerChain: Record<string, number>;
15
- }
16
-
17
- // Metadata read from <Press> props by the engine pipeline. The 1.0 contract
18
- // declares these on the component; v0.x reads them from openpress.config.mjs
19
- // instead and leaves these as undefined. The engine merges both sources
20
- // (props override config) until v1.0 removes config support.
21
- export interface PressMetadata {
22
- title?: string;
23
- page?: PressProps["page"];
24
- slug?: string;
25
- theme?: string;
26
- componentsDir?: string;
27
- }
28
-
29
- export interface PressContextValue {
30
- sources: Record<string, ResolvedSource>;
31
- // Allocation map keyed by frameKey -> chainId -> areaIndex -> blocks.
32
- // null during measurement passes; populated during final render.
33
- allocation: FrameAllocation | null;
34
- // Allocation hints fed back from Layer 4 to Layer 2 helpers. null on
35
- // the first measurement pass.
36
- hints: AllocationHints | null;
37
- toc: Record<string, TocEntry[]> | null;
38
- // Metadata declared on <Press> props in v1.0. Engine providers may
39
- // omit this on v0.x; consumers should treat undefined as "no metadata
40
- // declared on Press — fall back to openpress.config.mjs values".
41
- metadata?: PressMetadata;
42
- }
43
-
44
- export const PressContext = createContext<PressContextValue | null>(null);
45
-
46
- export function Press(props: PressProps) {
47
- // Press is intentionally inert at render time — the engine reads its
48
- // props and children through React.Children inspection during the
49
- // export pipeline, then injects context above any nested helpers.
50
- // For the v0.x shape (children-only usage), this still passes children
51
- // through unchanged.
52
- return <Fragment>{props.children}</Fragment>;
53
- }
54
-
55
- (Press as unknown as { openpressMarker: typeof PRESS_MARKER }).openpressMarker = PRESS_MARKER;
@@ -1,36 +0,0 @@
1
- import { createContext, Fragment } from "react";
2
- import type { WorkspaceProps } from "./types";
3
-
4
- // Marker the engine uses to identify a Workspace default export, in the
5
- // same way PRESS_MARKER identifies Press. Multi-doc projects nest one
6
- // or more <Press> children inside <Workspace>; single-doc projects use
7
- // a Workspace with one Press child (uniform shape — no exceptions).
8
- export const WORKSPACE_MARKER: unique symbol = Symbol.for("@open-press/core:Workspace");
9
-
10
- export interface WorkspaceContextValue {
11
- // Project-level label surfaced in the gallery header / tab bar / PDF
12
- // metadata. Undefined if the Workspace did not declare a name.
13
- name?: string;
14
- // Workspace-level shared theme directory. Press children that don't
15
- // set their own `theme` prop inherit from this.
16
- theme?: string;
17
- // Workspace-level shared media directory.
18
- media?: string;
19
- // Number of Press children registered in this Workspace. Set by the
20
- // engine during expansion; useful to detect "gallery vs single-doc"
21
- // routing without re-walking the tree.
22
- pressCount: number;
23
- }
24
-
25
- export const WorkspaceContext = createContext<WorkspaceContextValue | null>(null);
26
-
27
- // Workspace is intentionally inert at render time. The engine inspects
28
- // its props (name / theme / media) and iterates Press children during
29
- // the export pipeline; rendering just passes children through so the
30
- // Press → Frame → MdxArea tree underneath behaves identically to v0.x
31
- // when there's only one Press child.
32
- export function Workspace(props: WorkspaceProps) {
33
- return <Fragment>{props.children}</Fragment>;
34
- }
35
-
36
- (Workspace as unknown as { openpressMarker: typeof WORKSPACE_MARKER }).openpressMarker = WORKSPACE_MARKER;
@@ -1,4 +0,0 @@
1
- export function cn(...values: Array<string | false | null | undefined>) {
2
- const joined = values.filter(Boolean).join(" ");
3
- return joined.length > 0 ? joined : undefined;
4
- }
@@ -1,47 +0,0 @@
1
- // @open-press/core — Press tree primitives.
2
- //
3
- // Layout: this entry exports only the kernel. Source descriptors live in
4
- // `@open-press/core/mdx`; manuscript helpers live in
5
- // `@open-press/core/manuscript`. Keeping the surface small is intentional —
6
- // the engine is not allowed to know about higher-level conventions.
7
-
8
- export { Press, PressContext, PRESS_MARKER } from "./Press";
9
- export { Workspace, WorkspaceContext, WORKSPACE_MARKER } from "./Workspace";
10
- export { Frame, FRAME_MARKER } from "./Frame";
11
- export { FrameContext } from "./FrameContext";
12
- export { MdxArea } from "./MdxArea";
13
- export { useSource } from "./useSource";
14
- export { ObjectEntity, Text, BaseFigure, BaseCallout, MediaFigure, ImageFigure } from "./primitives";
15
-
16
- export type {
17
- FrameProps,
18
- FrameRole,
19
- MdxAreaProps,
20
- MdxAreaOverflow,
21
- PressProps,
22
- PageGeometry,
23
- PressSource,
24
- WorkspaceProps,
25
- BaseFigureProps,
26
- MediaFigureProps,
27
- BaseCalloutKind,
28
- BaseCalloutProps,
29
- ObjectEntityElement,
30
- ObjectEntityProps,
31
- TextProps,
32
- // Source-side types are re-exported here for convenience so authors can
33
- // import `ResolvedSource` from the same place they import primitives.
34
- ResolvedSource,
35
- SourceNode,
36
- OutlineItem,
37
- SourceFileRecord,
38
- SourceBlock,
39
- TocEntry,
40
- MdxSourceDescriptor,
41
- SourceDescriptor,
42
- FrameAllocation,
43
- } from "./types";
44
-
45
- export type { PressContextValue, AllocationHints, PressMetadata } from "./Press";
46
- export type { WorkspaceContextValue } from "./Workspace";
47
- export type { FrameContextValue } from "./FrameContext";
@@ -1,91 +0,0 @@
1
- import { cn } from "./cn";
2
- import { useContext } from "react";
3
- import { FrameContext } from "./FrameContext";
4
- import type { BaseCalloutProps, BaseFigureProps, MediaFigureProps, ObjectEntityProps, TextProps } from "./types";
5
- import { createScopedObjectEntityId } from "../document-model/objectEntityModel";
6
-
7
- export function ObjectEntity({
8
- as: Element = "span",
9
- objectId,
10
- kind,
11
- label,
12
- parentId,
13
- pageId,
14
- blockId,
15
- frameKey,
16
- chainId,
17
- source,
18
- metadata,
19
- children,
20
- ...entityProps
21
- }: ObjectEntityProps) {
22
- const frame = useContext(FrameContext);
23
- const resolvedParentId = parentId ?? frame?.objectId;
24
- const resolvedPageId = pageId ?? frame?.pageId;
25
- const resolvedFrameKey = frameKey ?? frame?.frameKey;
26
- const resolvedObjectId = createScopedObjectEntityId(kind, resolvedParentId, objectId);
27
-
28
- return (
29
- <Element
30
- {...entityProps}
31
- data-openpress-object-id={resolvedObjectId}
32
- data-openpress-object-kind={kind}
33
- data-openpress-object-label={label}
34
- data-openpress-object-parent-id={resolvedParentId}
35
- data-openpress-object-page-id={resolvedPageId}
36
- data-openpress-block-id={blockId}
37
- data-openpress-object-frame-key={resolvedFrameKey}
38
- data-openpress-object-chain-id={chainId}
39
- data-openpress-object-source={source ? JSON.stringify(source) : undefined}
40
- data-openpress-object-metadata={metadata ? JSON.stringify(metadata) : undefined}
41
- >
42
- {children}
43
- </Element>
44
- );
45
- }
46
-
47
- export function Text(props: TextProps) {
48
- return <ObjectEntity {...props} kind="text" />;
49
- }
50
-
51
- export function BaseFigure({ caption, className, children, ...figureProps }: BaseFigureProps) {
52
- return (
53
- <figure {...figureProps} className={cn("openpress-figure", className)}>
54
- <div data-figure-body>{children}</div>
55
- {caption === undefined ? null : <figcaption>{caption}</figcaption>}
56
- </figure>
57
- );
58
- }
59
-
60
- export function BaseCallout({ kind = "info", className, children, ...calloutProps }: BaseCalloutProps) {
61
- return (
62
- <aside {...calloutProps} className={cn("openpress-callout", className)} data-callout-kind={kind}>
63
- {children}
64
- </aside>
65
- );
66
- }
67
-
68
- export function MediaFigure({
69
- src,
70
- alt,
71
- caption,
72
- className,
73
- imgClassName,
74
- loading = "eager",
75
- ...figureProps
76
- }: MediaFigureProps) {
77
- return (
78
- <BaseFigure {...figureProps} className={cn("openpress-media-figure", className)} caption={caption}>
79
- <img src={resolveMediaSrc(src)} alt={alt} loading={loading} className={imgClassName} />
80
- </BaseFigure>
81
- );
82
- }
83
-
84
- export const ImageFigure = MediaFigure;
85
-
86
- function resolveMediaSrc(src: string) {
87
- const trimmed = String(src ?? "").trim();
88
- if (!trimmed) return "";
89
- if (/^(?:[a-z][a-z0-9+.-]*:|\/)/i.test(trimmed)) return trimmed;
90
- return `/openpress/media/${trimmed.replace(/^\.?\/*/, "")}`;
91
- }
@@ -1,236 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
2
- import type { EditableSourceRef, ObjectEntityKind } from "../document-model/documentTypes";
3
-
4
- // ---------------------------------------------------------------------------
5
- // Frame / MdxArea / Press primitives
6
- // ---------------------------------------------------------------------------
7
-
8
- // `role` is opaque to core. Helpers and themes interpret it; the engine
9
- // never branches on its value. Format convention is dotted, e.g.
10
- // "manuscript.cover", "manuscript.content", "folio.page".
11
- export type FrameRole = string;
12
-
13
- export type FrameProps = Omit<HTMLAttributes<HTMLElement>, "role" | "children"> & {
14
- frameKey: string;
15
- role?: FrameRole;
16
- chrome?: boolean;
17
- className?: string;
18
- children?: ReactNode;
19
- };
20
-
21
- export type MdxAreaOverflow = "extend" | "truncate" | "error";
22
-
23
- export type MdxAreaProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
24
- chainId: string;
25
- overflow?: MdxAreaOverflow;
26
- className?: string;
27
- };
28
-
29
- // PageGeometry — a custom fixed-size geometry passed to <Press page>.
30
- // Same shape as the engine's normalized geometry (CSS lengths,
31
- // matching units between width / height).
32
- export interface PageGeometry {
33
- id?: string;
34
- label?: string;
35
- preset?: string;
36
- width: string;
37
- height: string;
38
- }
39
-
40
- // Source descriptor passed inside <Press sources>. The actual type is
41
- // the return value of mdxSource() from @open-press/core/mdx; we accept
42
- // "unknown" at the core boundary to avoid a circular type dependency.
43
- // The engine validates the shape at render time.
44
- export type PressSource = unknown;
45
-
46
- export interface PressProps {
47
- // Document tree — Frames, manuscript helpers, etc.
48
- children: ReactNode;
49
- // -------------------------------------------------------------------------
50
- // 1.0 metadata props — optional during v0.x deprecation, required in v1.0.
51
- // -------------------------------------------------------------------------
52
- // Document title. Required in 1.0. Used for PDF metadata, HTML <title>,
53
- // OG tags, and the Workspace gallery / tab-bar label.
54
- title?: string;
55
- // Page geometry preset name or a custom geometry object. Optional;
56
- // workspace default applies if not set.
57
- page?: "a4" | "social-square" | "slide-16-9" | PageGeometry;
58
- // Array of source registrations from mdxSource(). Replaces the v0.x
59
- // `export const sources` named export.
60
- sources?: ReadonlyArray<PressSource>;
61
- // URL / output slug for this Press inside a Workspace. Defaults to
62
- // "/" when only one Press exists in the Workspace; required when the
63
- // Workspace has multiple Press children.
64
- slug?: string;
65
- // Optional per-Press theme directory. Defaults to "./theme" relative
66
- // to the document file; inherits from <Workspace theme> if not set.
67
- theme?: string;
68
- // Optional per-Press components directory. Default "./components".
69
- componentsDir?: string;
70
- // Optional caption numbering overrides. Engine defaults to
71
- // { figure: "Figure", table: "Table", separator: " " }.
72
- captionNumbering?: {
73
- figure?: string;
74
- table?: string;
75
- separator?: string;
76
- };
77
- }
78
-
79
- // ---------------------------------------------------------------------------
80
- // Workspace — root component holding one or more Press children
81
- // ---------------------------------------------------------------------------
82
-
83
- export interface WorkspaceProps {
84
- // One or more <Press> children. 1 child = single-doc workspace; N
85
- // children = multi-doc workspace (proposal + pitch + social, etc).
86
- children: ReactNode;
87
- // Project label surfaced in the gallery header, tab bar, and PDF
88
- // metadata. Optional.
89
- name?: string;
90
- // Workspace-level shared theme directory. Press children that don't
91
- // set their own `theme` prop inherit from this. Default "./theme".
92
- theme?: string;
93
- // Workspace-level shared media directory. Default "./media".
94
- media?: string;
95
- }
96
-
97
- // ---------------------------------------------------------------------------
98
- // Content primitives (figure, callout)
99
- // ---------------------------------------------------------------------------
100
-
101
- export type BaseFigureProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
102
- caption?: ReactNode;
103
- children: ReactNode;
104
- };
105
-
106
- export type MediaFigureProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
107
- src: string;
108
- alt: string;
109
- caption: ReactNode;
110
- imgClassName?: string;
111
- loading?: "eager" | "lazy";
112
- };
113
-
114
- export type BaseCalloutKind = "info" | "warn" | "success" | "error" | (string & {});
115
-
116
- export type BaseCalloutProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
117
- kind?: BaseCalloutKind;
118
- children: ReactNode;
119
- };
120
-
121
- export type ObjectEntityElement = "span" | "div" | "section" | "article" | "figure" | "p";
122
-
123
- export type ObjectEntityProps = Omit<HTMLAttributes<HTMLElement>, "children"> & {
124
- as?: ObjectEntityElement;
125
- objectId: string;
126
- kind: ObjectEntityKind;
127
- label: string;
128
- parentId?: string;
129
- pageId?: string;
130
- blockId?: string;
131
- frameKey?: string;
132
- chainId?: string;
133
- source?: EditableSourceRef;
134
- metadata?: Record<string, string | number | boolean | null>;
135
- children?: ReactNode;
136
- };
137
-
138
- export type TextProps = Omit<ObjectEntityProps, "kind"> & {
139
- as?: "span" | "div" | "p";
140
- };
141
-
142
- // ---------------------------------------------------------------------------
143
- // Source descriptors and resolved sources
144
- // ---------------------------------------------------------------------------
145
-
146
- export interface MdxSourceDescriptorSectionFolders {
147
- type: "mdx";
148
- preset: "section-folders";
149
- root?: string;
150
- }
151
-
152
- export interface MdxSourceDescriptorSectionFiles {
153
- type: "mdx";
154
- preset: "section-files";
155
- root?: string;
156
- }
157
-
158
- export interface MdxSourceDescriptorFileList {
159
- type: "mdx";
160
- preset: "file-list";
161
- files: string[];
162
- }
163
-
164
- export type MdxSourceDescriptor =
165
- | MdxSourceDescriptorSectionFolders
166
- | MdxSourceDescriptorSectionFiles
167
- | MdxSourceDescriptorFileList;
168
-
169
- export type SourceDescriptor = MdxSourceDescriptor;
170
-
171
- export interface SourceNode {
172
- id: string;
173
- slug: string;
174
- title: string;
175
- meta?: Record<string, unknown>;
176
- children?: SourceNode[];
177
- }
178
-
179
- export interface OutlineItem {
180
- id: string;
181
- depth: number;
182
- title: string;
183
- sectionSlug: string;
184
- pageNumber?: number;
185
- }
186
-
187
- export interface TocEntry {
188
- id: string;
189
- blockId: string;
190
- sourceId: string;
191
- sectionSlug: string;
192
- title: string;
193
- href: string;
194
- level: 2 | 3;
195
- label: string;
196
- pageNumber?: number;
197
- }
198
-
199
- export interface SourceFileRecord {
200
- path: string;
201
- absolutePath: string;
202
- sectionSlug: string;
203
- }
204
-
205
- export interface SourceBlock {
206
- id: string;
207
- kind: string;
208
- name?: string;
209
- chainId: string;
210
- sectionSlug: string;
211
- path: string;
212
- source: {
213
- file: string;
214
- line?: number;
215
- column?: number;
216
- offset?: number;
217
- };
218
- }
219
-
220
- export interface ResolvedSource {
221
- id: string;
222
- type: "mdx";
223
- tree: SourceNode[];
224
- outline: OutlineItem[];
225
- chains: Record<string, SourceBlock[]>;
226
- files: SourceFileRecord[];
227
- }
228
-
229
- // ---------------------------------------------------------------------------
230
- // Allocation context shape (engine -> Frame -> MdxArea)
231
- // ---------------------------------------------------------------------------
232
-
233
- // Per-frame, per-chain, ordered list of React nodes assigned to each
234
- // MdxArea by area index.
235
- export type FrameAllocation = Record<string, Record<string, ReactNode[]>>;
236
-
@@ -1,28 +0,0 @@
1
- import { useContext } from "react";
2
- import { PressContext } from "./Press";
3
- import type { ResolvedSource } from "./types";
4
-
5
- // Read a resolved source by its registered key. The engine populates the
6
- // PressContext before rendering, so this is synchronous and safe to call
7
- // from any component inside <Press>.
8
- //
9
- // Throws if the source is missing, with a hint listing known sources.
10
- export function useSource<T extends ResolvedSource = ResolvedSource>(id: string): T {
11
- const ctx = useContext(PressContext);
12
- if (!ctx) {
13
- throw new Error(
14
- `useSource("${id}") called outside <Press> tree. ` +
15
- `Source hooks only work inside the default-exported <Press> component.`,
16
- );
17
- }
18
- const source = ctx.sources[id];
19
- if (!source) {
20
- const known = Object.keys(ctx.sources).sort();
21
- const knownText = known.length > 0 ? known.join(", ") : "(none)";
22
- throw new Error(
23
- `Unknown source "${id}". Available sources: ${knownText}. ` +
24
- `Register it as a <Press sources={[mdxSource({ id: "${id}", ... })]}> entry in press/index.tsx.`,
25
- );
26
- }
27
- return source as T;
28
- }
@@ -1,27 +0,0 @@
1
- // Anchor → page-index resolution shared between the public viewer and
2
- // the workbench. Lives in its own module so React Fast Refresh can keep
3
- // `PublicPage` / `HtmlWorkbench` HMR-clean (Fast Refresh expects component
4
- // files to export only components).
5
-
6
- import type { DisplayPage } from "../reader";
7
-
8
- export function createAnchorPageMap(pages: DisplayPage[]) {
9
- const map = new Map<string, number>();
10
- pages.forEach((page, index) => {
11
- page.anchors?.forEach((anchor) => {
12
- if (anchor && !map.has(anchor)) map.set(anchor, index);
13
- });
14
- });
15
- return map;
16
- }
17
-
18
- export function resolveAnchorPageIndex(
19
- anchorPageMap: Map<string, number>,
20
- pageCount: number,
21
- anchorId: string,
22
- pageIndex?: number,
23
- ): number | null {
24
- if (typeof pageIndex === "number" && Number.isInteger(pageIndex) && pageIndex >= 0 && pageIndex < pageCount) return pageIndex;
25
- const mapped = anchorPageMap.get(anchorId);
26
- return mapped === undefined ? null : mapped;
27
- }