@puredesktop/puredesktop-ui-bridge 2.1.7 → 2.1.8

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 (64) hide show
  1. package/package.json +55 -1
  2. package/src/bridge/agentTypes.ts +21 -1
  3. package/src/bridge/collectionImagePaste.ts +19 -1
  4. package/src/bridge/context.mjs +32 -0
  5. package/src/bridge/documents.d.mts +76 -0
  6. package/src/bridge/documents.mjs +40 -0
  7. package/src/bridge/methods.d.mts +23 -0
  8. package/src/bridge/methods.mjs +23 -0
  9. package/src/bridge/pureRender/base.css +44 -0
  10. package/src/bridge/pureRender/document.ts +29 -2
  11. package/src/bridge/pureRender/index.ts +3 -0
  12. package/src/bridge/pureRender/normalize.ts +167 -0
  13. package/src/bridge/pureRender/sanitizeExportBody.test.ts +51 -0
  14. package/src/bridge/pureRender/sanitizeExportBody.ts +61 -0
  15. package/src/bridge/pureRender/styles.ts +125 -5
  16. package/src/bridge/pureRender/theme.test.ts +259 -0
  17. package/src/bridge/pureRender/theme.ts +19 -1
  18. package/src/bridge/pureRender/types.ts +33 -0
  19. package/src/bridge/pureRender/visualLayoutInspection.test.ts +26 -0
  20. package/src/bridge/pureRender/visualLayoutInspection.ts +75 -0
  21. package/src/bridge/react/useDocumentHotkeys.ts +41 -0
  22. package/src/bridge/react/useDocumentLifecycle.tsx +359 -0
  23. package/src/bridge/react/usePlatformAppSettings.test.tsx +105 -0
  24. package/src/bridge/react/usePlatformAppSettings.tsx +104 -0
  25. package/src/bridge/react/usePlatformJsonStore.test.tsx +152 -0
  26. package/src/bridge/react/usePlatformJsonStore.tsx +149 -0
  27. package/src/bridge/storage.d.mts +6 -6
  28. package/src/bridge/storage.test.ts +6 -6
  29. package/src/bridge/types.ts +7 -0
  30. package/src/components/agents/AgentDrawerPanel.tsx +2 -0
  31. package/src/components/agents/AgentMessageList.tsx +6 -1
  32. package/src/components/agents/AgentToolCallCard.tsx +20 -20
  33. package/src/components/agents/ContextPicker.tsx +239 -0
  34. package/src/components/agents/agentPanelStyles.ts +3 -2
  35. package/src/components/agents/agentTypes.ts +2 -0
  36. package/src/components/chrome/WorkspaceTabStrip.tsx +18 -1
  37. package/src/components/chrome/workspaceTabTypes.ts +2 -0
  38. package/src/components/common/containers/AppFrame.test.tsx +4 -4
  39. package/src/components/common/containers/AppFrame.tsx +10 -1
  40. package/src/components/common/containers/AppHeader.tsx +22 -0
  41. package/src/components/common/documents/DocumentHeaderActions.tsx +206 -0
  42. package/src/components/common/documents/DocumentSwitcher.tsx +1176 -0
  43. package/src/components/common/documents/index.ts +8 -0
  44. package/src/components/common/research/EvidenceDossier.tsx +1232 -150
  45. package/src/components/common/research/index.ts +2 -0
  46. package/src/components/print-design/PrintDesignPanel.test.tsx +430 -40
  47. package/src/components/print-design/PrintDesignPanel.tsx +1770 -207
  48. package/src/components/print-design/index.ts +2 -0
  49. package/src/components/print-design/previewContent.test.ts +32 -0
  50. package/src/components/print-design/previewContent.ts +31 -0
  51. package/src/context/buildContextDocument.test.ts +240 -0
  52. package/src/context/buildContextDocument.ts +309 -0
  53. package/src/context/contextAccess.ts +66 -0
  54. package/src/context/contextConfig.ts +72 -0
  55. package/src/context/contextDocument.test.ts +155 -0
  56. package/src/context/contextDocument.ts +300 -0
  57. package/src/context/contextSections.test.ts +88 -0
  58. package/src/context/contextSections.ts +84 -0
  59. package/src/context/htmlToContextMarkdown.test.ts +134 -0
  60. package/src/context/htmlToContextMarkdown.ts +369 -0
  61. package/src/theme/appAccents.test.ts +36 -35
  62. package/src/theme/appAccents.ts +87 -104
  63. package/src/theme/appIdentityCss.mjs +169 -231
  64. package/src/theme/appIdentityCss.ts +213 -233
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@puredesktop/puredesktop-ui-bridge",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "PureScience plugin SDK — bridge client, theme, and shared UI",
5
5
  "type": "module",
