@open-press/cli 0.7.1 → 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 +29 -13
- package/dist/cli.js +44 -195
- package/package.json +4 -5
- package/template/core/AGENTS.md +18 -14
- package/template/core/CHANGELOG.md +57 -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/dev.mjs +2 -2
- 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 +110 -3
- package/template/core/engine/output/static-server.mjs +87 -9
- package/template/core/engine/react/comment-endpoint.mjs +13 -39
- package/template/core/engine/react/comment-marker.mjs +43 -19
- package/template/core/engine/react/document-entry.mjs +46 -28
- package/template/core/engine/react/document-export.mjs +328 -164
- package/template/core/engine/react/http-json.mjs +24 -0
- package/template/core/engine/react/mdx-compile.mjs +126 -3
- package/template/core/engine/react/measurement-css.mjs +114 -1
- package/template/core/engine/react/object-entities.mjs +204 -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 +41 -72
- package/template/core/engine/react/pipeline/frame-measurement.mjs +6 -0
- package/template/core/engine/react/press-tree-inspection.mjs +172 -0
- package/template/core/engine/react/project-asset-endpoint.mjs +6 -24
- package/template/core/engine/react/source-edit-endpoint.d.mts +10 -0
- package/template/core/engine/react/source-edit-endpoint.mjs +75 -0
- package/template/core/engine/react/sources/mdx-resolver.mjs +13 -15
- package/template/core/engine/react/style-discovery.mjs +23 -8
- 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/file-walk.mjs +22 -0
- package/template/core/engine/runtime/inspection.mjs +1 -20
- package/template/core/engine/runtime/page-geometry.mjs +131 -0
- package/template/core/engine/runtime/path-utils.mjs +20 -0
- package/template/core/engine/runtime/source-text-tools.d.mts +102 -0
- package/template/core/engine/runtime/source-text-tools.mjs +551 -16
- package/template/core/engine/runtime/source-workspace.mjs +16 -34
- 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/main.tsx +2 -2
- package/template/core/src/openpress/app/OpenPressApp.tsx +296 -0
- package/template/core/src/openpress/{renderer.tsx → app/OpenPressRuntime.tsx} +20 -9
- package/template/core/src/openpress/app/WorkspaceGalleryPage.tsx +219 -0
- package/template/core/src/openpress/app/index.ts +2 -0
- package/template/core/src/openpress/core/Frame.tsx +26 -15
- package/template/core/src/openpress/core/FrameContext.tsx +10 -3
- package/template/core/src/openpress/core/MdxArea.tsx +11 -12
- 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/cn.ts +4 -0
- package/template/core/src/openpress/core/index.tsx +11 -3
- package/template/core/src/openpress/core/primitives.tsx +74 -6
- package/template/core/src/openpress/core/types.ts +94 -41
- package/template/core/src/openpress/core/useSource.ts +1 -1
- package/template/core/src/openpress/{anchorMap.ts → document-model/anchorMapModel.ts} +1 -1
- package/template/core/src/openpress/{indexes.ts → document-model/documentIndexes.ts} +1 -1
- package/template/core/src/openpress/{types.ts → document-model/documentTypes.ts} +51 -0
- package/template/core/src/openpress/document-model/index.ts +7 -0
- package/template/core/src/openpress/document-model/objectEntityModel.ts +55 -0
- package/template/core/src/openpress/{projectIdentity.ts → document-model/projectIdentityModel.ts} +1 -1
- package/template/core/src/openpress/{reactDocumentMetadata.ts → document-model/reactDocumentMetadataModel.ts} +1 -1
- package/template/core/src/openpress/document-model/workspaceManifestModel.ts +57 -0
- package/template/core/src/openpress/manuscript/index.tsx +49 -7
- 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/{publicPage.tsx → reader/PublicReaderPage.tsx} +31 -51
- package/template/core/src/openpress/{workbenchPanels.tsx → reader/ReaderNavigationPanel.tsx} +6 -5
- package/template/core/src/openpress/reader/index.ts +11 -0
- package/template/core/src/openpress/reader/pageViewportScaleModel.ts +73 -0
- package/template/core/src/openpress/reader/readerTypes.ts +4 -0
- package/template/core/src/openpress/reader/usePageViewportScale.ts +119 -0
- package/template/core/src/openpress/reader/usePanelState.ts +56 -0
- package/template/core/src/openpress/reader/useReaderHashSync.ts +61 -0
- package/template/core/src/openpress/reader/useReaderKeyboardNav.ts +48 -0
- package/template/core/src/openpress/reader/useReaderRuntime.ts +146 -0
- package/template/core/src/openpress/reader/useReaderScrollAnchor.ts +64 -0
- package/template/core/src/openpress/shared/Panel.tsx +77 -0
- package/template/core/src/openpress/shared/index.ts +4 -0
- package/template/core/src/openpress/shared/numberUtils.ts +3 -0
- package/template/core/src/openpress/{runtimeMode.ts → shared/runtimeMode.ts} +0 -11
- package/template/core/src/openpress/workbench/Workbench.tsx +506 -0
- package/template/core/src/openpress/workbench/actions/DeploymentControl.tsx +157 -0
- package/template/core/src/openpress/workbench/actions/ExportImageControl.tsx +96 -0
- package/template/core/src/openpress/workbench/actions/PageZoomControl.tsx +182 -0
- package/template/core/src/openpress/workbench/actions/SearchControl.tsx +345 -0
- package/template/core/src/openpress/workbench/actions/deploymentStatusModel.ts +112 -0
- package/template/core/src/openpress/workbench/actions/index.ts +6 -0
- package/template/core/src/openpress/workbench/actions/useDeploymentWorkbench.ts +136 -0
- package/template/core/src/openpress/workbench/dialog/WorkbenchDialog.tsx +72 -0
- package/template/core/src/openpress/workbench/dialog/index.ts +1 -0
- package/template/core/src/openpress/workbench/document/components/DocumentPanel.tsx +127 -0
- package/template/core/src/openpress/workbench/document/components/InlineSourceEditorLayer.tsx +207 -0
- package/template/core/src/openpress/workbench/document/components/ReaderStage.tsx +9 -0
- package/template/core/src/openpress/workbench/document/hooks/useDocumentWorkbenchModel.ts +34 -0
- package/template/core/src/openpress/workbench/document/hooks/useInlineDocumentEditor.ts +525 -0
- package/template/core/src/openpress/workbench/document/index.ts +10 -0
- package/template/core/src/openpress/workbench/index.ts +2 -0
- package/template/core/src/openpress/workbench/inspector/InlineInspectorLayer.tsx +459 -0
- package/template/core/src/openpress/workbench/inspector/index.ts +5 -0
- package/template/core/src/openpress/workbench/inspector/inlineCommentModel.ts +125 -0
- package/template/core/src/openpress/workbench/inspector/inspectorGeometryModel.ts +160 -0
- package/template/core/src/openpress/workbench/inspector/inspectorModel.ts +408 -0
- package/template/core/src/openpress/workbench/inspector/useInspectorComments.ts +254 -0
- package/template/core/src/openpress/workbench/mentions/MentionSuggestionList.tsx +41 -0
- package/template/core/src/openpress/workbench/mentions/index.ts +2 -0
- package/template/core/src/openpress/{composerMentions.ts → workbench/mentions/useComposerMentions.ts} +1 -4
- package/template/core/src/openpress/workbench/panels/Panel.tsx +1 -0
- package/template/core/src/openpress/workbench/panels/PendingCommentsPanel.tsx +80 -0
- package/template/core/src/openpress/workbench/panels/WorkbenchControlPanel.tsx +29 -0
- package/template/core/src/openpress/workbench/panels/index.ts +3 -0
- package/template/core/src/openpress/workbench/project/ProjectEntryPanel.tsx +525 -0
- package/template/core/src/openpress/workbench/project/ProjectPreviewDialog.tsx +35 -0
- package/template/core/src/openpress/workbench/project/index.ts +2 -0
- package/template/core/src/openpress/workbench/project/projectPreviewTypes.ts +11 -0
- package/template/core/src/openpress/workbench/shell/WorkbenchShell.tsx +167 -0
- package/template/core/src/openpress/workbench/shell/index.ts +1 -0
- package/template/core/src/openpress/workbench/workbenchFormatters.ts +120 -0
- package/template/core/src/openpress/workbench/workbenchTypes.ts +35 -0
- package/template/core/src/styles/openpress/print-route.css +0 -2
- package/template/core/src/styles/openpress/{project-workspace.css → project-preview-panel.css} +13 -407
- package/template/core/src/styles/openpress/public-viewer.css +25 -320
- package/template/core/src/styles/openpress/reader-runtime.css +252 -55
- package/template/core/src/styles/openpress/responsive.css +145 -270
- package/template/core/src/styles/openpress/workbench-panels.css +327 -178
- package/template/core/src/styles/openpress/workbench.css +986 -451
- package/template/core/src/styles/openpress/workspace-gallery.css +300 -0
- package/template/core/src/styles/openpress.css +2 -1
- package/template/core/tsconfig.json +1 -1
- package/template/core/vite.config.ts +50 -0
- package/template/core/engine/commands/init.mjs +0 -24
- package/template/core/engine/init.mjs +0 -90
- package/template/core/src/openpress/App.tsx +0 -127
- package/template/core/src/openpress/inspector.ts +0 -282
- package/template/core/src/openpress/projectWorkspace.tsx +0 -919
- package/template/core/src/openpress/readerRuntime.ts +0 -230
- package/template/core/src/openpress/workbench.tsx +0 -1265
- package/template/core/src/openpress/workbenchTypes.ts +0 -4
- 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
- /package/template/core/src/openpress/{readerPageRegistry.ts → reader/readerPageRegistry.ts} +0 -0
- /package/template/core/src/openpress/{pageRoute.ts → reader/readerPageRoute.ts} +0 -0
- /package/template/core/src/openpress/{readerScroll.ts → reader/readerScroll.ts} +0 -0
- /package/template/core/src/openpress/{readerState.ts → reader/readerStateModel.ts} +0 -0
- /package/template/core/src/openpress/{frameScheduler.ts → shared/frameScheduler.ts} +0 -0
- /package/template/core/src/openpress/{projectSources.ts → workbench/project/projectSourceModel.ts} +0 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { createContext, useContext, type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
import { PanelLeftClose, PanelLeftOpen, PanelRightClose, PanelRightOpen, X } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
type WorkbenchShellContextValue = {
|
|
5
|
+
leftPanelOpen: boolean;
|
|
6
|
+
rightPanelOpen: boolean;
|
|
7
|
+
onToggleLeftPanel: () => void;
|
|
8
|
+
onToggleRightPanel: () => void;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const WorkbenchShellContext = createContext<WorkbenchShellContextValue | null>(null);
|
|
12
|
+
|
|
13
|
+
function useWorkbenchShell() {
|
|
14
|
+
const value = useContext(WorkbenchShellContext);
|
|
15
|
+
if (!value) throw new Error("WorkbenchShell compound components must be rendered inside <WorkbenchShell>.");
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function WorkbenchShellRoot({
|
|
20
|
+
style,
|
|
21
|
+
devMode,
|
|
22
|
+
viewMode,
|
|
23
|
+
inspectorMode,
|
|
24
|
+
editMode = false,
|
|
25
|
+
leftPanelOpen,
|
|
26
|
+
rightPanelOpen,
|
|
27
|
+
onToggleLeftPanel,
|
|
28
|
+
onToggleRightPanel,
|
|
29
|
+
children,
|
|
30
|
+
}: {
|
|
31
|
+
style: CSSProperties;
|
|
32
|
+
devMode: boolean;
|
|
33
|
+
viewMode: string;
|
|
34
|
+
inspectorMode: boolean;
|
|
35
|
+
editMode?: boolean;
|
|
36
|
+
leftPanelOpen: boolean;
|
|
37
|
+
rightPanelOpen: boolean;
|
|
38
|
+
onToggleLeftPanel: () => void;
|
|
39
|
+
onToggleRightPanel: () => void;
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
}) {
|
|
42
|
+
const scrimOpen = leftPanelOpen || rightPanelOpen;
|
|
43
|
+
const handleScrimClick = rightPanelOpen ? onToggleRightPanel : onToggleLeftPanel;
|
|
44
|
+
const shellClassName = [
|
|
45
|
+
"reader-app openpress-reader-app openpress-public-viewer openpress-dev-public-viewer openpress-workbench-shell is-ready",
|
|
46
|
+
leftPanelOpen ? "" : "is-closed-left",
|
|
47
|
+
rightPanelOpen ? "" : "is-closed-right",
|
|
48
|
+
].filter(Boolean).join(" ");
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<WorkbenchShellContext.Provider value={{ leftPanelOpen, rightPanelOpen, onToggleLeftPanel, onToggleRightPanel }}>
|
|
52
|
+
<main className="openpress-workbench" style={style} data-dev-mode={devMode ? "true" : "false"}>
|
|
53
|
+
<div
|
|
54
|
+
className={shellClassName}
|
|
55
|
+
data-openpress-react-runtime="true"
|
|
56
|
+
data-openpress-view-mode={viewMode}
|
|
57
|
+
data-openpress-inspector-mode={inspectorMode ? "on" : "off"}
|
|
58
|
+
data-openpress-edit-mode={editMode ? "on" : "off"}
|
|
59
|
+
data-openpress-workbench-shell
|
|
60
|
+
data-testid="workbench-shell"
|
|
61
|
+
>
|
|
62
|
+
{scrimOpen ? (
|
|
63
|
+
<div className="openpress-public-scrim" aria-hidden="true" onClick={handleScrimClick} />
|
|
64
|
+
) : null}
|
|
65
|
+
{children}
|
|
66
|
+
</div>
|
|
67
|
+
</main>
|
|
68
|
+
</WorkbenchShellContext.Provider>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function WorkbenchToolbar({ children }: { children: ReactNode }) {
|
|
73
|
+
const {
|
|
74
|
+
leftPanelOpen,
|
|
75
|
+
rightPanelOpen,
|
|
76
|
+
onToggleLeftPanel,
|
|
77
|
+
onToggleRightPanel,
|
|
78
|
+
} = useWorkbenchShell();
|
|
79
|
+
const LeftIcon = leftPanelOpen ? PanelLeftClose : PanelLeftOpen;
|
|
80
|
+
const RightIcon = rightPanelOpen ? PanelRightClose : PanelRightOpen;
|
|
81
|
+
const leftLabel = leftPanelOpen ? "收合左側面板" : "展開左側面板";
|
|
82
|
+
const rightLabel = rightPanelOpen ? "收合右側面板" : "展開右側面板";
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<header
|
|
86
|
+
className="openpress-workbench-toolbar"
|
|
87
|
+
role="toolbar"
|
|
88
|
+
aria-label="工作台操作"
|
|
89
|
+
data-openpress-workbench-toolbar
|
|
90
|
+
>
|
|
91
|
+
<button
|
|
92
|
+
type="button"
|
|
93
|
+
className="openpress-workbench-toolbar-panel-toggle"
|
|
94
|
+
data-openpress-toggle-left-panel
|
|
95
|
+
data-openpress-panel-open={leftPanelOpen ? "true" : "false"}
|
|
96
|
+
aria-label={leftLabel}
|
|
97
|
+
title={leftLabel}
|
|
98
|
+
onClick={onToggleLeftPanel}
|
|
99
|
+
>
|
|
100
|
+
<LeftIcon aria-hidden="true" />
|
|
101
|
+
</button>
|
|
102
|
+
<div className="openpress-workbench-toolbar__content">
|
|
103
|
+
{children}
|
|
104
|
+
</div>
|
|
105
|
+
<button
|
|
106
|
+
type="button"
|
|
107
|
+
className="openpress-workbench-toolbar-panel-toggle"
|
|
108
|
+
data-openpress-toggle-right-panel
|
|
109
|
+
data-openpress-panel-open={rightPanelOpen ? "true" : "false"}
|
|
110
|
+
aria-label={rightLabel}
|
|
111
|
+
title={rightLabel}
|
|
112
|
+
onClick={onToggleRightPanel}
|
|
113
|
+
>
|
|
114
|
+
<RightIcon aria-hidden="true" />
|
|
115
|
+
</button>
|
|
116
|
+
</header>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function WorkbenchLeftPanel({ children }: { children: ReactNode }) {
|
|
121
|
+
return (
|
|
122
|
+
<aside
|
|
123
|
+
className="reader-side-nav openpress-workspace-panel openpress-workbench-left-panel openpress-public-navigation"
|
|
124
|
+
aria-label="文件導覽"
|
|
125
|
+
data-openpress-left-panel
|
|
126
|
+
>
|
|
127
|
+
{children}
|
|
128
|
+
</aside>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function WorkbenchRightPanel({ children }: { children: ReactNode }) {
|
|
133
|
+
const { onToggleRightPanel } = useWorkbenchShell();
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<aside
|
|
137
|
+
className="openpress-workspace-panel openpress-workbench-right-panel openpress-dev-public-navigation"
|
|
138
|
+
aria-label="控制面板"
|
|
139
|
+
data-openpress-right-panel
|
|
140
|
+
>
|
|
141
|
+
<button type="button" className="openpress-public-drawer-close" aria-label="關閉右側面板" onClick={onToggleRightPanel}>
|
|
142
|
+
<X size={16} aria-hidden="true" />
|
|
143
|
+
</button>
|
|
144
|
+
{children}
|
|
145
|
+
</aside>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function WorkbenchMainContent({ children }: { children: ReactNode }) {
|
|
150
|
+
return (
|
|
151
|
+
<section
|
|
152
|
+
className="openpress-workbench__stage openpress-workbench-main openpress-public-viewer__stage openpress-dev-main-content"
|
|
153
|
+
aria-label="主要內容"
|
|
154
|
+
data-openpress-main-content
|
|
155
|
+
>
|
|
156
|
+
{children}
|
|
157
|
+
</section>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export const WorkbenchShell = Object.assign(WorkbenchShellRoot, {
|
|
162
|
+
Toolbar: WorkbenchToolbar,
|
|
163
|
+
LeftPanel: WorkbenchLeftPanel,
|
|
164
|
+
RightPanel: WorkbenchRightPanel,
|
|
165
|
+
ControlPanel: WorkbenchRightPanel,
|
|
166
|
+
MainContent: WorkbenchMainContent,
|
|
167
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./WorkbenchShell";
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { InspectorPlacement } from "./inspector";
|
|
2
|
+
import type { ObjectEntity, SourceBlock, Theme } from "../document-model";
|
|
3
|
+
import type { PendingCommentsStatus, InspectorCommentStatus } from "./workbenchTypes";
|
|
4
|
+
|
|
5
|
+
export type PageGeometrySpec = {
|
|
6
|
+
label: string;
|
|
7
|
+
dimensions: string;
|
|
8
|
+
title: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const DEFAULT_PAGE_GEOMETRY = {
|
|
12
|
+
pageWidth: "210mm",
|
|
13
|
+
pageHeight: "297mm",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export function formatInspectorSelection(block: SourceBlock | null, entity?: ObjectEntity | null) {
|
|
17
|
+
if (entity) return entity.label;
|
|
18
|
+
if (!block) return "未選取";
|
|
19
|
+
const line = block.source?.line;
|
|
20
|
+
return line ? `${block.path}:${line}` : block.path;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function formatInspectorCommentStatus(status: InspectorCommentStatus, error: string) {
|
|
24
|
+
if (status === "submitting") return "寫入中";
|
|
25
|
+
if (status === "saved") return "已寫入 source";
|
|
26
|
+
if (status === "failed") return error || "寫入失敗";
|
|
27
|
+
return "";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function formatCommentsCount(count: number, status: PendingCommentsStatus) {
|
|
31
|
+
if (status === "loading") return "正在讀取";
|
|
32
|
+
if (status === "clearing") return "正在清除";
|
|
33
|
+
return `${count} 則待處理`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function formatPageGeometrySpec(theme?: Pick<Theme, "pageLabel" | "pageWidth" | "pageHeight">): PageGeometrySpec {
|
|
37
|
+
const width = parseCssLength(theme?.pageWidth ?? DEFAULT_PAGE_GEOMETRY.pageWidth);
|
|
38
|
+
const height = parseCssLength(theme?.pageHeight ?? DEFAULT_PAGE_GEOMETRY.pageHeight);
|
|
39
|
+
const dimensions = formatLengthPair(width, height);
|
|
40
|
+
const label = theme?.pageLabel?.trim() || pageGeometryLabel(width, height);
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
label,
|
|
44
|
+
dimensions,
|
|
45
|
+
title: `${label} · ${dimensions}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function parseCommentHint(hint?: string) {
|
|
50
|
+
if (!hint?.startsWith("openpress-react-inspector")) return null;
|
|
51
|
+
const intent = hint.match(/\bintent=(add|edit|delete)\b/)?.[1];
|
|
52
|
+
const placement = hint.match(/\bplacement=(block|before)\b/)?.[1] as InspectorPlacement | undefined;
|
|
53
|
+
const targetObjectId = decodeHintValue(hint.match(/\btarget=([^\s]+)/)?.[1]);
|
|
54
|
+
const intentLabel = intent === "add" ? "Add" : intent === "delete" ? "Remove" : "Edit";
|
|
55
|
+
const placementLabel = placement === "before" ? "插入於區塊前" : "針對目前區塊";
|
|
56
|
+
return { intent: intent ?? "edit", intentLabel, placement: placement ?? "block", placementLabel, targetObjectId };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function formatCommentTimestamp(value: string) {
|
|
60
|
+
const date = new Date(value);
|
|
61
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
62
|
+
return new Intl.DateTimeFormat("zh-TW", {
|
|
63
|
+
month: "2-digit",
|
|
64
|
+
day: "2-digit",
|
|
65
|
+
hour: "2-digit",
|
|
66
|
+
minute: "2-digit",
|
|
67
|
+
hour12: false,
|
|
68
|
+
}).format(date);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function pageGeometryLabel(width: CssLength, height: CssLength) {
|
|
72
|
+
if (matchesPageSize(width, height, "210", "297", "mm")) return "A4 Page";
|
|
73
|
+
if (matchesPageSize(width, height, "176", "250", "mm")) return "B5 Page";
|
|
74
|
+
if (matchesPageSize(width, height, "215.9", "279.4", "mm")) return "Letter Page";
|
|
75
|
+
if (isSixteenByNine(width, height)) return "16:9 Page";
|
|
76
|
+
return "Custom Page";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
type CssLength = {
|
|
80
|
+
raw: string;
|
|
81
|
+
value: string | null;
|
|
82
|
+
unit: string | null;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
function parseCssLength(value: string): CssLength {
|
|
86
|
+
const raw = value.trim();
|
|
87
|
+
const match = raw.match(/^(-?\d+(?:\.\d+)?)([a-z%]+)$/i);
|
|
88
|
+
if (!match) return { raw, value: null, unit: null };
|
|
89
|
+
return { raw, value: trimTrailingZeroes(match[1]), unit: match[2] };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function formatLengthPair(width: CssLength, height: CssLength) {
|
|
93
|
+
if (width.value && height.value && width.unit && width.unit === height.unit) {
|
|
94
|
+
return `${width.value} × ${height.value} ${width.unit}`;
|
|
95
|
+
}
|
|
96
|
+
return `${width.raw} × ${height.raw}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function matchesPageSize(width: CssLength, height: CssLength, targetWidth: string, targetHeight: string, unit: string) {
|
|
100
|
+
return width.value === targetWidth && height.value === targetHeight && width.unit === unit && height.unit === unit;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isSixteenByNine(width: CssLength, height: CssLength) {
|
|
104
|
+
if (!width.value || !height.value || !width.unit || width.unit !== height.unit) return false;
|
|
105
|
+
const ratio = Number(width.value) / Number(height.value);
|
|
106
|
+
return ratio > 1 && Math.abs(ratio - (16 / 9)) < 0.02;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function decodeHintValue(value?: string) {
|
|
110
|
+
if (!value) return undefined;
|
|
111
|
+
try {
|
|
112
|
+
return decodeURIComponent(value);
|
|
113
|
+
} catch {
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function trimTrailingZeroes(value: string) {
|
|
119
|
+
return value.replace(/\.0+$/, "").replace(/(\.\d*?)0+$/, "$1");
|
|
120
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { InspectorPlacement, ObjectSelection } from "./inspector/inspectorModel";
|
|
2
|
+
|
|
3
|
+
export type DeployStatus = "idle" | "deploying" | "deployed" | "unavailable" | "failed" | "setup";
|
|
4
|
+
export type PdfActionStatus = "idle" | "generating" | "opening" | "failed";
|
|
5
|
+
export type InspectorCommentStatus = "idle" | "submitting" | "saved" | "failed";
|
|
6
|
+
export type PendingCommentsStatus = "idle" | "loading" | "ready" | "failed" | "clearing";
|
|
7
|
+
|
|
8
|
+
export interface InlineSavedComment {
|
|
9
|
+
id: string;
|
|
10
|
+
objectId?: string;
|
|
11
|
+
blockId?: string;
|
|
12
|
+
placement: InspectorPlacement;
|
|
13
|
+
note: string;
|
|
14
|
+
path?: string;
|
|
15
|
+
line?: number;
|
|
16
|
+
timestamp?: string;
|
|
17
|
+
markerLabel?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface InlineSavedCommentMarkerEntry {
|
|
21
|
+
target: ObjectSelection;
|
|
22
|
+
comments: InlineSavedComment[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface InspectorLayerRect {
|
|
26
|
+
top: number;
|
|
27
|
+
left: number;
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface InspectorInsertTargetView {
|
|
33
|
+
blockId: string;
|
|
34
|
+
rect: InspectorLayerRect;
|
|
35
|
+
}
|