6
6
  "repository": {
@@ -113,6 +113,9 @@
113
113
  "./bridge/dialog.mjs": "./src/bridge/dialog.mjs",
114
114
  "./bridge/dialog": "./src/bridge/dialog.mjs",
115
115
  "./bridge/dialog.js": "./src/bridge/dialog.mjs",
116
+ "./bridge/documents.mjs": "./src/bridge/documents.mjs",
117
+ "./bridge/documents": "./src/bridge/documents.mjs",
118
+ "./bridge/documents.js": "./src/bridge/documents.mjs",
116
119
  "./bridge/events.mjs": "./src/bridge/events.mjs",
117
120
  "./bridge/events": "./src/bridge/events.mjs",
118
121
  "./bridge/events.js": "./src/bridge/events.mjs",
@@ -190,6 +193,9 @@
190
193
  "./bridge/pureRender/samples.ts": "./src/bridge/pureRender/samples.ts",
191
194
  "./bridge/pureRender/samples": "./src/bridge/pureRender/samples.ts",
192
195
  "./bridge/pureRender/samples.js": "./src/bridge/pureRender/samples.ts",
196
+ "./bridge/pureRender/sanitizeExportBody.ts": "./src/bridge/pureRender/sanitizeExportBody.ts",
197
+ "./bridge/pureRender/sanitizeExportBody": "./src/bridge/pureRender/sanitizeExportBody.ts",
198
+ "./bridge/pureRender/sanitizeExportBody.js": "./src/bridge/pureRender/sanitizeExportBody.ts",
193
199
  "./bridge/pureRender/styles.ts": "./src/bridge/pureRender/styles.ts",
194
200
  "./bridge/pureRender/styles": "./src/bridge/pureRender/styles.ts",
195
201
  "./bridge/pureRender/styles.js": "./src/bridge/pureRender/styles.ts",
@@ -207,6 +213,12 @@
207
213
  "./bridge/react/useDebouncedEffect.ts": "./src/bridge/react/useDebouncedEffect.ts",
208
214
  "./bridge/react/useDebouncedEffect": "./src/bridge/react/useDebouncedEffect.ts",
209
215
  "./bridge/react/useDebouncedEffect.js": "./src/bridge/react/useDebouncedEffect.ts",
216
+ "./bridge/react/useDocumentHotkeys.ts": "./src/bridge/react/useDocumentHotkeys.ts",
217
+ "./bridge/react/useDocumentHotkeys": "./src/bridge/react/useDocumentHotkeys.ts",
218
+ "./bridge/react/useDocumentHotkeys.js": "./src/bridge/react/useDocumentHotkeys.ts",
219
+ "./bridge/react/useDocumentLifecycle.tsx": "./src/bridge/react/useDocumentLifecycle.tsx",
220
+ "./bridge/react/useDocumentLifecycle": "./src/bridge/react/useDocumentLifecycle.tsx",
221
+ "./bridge/react/useDocumentLifecycle.js": "./src/bridge/react/useDocumentLifecycle.tsx",
210
222
  "./bridge/react/useIpc.tsx": "./src/bridge/react/useIpc.tsx",
211
223
  "./bridge/react/useIpc": "./src/bridge/react/useIpc.tsx",
212
224
  "./bridge/react/useIpc.js": "./src/bridge/react/useIpc.tsx",
@@ -225,6 +237,9 @@
225
237
  "./bridge/react/usePlatformAppManifest.tsx": "./src/bridge/react/usePlatformAppManifest.tsx",
226
238
  "./bridge/react/usePlatformAppManifest": "./src/bridge/react/usePlatformAppManifest.tsx",
227
239
  "./bridge/react/usePlatformAppManifest.js": "./src/bridge/react/usePlatformAppManifest.tsx",
240
+ "./bridge/react/usePlatformAppSettings.tsx": "./src/bridge/react/usePlatformAppSettings.tsx",
241
+ "./bridge/react/usePlatformAppSettings": "./src/bridge/react/usePlatformAppSettings.tsx",
242
+ "./bridge/react/usePlatformAppSettings.js": "./src/bridge/react/usePlatformAppSettings.tsx",
228
243
  "./bridge/react/usePlatformBridge.tsx": "./src/bridge/react/usePlatformBridge.tsx",
229
244
  "./bridge/react/usePlatformBridge": "./src/bridge/react/usePlatformBridge.tsx",
230
245
  "./bridge/react/usePlatformBridge.js": "./src/bridge/react/usePlatformBridge.tsx",
@@ -237,6 +252,9 @@
237
252
  "./bridge/react/usePlatformFilePreview.tsx": "./src/bridge/react/usePlatformFilePreview.tsx",
238
253
  "./bridge/react/usePlatformFilePreview": "./src/bridge/react/usePlatformFilePreview.tsx",
239
254
  "./bridge/react/usePlatformFilePreview.js": "./src/bridge/react/usePlatformFilePreview.tsx",
255
+ "./bridge/react/usePlatformJsonStore.tsx": "./src/bridge/react/usePlatformJsonStore.tsx",
256
+ "./bridge/react/usePlatformJsonStore": "./src/bridge/react/usePlatformJsonStore.tsx",
257
+ "./bridge/react/usePlatformJsonStore.js": "./src/bridge/react/usePlatformJsonStore.tsx",
240
258
  "./bridge/react/usePlatformPreferences.tsx": "./src/bridge/react/usePlatformPreferences.tsx",
241
259
  "./bridge/react/usePlatformPreferences": "./src/bridge/react/usePlatformPreferences.tsx",
242
260
  "./bridge/react/usePlatformPreferences.js": "./src/bridge/react/usePlatformPreferences.tsx",
@@ -360,6 +378,9 @@
360
378
  "./components/agents/agentTypes.ts": "./src/components/agents/agentTypes.ts",
361
379
  "./components/agents/agentTypes": "./src/components/agents/agentTypes.ts",
362
380
  "./components/agents/agentTypes.js": "./src/components/agents/agentTypes.ts",
381
+ "./components/agents/ContextPicker.tsx": "./src/components/agents/ContextPicker.tsx",
382
+ "./components/agents/ContextPicker": "./src/components/agents/ContextPicker.tsx",
383
+ "./components/agents/ContextPicker.js": "./src/components/agents/ContextPicker.tsx",
363
384
  "./components/agents/formatToolCallArguments.ts": "./src/components/agents/formatToolCallArguments.ts",
364
385
  "./components/agents/formatToolCallArguments": "./src/components/agents/formatToolCallArguments.ts",
365
386
  "./components/agents/formatToolCallArguments.js": "./src/components/agents/formatToolCallArguments.ts",
@@ -681,6 +702,17 @@
681
702
  "./components/common/desk/index.js": "./src/components/common/desk/index.ts",
682
703
  "./components/common/desk": "./src/components/common/desk/index.ts",
683
704
  "./components/common/desk.js": "./src/components/common/desk/index.ts",
705
+ "./components/common/documents/DocumentHeaderActions.tsx": "./src/components/common/documents/DocumentHeaderActions.tsx",
706
+ "./components/common/documents/DocumentHeaderActions": "./src/components/common/documents/DocumentHeaderActions.tsx",
707
+ "./components/common/documents/DocumentHeaderActions.js": "./src/components/common/documents/DocumentHeaderActions.tsx",
708
+ "./components/common/documents/DocumentSwitcher.tsx": "./src/components/common/documents/DocumentSwitcher.tsx",
709
+ "./components/common/documents/DocumentSwitcher": "./src/components/common/documents/DocumentSwitcher.tsx",
710
+ "./components/common/documents/DocumentSwitcher.js": "./src/components/common/documents/DocumentSwitcher.tsx",
711
+ "./components/common/documents/index.ts": "./src/components/common/documents/index.ts",
712
+ "./components/common/documents/index": "./src/components/common/documents/index.ts",
713
+ "./components/common/documents/index.js": "./src/components/common/documents/index.ts",
714
+ "./components/common/documents": "./src/components/common/documents/index.ts",
715
+ "./components/common/documents.js": "./src/components/common/documents/index.ts",
684
716
  "./components/common/dropdown/ContextMenu.tsx": "./src/components/common/dropdown/ContextMenu.tsx",
685
717
  "./components/common/dropdown/ContextMenu": "./src/components/common/dropdown/ContextMenu.tsx",
686
718
  "./components/common/dropdown/ContextMenu.js": "./src/components/common/dropdown/ContextMenu.tsx",
@@ -1044,6 +1076,9 @@
1044
1076
  "./components/print-design/index.js": "./src/components/print-design/index.ts",
1045
1077
  "./components/print-design": "./src/components/print-design/index.ts",
1046
1078
  "./components/print-design.js": "./src/components/print-design/index.ts",
1079
+ "./components/print-design/previewContent.ts": "./src/components/print-design/previewContent.ts",
1080
+ "./components/print-design/previewContent": "./src/components/print-design/previewContent.ts",
1081
+ "./components/print-design/previewContent.js": "./src/components/print-design/previewContent.ts",
1047
1082
  "./components/print-design/PrintDesignPanel.tsx": "./src/components/print-design/PrintDesignPanel.tsx",
1048
1083
  "./components/print-design/PrintDesignPanel": "./src/components/print-design/PrintDesignPanel.tsx",
1049
1084
  "./components/print-design/PrintDesignPanel.js": "./src/components/print-design/PrintDesignPanel.tsx",
@@ -1055,6 +1090,24 @@
1055
1090
  "./components/proofing/PagedProofDialog.tsx": "./src/components/proofing/PagedProofDialog.tsx",
1056
1091
  "./components/proofing/PagedProofDialog": "./src/components/proofing/PagedProofDialog.tsx",
1057
1092
  "./components/proofing/PagedProofDialog.js": "./src/components/proofing/PagedProofDialog.tsx",
1093
+ "./context/buildContextDocument.ts": "./src/context/buildContextDocument.ts",
1094
+ "./context/buildContextDocument": "./src/context/buildContextDocument.ts",
1095
+ "./context/buildContextDocument.js": "./src/context/buildContextDocument.ts",
1096
+ "./context/contextAccess.ts": "./src/context/contextAccess.ts",
1097
+ "./context/contextAccess": "./src/context/contextAccess.ts",
1098
+ "./context/contextAccess.js": "./src/context/contextAccess.ts",
1099
+ "./context/contextConfig.ts": "./src/context/contextConfig.ts",
1100
+ "./context/contextConfig": "./src/context/contextConfig.ts",
1101
+ "./context/contextConfig.js": "./src/context/contextConfig.ts",
1102
+ "./context/contextDocument.ts": "./src/context/contextDocument.ts",
1103
+ "./context/contextDocument": "./src/context/contextDocument.ts",
1104
+ "./context/contextDocument.js": "./src/context/contextDocument.ts",
1105
+ "./context/contextSections.ts": "./src/context/contextSections.ts",
1106
+ "./context/contextSections": "./src/context/contextSections.ts",
1107
+ "./context/contextSections.js": "./src/context/contextSections.ts",
1108
+ "./context/htmlToContextMarkdown.ts": "./src/context/htmlToContextMarkdown.ts",
1109
+ "./context/htmlToContextMarkdown": "./src/context/htmlToContextMarkdown.ts",
1110
+ "./context/htmlToContextMarkdown.js": "./src/context/htmlToContextMarkdown.ts",
1058
1111
  "./editor/DocumentEditor.tsx": "./src/editor/DocumentEditor.tsx",
1059
1112
  "./editor/DocumentEditor": "./src/editor/DocumentEditor.tsx",
1060
1113
  "./editor/DocumentEditor.js": "./src/editor/DocumentEditor.tsx",
@@ -1181,6 +1234,7 @@
1181
1234
  "lucide-react": "^0.511.0",
1182
1235
  "mermaid": "^11.15.0",
1183
1236
  "styled-components": "^6.1.18",
1237
+ "yaml": "^2.9.0",
1184
1238
  "@puredesktop/platform-editor": "2.1.0"
1185
1239
  },
1186
1240
  "peerDependencies": {
@@ -24,7 +24,27 @@ export interface PlatformAgentImageAttachment {
24
24
  name?: string
25
25
  }
26
26
 
27
- export type PlatformAgentMessageAttachment = PlatformAgentImageAttachment
27
+ /**
28
+ * An object's markdown context document attached to a user message —
29
+ * output of the context picker (`context.read`). Mirrors the shell's
30
+ * `AgentContextAttachment`.
31
+ */
32
+ export interface PlatformAgentContextAttachment {
33
+ type: 'context'
34
+ /** Object kind, e.g. 'manuscript' | 'book'. */
35
+ kind: string
36
+ appSlug: string
37
+ objectId: string
38
+ title: string
39
+ /** Full or section markdown from the object's context document. */
40
+ markdown: string
41
+ /** Durable section id when a segmented read was attached. */
42
+ section?: string
43
+ }
44
+
45
+ export type PlatformAgentMessageAttachment =
46
+ | PlatformAgentImageAttachment
47
+ | PlatformAgentContextAttachment
28
48
 
29
49
  export interface PlatformAgentUiToolCall {
30
50
  id: string
@@ -25,12 +25,29 @@ export interface CollectionImagePastePayload {
25
25
  mimeType: string
26
26
  }
27
27
 
28
+ export interface CollectionImageInsertPayload {
29
+ relativePath: string
30
+ alt: string
31
+ bytes: Uint8Array
32
+ mimeType: string
33
+ }
34
+
28
35
  export interface CollectionImagePasteHandlerOptions {
29
36
  collectionPath?: string
30
37
  subdir?: string
31
38
  onError?: (message: string) => void
32
39
  getEditor: () => Editor | null | undefined
33
40
  writeBinary: (absolutePath: string, bytes: Uint8Array) => Promise<void>
41
+ /**
42
+ * Override how the persisted image is placed into the document. Defaults to a
43
+ * bare image node; callers (e.g. the manuscript editor) can supply a handler
44
+ * that wraps it in a captioned `<figure>` so it is numbered and
45
+ * cross-referenceable. Returns `false` if the editor cannot accept the node.
46
+ */
47
+ insertImage?: (
48
+ editor: Editor | null | undefined,
49
+ image: CollectionImageInsertPayload,
50
+ ) => boolean
34
51
  }
35
52
 
36
53
  export function normalizeCollectionImageMimeType(
@@ -93,6 +110,7 @@ export function createCollectionImagePasteHandler(
93
110
  onError,
94
111
  getEditor,
95
112
  writeBinary,
113
+ insertImage = insertCollectionImage,
96
114
  } = options
97
115
 
98
116
  return async ({ name, bytes, mimeType }) => {
@@ -117,7 +135,7 @@ export function createCollectionImagePasteHandler(
117
135
  const stem = stemFromImageFileName(name)
118
136
  const editor = getEditor()
119
137
  if (
120
- !insertCollectionImage(editor, {
138
+ !insertImage(editor, {
121
139
  relativePath,
122
140
  alt: stem,
123
141
  bytes,
@@ -10,3 +10,35 @@ import { PLATFORM_BRIDGE_METHODS } from './methods.mjs'
10
10
  export async function publishContext(request) {
11
11
  return bridge.call(PLATFORM_BRIDGE_METHODS.CONTEXT_PUBLISH, [request])
12
12
  }
13
+
14
+ /**
15
+ * Resolve one object's context document — generates or refreshes the
16
+ * `<name>.<kind>.md` file when missing or stale. Requires `filesystem`.
17
+ *
18
+ * @param {{ path?: string, appSlug?: string, objectId?: string }} ref
19
+ * @returns {Promise<import('../context/contextAccess.js').PlatformContextResolveResult>}
20
+ */
21
+ export async function resolveContextDocument(ref) {
22
+ return bridge.call(PLATFORM_BRIDGE_METHODS.CONTEXT_RESOLVE, [ref])
23
+ }
24
+
25
+ /**
26
+ * Read one object's context markdown — the whole document or one section by
27
+ * durable section id. Requires `filesystem`.
28
+ *
29
+ * @param {{ path?: string, appSlug?: string, objectId?: string, section?: string }} request
30
+ * @returns {Promise<import('../context/contextAccess.js').PlatformContextReadResult>}
31
+ */
32
+ export async function readContextDocument(request) {
33
+ return bridge.call(PLATFORM_BRIDGE_METHODS.CONTEXT_READ, [request])
34
+ }
35
+
36
+ /**
37
+ * Search context-enabled objects across apps. Requires `filesystem`.
38
+ *
39
+ * @param {{ query: string, kinds?: string[], appSlug?: string, limit?: number }} request
40
+ * @returns {Promise<import('../context/contextAccess.js').PlatformContextSearchHit[]>}
41
+ */
42
+ export async function searchContextObjects(request) {
43
+ return bridge.call(PLATFORM_BRIDGE_METHODS.CONTEXT_SEARCH, [request])
44
+ }
@@ -0,0 +1,76 @@
1
+ /** One file inside a document. `name: null` addresses a single-file document
2
+ * itself; a string is a path relative to a package directory. */
3
+ export interface PlatformDocumentFilePayload {
4
+ name: string | null
5
+ content: string
6
+ }
7
+
8
+ export interface PlatformDocumentCreateDraftRequest {
9
+ appSlug: string
10
+ suffix: string
11
+ kind: 'package' | 'file'
12
+ title?: string
13
+ files: PlatformDocumentFilePayload[]
14
+ }
15
+
16
+ export interface PlatformDocumentListEntry {
17
+ path: string
18
+ name: string
19
+ mtimeMs: number
20
+ isDraft: boolean
21
+ kind: 'package' | 'file'
22
+ }
23
+
24
+ export interface PlatformRecentDocumentEntry {
25
+ path: string
26
+ title: string
27
+ touchedAt: string
28
+ }
29
+
30
+ export function createPlatformDraft(
31
+ request: PlatformDocumentCreateDraftRequest,
32
+ ): Promise<{ path: string }>
33
+
34
+ export function autosavePlatformDocument(request: {
35
+ path: string
36
+ files: PlatformDocumentFilePayload[]
37
+ }): Promise<{ savedAt: string }>
38
+
39
+ export function promotePlatformDocument(request: {
40
+ path: string
41
+ title: string
42
+ targetDir?: string
43
+ /** The document type's real suffix (e.g. `.chart.json`) — required for
44
+ * compound suffixes, which cannot be recovered from the path. */
45
+ suffix?: string
46
+ appSlug?: string
47
+ }): Promise<{ path: string }>
48
+
49
+ export function renamePlatformDocument(request: {
50
+ path: string
51
+ title: string
52
+ suffix?: string
53
+ appSlug?: string
54
+ }): Promise<{ path: string }>
55
+
56
+ export function duplicatePlatformDocument(request: {
57
+ path: string
58
+ suffix?: string
59
+ }): Promise<{ path: string }>
60
+
61
+ export function listPlatformDocumentsByType(request: {
62
+ suffixes: string[]
63
+ }): Promise<PlatformDocumentListEntry[]>
64
+
65
+ export function listPlatformRecentDocuments(request: {
66
+ appSlug: string
67
+ limit?: number
68
+ }): Promise<PlatformRecentDocumentEntry[]>
69
+
70
+ export function touchPlatformRecentDocument(request: {
71
+ appSlug: string
72
+ path: string
73
+ title: string
74
+ }): Promise<void>
75
+
76
+ export function suggestPlatformDocumentLocation(): Promise<{ dir: string }>
@@ -0,0 +1,40 @@
1
+ import { bridge } from './client.mjs'
2
+ import { PLATFORM_BRIDGE_METHODS } from './methods.mjs'
3
+
4
+ /** Unified document lifecycle bridge: drafts, autosave, filing, recents. */
5
+
6
+ export async function createPlatformDraft(request) {
7
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_CREATE_DRAFT, [request])
8
+ }
9
+
10
+ export async function autosavePlatformDocument(request) {
11
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_AUTOSAVE, [request])
12
+ }
13
+
14
+ export async function promotePlatformDocument(request) {
15
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_PROMOTE, [request])
16
+ }
17
+
18
+ export async function renamePlatformDocument(request) {
19
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_RENAME, [request])
20
+ }
21
+
22
+ export async function duplicatePlatformDocument(request) {
23
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_DUPLICATE, [request])
24
+ }
25
+
26
+ export async function listPlatformDocumentsByType(request) {
27
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_LIST_BY_TYPE, [request])
28
+ }
29
+
30
+ export async function listPlatformRecentDocuments(request) {
31
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_RECENTS_LIST, [request])
32
+ }
33
+
34
+ export async function touchPlatformRecentDocument(request) {
35
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_RECENTS_TOUCH, [request])
36
+ }
37
+
38
+ export async function suggestPlatformDocumentLocation() {
39
+ return bridge.call(PLATFORM_BRIDGE_METHODS.DOCUMENTS_SUGGEST_LOCATION, [])
40
+ }
@@ -8,6 +8,7 @@ export declare const PLATFORM_BRIDGE_METHODS: {
8
8
  readonly WORKSPACE_OPEN_APP: 'workspace.openApp'
9
9
  readonly WORKSPACE_OPEN_PALETTE: 'workspace.openPalette'
10
10
  readonly WORKSPACE_UPDATE_CURRENT_TAB: 'workspace.updateCurrentTab'
11
+ readonly WORKSPACE_SET_OVERLAY_OPEN: 'workspace.setOverlayOpen'
11
12
  readonly SCHEDULER_REGISTER: 'scheduler.register'
12
13
  readonly SCHEDULER_UNREGISTER: 'scheduler.unregister'
13
14
  readonly CATALOG_CONSUME_PENDING_OPEN: 'catalog.consumePendingOpen'
@@ -60,17 +61,27 @@ export declare const PLATFORM_BRIDGE_METHODS: {
60
61
  readonly ASSETS_TRANSFORM: 'assets.transform'
61
62
  readonly ASSETS_GET_CONTEXT: 'assets.getContext'
62
63
  readonly NETWORK_FETCH: 'network.fetch'
64
+ readonly RESEARCH_QUERY: 'research.query'
63
65
  readonly VISION_GENERATE_IMAGE: 'vision.generateImage'
64
66
  readonly OAUTH_LOOPBACK_AUTHORIZE: 'oauth.loopbackAuthorize'
65
67
  readonly SECRETS_GET: 'secrets.get'
66
68
  readonly SECRETS_SET: 'secrets.set'
67
69
  readonly SECRETS_DELETE: 'secrets.delete'
68
70
  readonly SECRETS_STATUS: 'secrets.status'
71
+ readonly MYTOOLS_LIST: 'mytools.list'
72
+ readonly MYTOOLS_SAVE: 'mytools.save'
73
+ readonly MYTOOLS_UPDATE: 'mytools.update'
74
+ readonly MYTOOLS_DELETE: 'mytools.delete'
75
+ readonly MYTOOLS_TEST: 'mytools.test'
76
+ readonly MYTOOLS_RESEARCH: 'mytools.research'
69
77
  readonly DEBUG_EMIT_EVENT: 'debug.emitEvent'
70
78
  readonly PLUGINS_INSTALL: 'plugins.install'
71
79
  readonly PLUGINS_EVALUATE_BUILD: 'plugins.evaluateBuild'
72
80
  readonly PLUGINS_PREPARE_REGISTRATION: 'plugins.prepareRegistration'
73
81
  readonly CONTEXT_PUBLISH: 'context.publish'
82
+ readonly CONTEXT_RESOLVE: 'context.resolve'
83
+ readonly CONTEXT_READ: 'context.read'
84
+ readonly CONTEXT_SEARCH: 'context.search'
74
85
  readonly PEOPLE_SUGGEST: 'people.suggest'
75
86
  readonly PEOPLE_RESEARCH: 'people.research'
76
87
  readonly CREDENTIALS_STORAGE_STATUS: 'credentials.storageStatus'
@@ -102,6 +113,15 @@ export declare const PLATFORM_BRIDGE_METHODS: {
102
113
  readonly AGENTS_LOCAL_MODELS_STATUS: 'agents.localModels.status'
103
114
  readonly AGENTS_TOOLS_REGISTER: 'agents.tools.register'
104
115
  readonly AGENTS_TOOLS_COMPLETE: 'agents.tools.complete'
116
+ readonly DOCUMENTS_CREATE_DRAFT: 'documents.createDraft'
117
+ readonly DOCUMENTS_AUTOSAVE: 'documents.autosave'
118
+ readonly DOCUMENTS_PROMOTE: 'documents.promote'
119
+ readonly DOCUMENTS_RENAME: 'documents.rename'
120
+ readonly DOCUMENTS_DUPLICATE: 'documents.duplicate'
121
+ readonly DOCUMENTS_LIST_BY_TYPE: 'documents.listByType'
122
+ readonly DOCUMENTS_RECENTS_LIST: 'documents.recents.list'
123
+ readonly DOCUMENTS_RECENTS_TOUCH: 'documents.recents.touch'
124
+ readonly DOCUMENTS_SUGGEST_LOCATION: 'documents.suggestLocation'
105
125
  }
106
126
 
107
127
  export declare const PLATFORM_BRIDGE_METHOD_PREFIXES: {
@@ -119,12 +139,15 @@ export declare const PLATFORM_BRIDGE_METHOD_PREFIXES: {
119
139
  readonly WATCH: 'watch.'
120
140
  readonly ASSETS: 'assets.'
121
141
  readonly NETWORK: 'network.'
142
+ readonly RESEARCH: 'research.'
122
143
  readonly VISION: 'vision.'
123
144
  readonly OAUTH: 'oauth.'
124
145
  readonly SECRETS: 'secrets.'
146
+ readonly MYTOOLS: 'mytools.'
125
147
  readonly AGENTS: 'agents.'
126
148
  readonly PEOPLE: 'people.'
127
149
  readonly DEBUG: 'debug.'
150
+ readonly DOCUMENTS: 'documents.'
128
151
  }
129
152
 
130
153
  export type PlatformBridgeMethodName =
@@ -11,6 +11,7 @@ export const PLATFORM_BRIDGE_METHODS = {
11
11
  WORKSPACE_OPEN_APP: 'workspace.openApp',
12
12
  WORKSPACE_OPEN_PALETTE: 'workspace.openPalette',
13
13
  WORKSPACE_UPDATE_CURRENT_TAB: 'workspace.updateCurrentTab',
14
+ WORKSPACE_SET_OVERLAY_OPEN: 'workspace.setOverlayOpen',
14
15
  SCHEDULER_REGISTER: 'scheduler.register',
15
16
  SCHEDULER_UNREGISTER: 'scheduler.unregister',
16
17
  CATALOG_CONSUME_PENDING_OPEN: 'catalog.consumePendingOpen',
@@ -75,12 +76,19 @@ export const PLATFORM_BRIDGE_METHODS = {
75
76
  ASSETS_GET_CONTEXT: 'assets.getContext',
76
77
 
77
78
  NETWORK_FETCH: 'network.fetch',
79
+ RESEARCH_QUERY: 'research.query',
78
80
  VISION_GENERATE_IMAGE: 'vision.generateImage',
79
81
  OAUTH_LOOPBACK_AUTHORIZE: 'oauth.loopbackAuthorize',
80
82
  SECRETS_GET: 'secrets.get',
81
83
  SECRETS_SET: 'secrets.set',
82
84
  SECRETS_DELETE: 'secrets.delete',
83
85
  SECRETS_STATUS: 'secrets.status',
86
+ MYTOOLS_LIST: 'mytools.list',
87
+ MYTOOLS_SAVE: 'mytools.save',
88
+ MYTOOLS_UPDATE: 'mytools.update',
89
+ MYTOOLS_DELETE: 'mytools.delete',
90
+ MYTOOLS_TEST: 'mytools.test',
91
+ MYTOOLS_RESEARCH: 'mytools.research',
84
92
 
85
93
  DEBUG_EMIT_EVENT: 'debug.emitEvent',
86
94
 
@@ -88,6 +96,9 @@ export const PLATFORM_BRIDGE_METHODS = {
88
96
  PLUGINS_EVALUATE_BUILD: 'plugins.evaluateBuild',
89
97
  PLUGINS_PREPARE_REGISTRATION: 'plugins.prepareRegistration',
90
98
  CONTEXT_PUBLISH: 'context.publish',
99
+ CONTEXT_RESOLVE: 'context.resolve',
100
+ CONTEXT_READ: 'context.read',
101
+ CONTEXT_SEARCH: 'context.search',
91
102
  PEOPLE_SUGGEST: 'people.suggest',
92
103
  PEOPLE_RESEARCH: 'people.research',
93
104
 
@@ -124,6 +135,15 @@ export const PLATFORM_BRIDGE_METHODS = {
124
135
  AGENTS_LOCAL_MODELS_STATUS: 'agents.localModels.status',
125
136
  AGENTS_TOOLS_REGISTER: 'agents.tools.register',
126
137
  AGENTS_TOOLS_COMPLETE: 'agents.tools.complete',
138
+ DOCUMENTS_CREATE_DRAFT: 'documents.createDraft',
139
+ DOCUMENTS_AUTOSAVE: 'documents.autosave',
140
+ DOCUMENTS_PROMOTE: 'documents.promote',
141
+ DOCUMENTS_RENAME: 'documents.rename',
142
+ DOCUMENTS_DUPLICATE: 'documents.duplicate',
143
+ DOCUMENTS_LIST_BY_TYPE: 'documents.listByType',
144
+ DOCUMENTS_RECENTS_LIST: 'documents.recents.list',
145
+ DOCUMENTS_RECENTS_TOUCH: 'documents.recents.touch',
146
+ DOCUMENTS_SUGGEST_LOCATION: 'documents.suggestLocation',
127
147
  }
128
148
 
129
149
  export const PLATFORM_BRIDGE_METHOD_PREFIXES = {
@@ -141,10 +161,13 @@ export const PLATFORM_BRIDGE_METHOD_PREFIXES = {
141
161
  WATCH: 'watch.',
142
162
  ASSETS: 'assets.',
143
163
  NETWORK: 'network.',
164
+ RESEARCH: 'research.',
144
165
  VISION: 'vision.',
145
166
  OAUTH: 'oauth.',
146
167
  SECRETS: 'secrets.',
168
+ MYTOOLS: 'mytools.',
147
169
  AGENTS: 'agents.',
148
170
  PEOPLE: 'people.',
149
171
  DEBUG: 'debug.',
172
+ DOCUMENTS: 'documents.',
150
173
  }
@@ -16,6 +16,46 @@ body {
16
16
  max-width: 30rem;
17
17
  string-set: doctitle content(text);
18
18
  }
19
+ /* Metadata eyebrow above the title — driven purely by theme tokens. */
20
+ .doc-title::before {
21
+ content: var(--eyebrow-text, '');
22
+ display: var(--eyebrow-display, none);
23
+ font: 600 8pt / 1.3 var(--sans);
24
+ letter-spacing: 0.14em;
25
+ text-transform: uppercase;
26
+ color: var(--accent);
27
+ margin: 0 0 calc(var(--rhythm) * 0.6);
28
+ }
29
+ /* Drop cap on the opening paragraph — inert unless the theme enables it.
30
+ THREE separate rules on purpose: Paged.js crashes on comma-lists of
31
+ ::first-letter selectors ("item doesn't belong to list"). */
32
+ .doc-title + p::first-letter {
33
+ float: var(--drop-cap-float, none);
34
+ font-family: var(--drop-cap-font, inherit);
35
+ font-size: var(--drop-cap-size, 1em);
36
+ line-height: var(--drop-cap-lh, inherit);
37
+ font-weight: var(--drop-cap-weight, inherit);
38
+ padding: var(--drop-cap-pad, 0);
39
+ color: var(--drop-cap-ink, inherit);
40
+ }
41
+ .doc-title + section > p:first-child::first-letter {
42
+ float: var(--drop-cap-float, none);
43
+ font-family: var(--drop-cap-font, inherit);
44
+ font-size: var(--drop-cap-size, 1em);
45
+ line-height: var(--drop-cap-lh, inherit);
46
+ font-weight: var(--drop-cap-weight, inherit);
47
+ padding: var(--drop-cap-pad, 0);
48
+ color: var(--drop-cap-ink, inherit);
49
+ }
50
+ section:first-of-type > p:first-child::first-letter {
51
+ float: var(--drop-cap-float, none);
52
+ font-family: var(--drop-cap-font, inherit);
53
+ font-size: var(--drop-cap-size, 1em);
54
+ line-height: var(--drop-cap-lh, inherit);
55
+ font-weight: var(--drop-cap-weight, inherit);
56
+ padding: var(--drop-cap-pad, 0);
57
+ color: var(--drop-cap-ink, inherit);
58
+ }
19
59
  .authors {
20
60
  font: 500 11.5pt/1.4 var(--sans);
21
61
  margin: 0 0 0.4rem;
@@ -83,6 +123,10 @@ h2 {
83
123
  line-height: 1.15;
84
124
  margin: calc(var(--rhythm) * 1.5) 0 calc(var(--rhythm) * 0.4);
85
125
  string-set: sectitle content(text);
126
+ /* Optional accent rule beneath section headings (theme token). */
127
+ border-bottom: var(--heading-rule-width, 0) solid var(--accent);
128
+ padding-bottom: var(--heading-rule-pad, 0);
129
+ max-width: var(--measure);
86
130
  }
87
131
  section:not([data-type='abstract']):not([data-type='frontmatter']):not(
88
132
  [data-type='backmatter']
@@ -1,5 +1,10 @@
1
1
  import { buildPrintHtmlDocument } from '../printDocument.js'
2
- import { normalizePureRenderHtml } from './normalize.js'
2
+ import {
3
+ injectCoverSection,
4
+ injectGeneratedToc,
5
+ normalizePureRenderHtml,
6
+ wrapLooseBodyRun,
7
+ } from './normalize.js'
3
8
  import { buildPureRenderStylesheet } from './styles.js'
4
9
  import type { PureRenderRequest } from './types.js'
5
10
 
@@ -22,6 +27,28 @@ export function buildPureRenderHtmlDocument(options: {
22
27
  )
23
28
  }
24
29
 
30
+ // Theme-driven structure: cover first (title block onto its own named
31
+ // page), then a generated table of contents from the normalized
32
+ // article's sections (ids are assigned during normalization).
33
+ const setting = options.request.theme?.setting
34
+ let bodyHtml = normalized.html
35
+ if (setting?.coverPage) {
36
+ bodyHtml = injectCoverSection(bodyHtml, {
37
+ author: setting.coverAuthor,
38
+ date: setting.coverDate,
39
+ })
40
+ }
41
+ // Contents implies a cover: without one, a toc page before the title
42
+ // reads as clutter rather than structure.
43
+ if (setting?.coverPage && setting?.toc) {
44
+ bodyHtml = injectGeneratedToc(bodyHtml)
45
+ }
46
+ if (options.request.theme?.page?.columns === 2) {
47
+ // Columns attach to body sections; unsectioned (writer) articles need
48
+ // their loose body run wrapped so there is a section to columnize.
49
+ bodyHtml = wrapLooseBodyRun(bodyHtml)
50
+ }
51
+
25
52
  return buildPrintHtmlDocument({
26
53
  rootPath: options.rootPath,
27
54
  title: options.title ?? normalized.title,
@@ -30,6 +57,6 @@ export function buildPureRenderHtmlDocument(options: {
30
57
  theme: options.request.theme,
31
58
  }),
32
59
  bodyClass: `pure-render pure-render-${options.request.profile}`,
33
- bodyHtml: normalized.html,
60
+ bodyHtml,
34
61
  })
35
62
  }
@@ -1,4 +1,5 @@
1
1
  export { compilePrintTheme } from './compiler.js'
2
+ export { sanitizeBodyForPureRenderExport } from './sanitizeExportBody.js'
2
3
  export {
3
4
  buildBookPureRenderRequest,
4
5
  buildWriterPureRenderRequest,
@@ -46,7 +47,9 @@ export {
46
47
  } from './samples.js'
47
48
  export {
48
49
  inspectPureRenderVisualLayout,
50
+ relevantPagedSnapshotPages,
49
51
  visualIssuesForMetrics,
52
+ type PureRenderSnapshotRole,
50
53
  type PureRenderVisualCandidate,
51
54
  type PureRenderVisualDecision,
52
55
  type PureRenderVisualInspection,