@dxos/plugin-markdown 0.9.1-main.c7dcc2e112 → 0.9.1-staging.ee54ba693a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/neutral/{MarkdownArticle-I4UMD7AA.mjs → MarkdownArticle-ZHBXH7YF.mjs} +3 -5
- package/dist/lib/neutral/{MarkdownArticle-I4UMD7AA.mjs.map → MarkdownArticle-ZHBXH7YF.mjs.map} +2 -2
- package/dist/lib/neutral/{MarkdownCard-OYO2HYZF.mjs → MarkdownCard-2HUXCGZP.mjs} +2 -2
- package/dist/lib/neutral/{MarkdownCard-OYO2HYZF.mjs.map → MarkdownCard-2HUXCGZP.mjs.map} +1 -1
- package/dist/lib/neutral/MarkdownPlugin.mjs +3 -7
- package/dist/lib/neutral/MarkdownPlugin.mjs.map +3 -3
- package/dist/lib/neutral/MarkdownPlugin.node.mjs +4 -2
- package/dist/lib/neutral/MarkdownPlugin.node.mjs.map +3 -3
- package/dist/lib/neutral/MarkdownPlugin.workerd.mjs +6 -17
- package/dist/lib/neutral/MarkdownPlugin.workerd.mjs.map +4 -4
- package/dist/lib/neutral/MarkdownSettings-5VMOYMND.mjs +43 -0
- package/dist/lib/neutral/MarkdownSettings-5VMOYMND.mjs.map +7 -0
- package/dist/lib/neutral/{anchor-sort-UXN4RHFX.mjs → anchor-sort-QF7UDG2A.mjs} +4 -3
- package/dist/lib/neutral/anchor-sort-QF7UDG2A.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +9 -13
- package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
- package/dist/lib/neutral/capabilities/node.mjs +5 -3
- package/dist/lib/neutral/capabilities/node.mjs.map +3 -3
- package/dist/lib/neutral/chunk-2V6A5NDQ.mjs +8 -0
- package/dist/lib/neutral/{operation-handler-2ARMPBGZ.mjs → chunk-ANHHOTCD.mjs} +3 -4
- package/dist/lib/neutral/{operation-handler-2ARMPBGZ.mjs.map → chunk-ANHHOTCD.mjs.map} +1 -1
- package/dist/lib/neutral/chunk-CNYFGIDS.mjs +32 -0
- package/dist/lib/neutral/chunk-CNYFGIDS.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-LXNSKCPD.mjs → chunk-EV4ZOL4P.mjs} +12 -11
- package/dist/lib/neutral/chunk-EV4ZOL4P.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-GUXWFDD4.mjs → chunk-OC3JD73N.mjs} +2 -2
- package/dist/lib/neutral/{chunk-GUXWFDD4.mjs.map → chunk-OC3JD73N.mjs.map} +1 -1
- package/dist/lib/neutral/chunk-YJF6XOXX.mjs +175 -0
- package/dist/lib/neutral/chunk-YJF6XOXX.mjs.map +7 -0
- package/dist/lib/neutral/chunk-YMBC62S7.mjs +14 -0
- package/dist/lib/neutral/chunk-YMBC62S7.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-CRKAIDRD.mjs → chunk-ZJ3GWRUJ.mjs} +15 -14
- package/dist/lib/neutral/chunk-ZJ3GWRUJ.mjs.map +7 -0
- package/dist/lib/neutral/{comment-config-EGY7RPPW.mjs → comment-config-M5OGFULS.mjs} +6 -4
- package/dist/lib/neutral/comment-config-M5OGFULS.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +13 -52
- package/dist/lib/neutral/components/index.mjs.map +4 -4
- package/dist/lib/neutral/containers/index.mjs +5 -3
- package/dist/lib/neutral/containers/index.mjs.map +3 -3
- package/dist/lib/neutral/{create-XW2FQNLK.mjs → create-OQUMKL5I.mjs} +2 -2
- package/dist/lib/neutral/{create-markdown-KLSVQCT7.mjs → create-markdown-4O5FDA77.mjs} +2 -2
- package/dist/lib/neutral/{create-object-3WMEQJ2C.mjs → create-object-RSEWTCMM.mjs} +2 -6
- package/dist/lib/neutral/create-object-RSEWTCMM.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +41 -15
- package/dist/lib/neutral/hooks/index.mjs.map +3 -3
- package/dist/lib/neutral/index.mjs +10 -16
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/meta.mjs +1 -1
- package/dist/lib/neutral/{open-F7KLNKVN.mjs → open-BAZIRXII.mjs} +2 -2
- package/dist/lib/neutral/operation-handler-SDCXGMGK.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs +1 -1
- package/dist/lib/neutral/plugin.mjs +2 -2
- package/dist/lib/neutral/plugin.workerd.mjs +12 -0
- package/dist/lib/neutral/plugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/{react-surface-6LX4ZQ2H.mjs → react-surface-37GL3UVG.mjs} +4 -4
- package/dist/lib/neutral/react-surface-37GL3UVG.mjs.map +7 -0
- package/dist/lib/neutral/{scroll-to-anchor-ACND3WJU.mjs → scroll-to-anchor-I6HFE5AH.mjs} +2 -2
- package/dist/lib/neutral/{set-view-mode-WDC7CAEC.mjs → set-view-mode-NY5OYYIM.mjs} +2 -2
- package/dist/lib/neutral/skill-definition-ET7BYY47.mjs +8 -0
- package/dist/lib/neutral/skill-definition-ET7BYY47.mjs.map +7 -0
- package/dist/lib/neutral/skills/index.mjs +8 -0
- package/dist/lib/neutral/skills/index.mjs.map +7 -0
- package/dist/lib/neutral/{state-ZYT3JRWT.mjs → state-3BR7L6CW.mjs} +1 -1
- package/dist/lib/neutral/{state-ZYT3JRWT.mjs.map → state-3BR7L6CW.mjs.map} +2 -2
- package/dist/lib/neutral/types/index.mjs +1 -1
- package/dist/lib/neutral/update-markdown-M4PTA6VS.mjs +24 -0
- package/dist/lib/neutral/update-markdown-M4PTA6VS.mjs.map +7 -0
- package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
- package/dist/types/src/MarkdownPlugin.node.d.ts.map +1 -1
- package/dist/types/src/MarkdownPlugin.workerd.d.ts.map +1 -1
- package/dist/types/src/capabilities/anchor-sort.d.ts +1 -2
- package/dist/types/src/capabilities/anchor-sort.d.ts.map +1 -1
- package/dist/types/src/capabilities/comment-config.d.ts +1 -2
- package/dist/types/src/capabilities/comment-config.d.ts.map +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +1 -7
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -1
- package/dist/types/src/capabilities/editor-view-state.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +1 -3
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/node.d.ts +1 -0
- package/dist/types/src/capabilities/node.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/settings.d.ts +1 -2
- package/dist/types/src/capabilities/settings.d.ts.map +1 -1
- package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
- package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/state.d.ts +1 -2
- package/dist/types/src/capabilities/state.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +3 -4
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts +3 -2
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/PreviewComponent/PreviewComponent.d.ts +17 -0
- package/dist/types/src/components/PreviewComponent/PreviewComponent.d.ts.map +1 -0
- package/dist/types/src/components/PreviewComponent/index.d.ts +2 -0
- package/dist/types/src/components/PreviewComponent/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/MarkdownArticle/MarkdownArticle.d.ts +2 -13
- package/dist/types/src/containers/MarkdownArticle/MarkdownArticle.d.ts.map +1 -1
- package/dist/types/src/{components → containers}/MarkdownSettings/MarkdownSettings.d.ts +1 -1
- package/dist/types/src/{components → containers}/MarkdownSettings/MarkdownSettings.d.ts.map +1 -1
- package/dist/types/src/{components → containers}/MarkdownSettings/MarkdownSettings.stories.d.ts.map +1 -1
- package/dist/types/src/{components → containers}/MarkdownSettings/index.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts +1 -0
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useExtensions.d.ts +3 -3
- package/dist/types/src/hooks/useExtensions.d.ts.map +1 -1
- package/dist/types/src/hooks/useLinkQuery.d.ts +2 -2
- package/dist/types/src/hooks/useLinkQuery.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +4 -0
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/update-markdown.d.ts.map +1 -1
- package/dist/types/src/plugin.workerd.d.ts +2 -0
- package/dist/types/src/plugin.workerd.d.ts.map +1 -0
- package/dist/types/src/skills/index.d.ts +2 -0
- package/dist/types/src/skills/index.d.ts.map +1 -0
- package/dist/types/src/skills/markdown-skill.d.ts +4 -0
- package/dist/types/src/skills/markdown-skill.d.ts.map +1 -0
- package/dist/types/src/types/Markdown.d.ts +12 -20
- package/dist/types/src/types/Markdown.d.ts.map +1 -1
- package/dist/types/src/types/MarkdownOperation.d.ts +5 -28
- package/dist/types/src/types/MarkdownOperation.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +2 -0
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +1 -1
- package/package.json +66 -59
- package/src/MarkdownPlugin.node.ts +2 -1
- package/src/MarkdownPlugin.tsx +2 -6
- package/src/MarkdownPlugin.workerd.ts +5 -2
- package/src/capabilities/anchor-sort.ts +3 -2
- package/src/capabilities/comment-config.ts +6 -9
- package/src/capabilities/create-object.ts +1 -4
- package/src/capabilities/editor-view-state.ts +1 -1
- package/src/capabilities/index.ts +1 -3
- package/src/capabilities/node.ts +1 -0
- package/src/capabilities/react-surface.tsx +9 -3
- package/src/capabilities/skill-definition.ts +14 -0
- package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +72 -30
- package/src/components/MarkdownEditor/MarkdownEditor.tsx +11 -37
- package/src/components/MarkdownEditor/MarkdownEditorContent.tsx +3 -3
- package/src/components/PreviewComponent/PreviewComponent.tsx +195 -0
- package/src/components/PreviewComponent/index.ts +5 -0
- package/src/components/index.ts +1 -4
- package/src/containers/MarkdownArticle/MarkdownArticle.tsx +3 -3
- package/src/containers/MarkdownCard/MarkdownCard.tsx +1 -1
- package/src/{components → containers}/MarkdownSettings/MarkdownSettings.stories.tsx +1 -1
- package/src/containers/MarkdownSettings/MarkdownSettings.tsx +54 -0
- package/src/containers/index.ts +1 -0
- package/src/hooks/useEditorMenuOptions.ts +1 -1
- package/src/hooks/useExtensions.tsx +32 -12
- package/src/hooks/useLinkQuery.ts +5 -3
- package/src/index.ts +1 -2
- package/src/operations/create.conversations.json +1 -1
- package/src/operations/create.test.ts +5 -12
- package/src/operations/update-markdown.ts +7 -27
- package/src/operations/update.conversations.json +1 -1
- package/src/operations/update.test.ts +86 -16
- package/src/plugin.workerd.ts +5 -0
- package/src/skills/index.ts +5 -0
- package/src/{blueprints/markdown-blueprint.ts → skills/markdown-skill.ts} +8 -7
- package/src/types/Markdown.ts +19 -18
- package/src/types/MarkdownOperation.ts +11 -5
- package/src/types/types.ts +2 -7
- package/dist/lib/neutral/MarkdownSettings-F5AWRDT3.mjs +0 -32
- package/dist/lib/neutral/MarkdownSettings-F5AWRDT3.mjs.map +0 -7
- package/dist/lib/neutral/anchor-sort-UXN4RHFX.mjs.map +0 -7
- package/dist/lib/neutral/app-graph-builder-6Y5NHTNR.mjs +0 -66
- package/dist/lib/neutral/app-graph-builder-6Y5NHTNR.mjs.map +0 -7
- package/dist/lib/neutral/blueprint-definition-DSPXK77L.mjs +0 -15
- package/dist/lib/neutral/blueprint-definition-DSPXK77L.mjs.map +0 -7
- package/dist/lib/neutral/blueprints/index.mjs +0 -8
- package/dist/lib/neutral/chunk-4ULSRZRL.mjs +0 -10
- package/dist/lib/neutral/chunk-4ULSRZRL.mjs.map +0 -7
- package/dist/lib/neutral/chunk-BL46CERY.mjs +0 -8
- package/dist/lib/neutral/chunk-CRKAIDRD.mjs.map +0 -7
- package/dist/lib/neutral/chunk-LXNSKCPD.mjs.map +0 -7
- package/dist/lib/neutral/comment-config-EGY7RPPW.mjs.map +0 -7
- package/dist/lib/neutral/create-object-3WMEQJ2C.mjs.map +0 -7
- package/dist/lib/neutral/navigation-resolver-3WEM7SSC.mjs +0 -14
- package/dist/lib/neutral/navigation-resolver-3WEM7SSC.mjs.map +0 -7
- package/dist/lib/neutral/react-surface-6LX4ZQ2H.mjs.map +0 -7
- package/dist/lib/neutral/update-markdown-FGVN3LD4.mjs +0 -44
- package/dist/lib/neutral/update-markdown-FGVN3LD4.mjs.map +0 -7
- package/dist/types/src/blueprints/index.d.ts +0 -2
- package/dist/types/src/blueprints/index.d.ts.map +0 -1
- package/dist/types/src/blueprints/markdown-blueprint.d.ts +0 -4
- package/dist/types/src/blueprints/markdown-blueprint.d.ts.map +0 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +0 -6
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +0 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +0 -6
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +0 -1
- package/dist/types/src/capabilities/navigation-resolver.d.ts +0 -6
- package/dist/types/src/capabilities/navigation-resolver.d.ts.map +0 -1
- package/dist/types/src/paths.d.ts +0 -3
- package/dist/types/src/paths.d.ts.map +0 -1
- package/src/blueprints/index.ts +0 -5
- package/src/capabilities/app-graph-builder.ts +0 -61
- package/src/capabilities/blueprint-definition.ts +0 -19
- package/src/capabilities/navigation-resolver.ts +0 -19
- package/src/components/MarkdownSettings/MarkdownSettings.tsx +0 -35
- package/src/paths.ts +0 -13
- /package/dist/lib/neutral/{chunk-BL46CERY.mjs.map → chunk-2V6A5NDQ.mjs.map} +0 -0
- /package/dist/lib/neutral/{create-XW2FQNLK.mjs.map → create-OQUMKL5I.mjs.map} +0 -0
- /package/dist/lib/neutral/{create-markdown-KLSVQCT7.mjs.map → create-markdown-4O5FDA77.mjs.map} +0 -0
- /package/dist/lib/neutral/{open-F7KLNKVN.mjs.map → open-BAZIRXII.mjs.map} +0 -0
- /package/dist/lib/neutral/{blueprints/index.mjs.map → operation-handler-SDCXGMGK.mjs.map} +0 -0
- /package/dist/lib/neutral/{scroll-to-anchor-ACND3WJU.mjs.map → scroll-to-anchor-I6HFE5AH.mjs.map} +0 -0
- /package/dist/lib/neutral/{set-view-mode-WDC7CAEC.mjs.map → set-view-mode-NY5OYYIM.mjs.map} +0 -0
- /package/dist/types/src/{components → containers}/MarkdownSettings/MarkdownSettings.stories.d.ts +0 -0
- /package/dist/types/src/{components → containers}/MarkdownSettings/index.d.ts +0 -0
- /package/src/{components → containers}/MarkdownSettings/index.ts +0 -0
|
@@ -9,11 +9,6 @@ import { createContext } from '@radix-ui/react-context';
|
|
|
9
9
|
import React, { type ReactNode, useCallback, useMemo, useState } from 'react';
|
|
10
10
|
import { createPortal } from 'react-dom';
|
|
11
11
|
|
|
12
|
-
import { Surface } from '@dxos/app-framework/ui';
|
|
13
|
-
import { AppSurface } from '@dxos/app-toolkit/ui';
|
|
14
|
-
import { Obj } from '@dxos/echo';
|
|
15
|
-
import { URI } from '@dxos/keys';
|
|
16
|
-
import { useClient } from '@dxos/react-client';
|
|
17
12
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
18
13
|
import { composable, composableProps } from '@dxos/react-ui';
|
|
19
14
|
import {
|
|
@@ -22,7 +17,7 @@ import {
|
|
|
22
17
|
createEditorController,
|
|
23
18
|
useEditorContext,
|
|
24
19
|
} from '@dxos/react-ui-editor';
|
|
25
|
-
import { type
|
|
20
|
+
import { type XmlWidgetState } from '@dxos/ui-editor';
|
|
26
21
|
import { isNonNullable } from '@dxos/util';
|
|
27
22
|
|
|
28
23
|
import {
|
|
@@ -49,7 +44,7 @@ import {
|
|
|
49
44
|
type MarkdownEditorContextValue = {
|
|
50
45
|
id: string;
|
|
51
46
|
attendableId?: string;
|
|
52
|
-
|
|
47
|
+
widgets: XmlWidgetState[];
|
|
53
48
|
} & Pick<ExtensionsOptions, 'compact' | 'viewMode'> &
|
|
54
49
|
Pick<NaturalMarkdownToolbarProps, 'onAction' | 'onFileUpload' | 'onViewModeChange'>;
|
|
55
50
|
|
|
@@ -94,20 +89,8 @@ export const MarkdownEditorProvider = ({
|
|
|
94
89
|
onFileUpload,
|
|
95
90
|
onViewModeChange,
|
|
96
91
|
}: MarkdownEditorProviderProps) => {
|
|
97
|
-
//
|
|
98
|
-
const [
|
|
99
|
-
const previewOptions = useMemo<PreviewOptions>(
|
|
100
|
-
() => ({
|
|
101
|
-
db: Obj.isObject(object) ? Obj.getDatabase(object) : undefined,
|
|
102
|
-
addBlockContainer: (block) => {
|
|
103
|
-
setPreviewBlocks((prev) => [...prev, block]);
|
|
104
|
-
},
|
|
105
|
-
removeBlockContainer: ({ link }) => {
|
|
106
|
-
setPreviewBlocks((prev) => prev.filter(({ link: prevLink }) => prevLink.dxn !== link.dxn));
|
|
107
|
-
},
|
|
108
|
-
}),
|
|
109
|
-
[object],
|
|
110
|
-
);
|
|
92
|
+
// Widget portals driven by xmlTags.
|
|
93
|
+
const [widgets, setWidgets] = useState<XmlWidgetState[]>([]);
|
|
111
94
|
|
|
112
95
|
// Context menu options (Editor.Root calls useEditorMenu with these props).
|
|
113
96
|
const menuOptions = useEditorMenuOptions({ slashCommandGroups, onLinkQuery });
|
|
@@ -120,7 +103,7 @@ export const MarkdownEditorProvider = ({
|
|
|
120
103
|
viewMode,
|
|
121
104
|
viewState,
|
|
122
105
|
editorStateStore,
|
|
123
|
-
|
|
106
|
+
setWidgets,
|
|
124
107
|
settings,
|
|
125
108
|
onSelectObject,
|
|
126
109
|
});
|
|
@@ -149,12 +132,12 @@ export const MarkdownEditorProvider = ({
|
|
|
149
132
|
attendableId,
|
|
150
133
|
compact,
|
|
151
134
|
viewMode,
|
|
152
|
-
|
|
135
|
+
widgets,
|
|
153
136
|
onAction,
|
|
154
137
|
onFileUpload,
|
|
155
138
|
onViewModeChange,
|
|
156
139
|
}),
|
|
157
|
-
[id, attendableId, compact, viewMode,
|
|
140
|
+
[id, attendableId, compact, viewMode, widgets, onAction, onFileUpload, onViewModeChange],
|
|
158
141
|
);
|
|
159
142
|
|
|
160
143
|
return (
|
|
@@ -251,12 +234,12 @@ const MARKDOWN_EDITOR_BLOCKS_NAME = 'MarkdownEditor.Blocks';
|
|
|
251
234
|
type MarkdownEditorBlocksProps = {};
|
|
252
235
|
|
|
253
236
|
const MarkdownEditorBlocks = (_props: MarkdownEditorBlocksProps) => {
|
|
254
|
-
const {
|
|
237
|
+
const { widgets } = useMarkdownEditorContext(MARKDOWN_EDITOR_BLOCKS_NAME);
|
|
255
238
|
|
|
256
239
|
return (
|
|
257
240
|
<>
|
|
258
|
-
{
|
|
259
|
-
<
|
|
241
|
+
{widgets.map(({ id, root, Component, props }) => (
|
|
242
|
+
<div key={id}>{createPortal(<Component {...props} />, root)}</div>
|
|
260
243
|
))}
|
|
261
244
|
</>
|
|
262
245
|
);
|
|
@@ -264,15 +247,6 @@ const MarkdownEditorBlocks = (_props: MarkdownEditorBlocksProps) => {
|
|
|
264
247
|
|
|
265
248
|
MarkdownEditorBlocks.displayName = MARKDOWN_EDITOR_BLOCKS_NAME;
|
|
266
249
|
|
|
267
|
-
const PreviewBlock = ({ el, link }: PreviewBlock) => {
|
|
268
|
-
const client = useClient();
|
|
269
|
-
const dxn = URI.make(link.dxn);
|
|
270
|
-
const subject = client.graph.makeRef(dxn).target;
|
|
271
|
-
const data = useMemo(() => ({ subject }), [subject]);
|
|
272
|
-
|
|
273
|
-
return createPortal(<Surface.Surface type={AppSurface.CardContent} data={data} limit={1} />, el);
|
|
274
|
-
};
|
|
275
|
-
|
|
276
250
|
//
|
|
277
251
|
// MarkdownEditor
|
|
278
252
|
//
|
|
@@ -284,7 +258,7 @@ export const MarkdownEditor = {
|
|
|
284
258
|
Blocks: MarkdownEditorBlocks,
|
|
285
259
|
};
|
|
286
260
|
|
|
287
|
-
export type { MarkdownEditorContentProps, MarkdownEditorToolbarProps
|
|
261
|
+
export type { MarkdownEditorBlocksProps, MarkdownEditorContentProps, MarkdownEditorToolbarProps };
|
|
288
262
|
|
|
289
263
|
/** @deprecated Use `MarkdownEditorProviderProps`. */
|
|
290
264
|
export type MarkdownEditorRootProps = MarkdownEditorProviderProps;
|
|
@@ -19,15 +19,15 @@ import {
|
|
|
19
19
|
type EditorSelectionState,
|
|
20
20
|
type EditorStateStore,
|
|
21
21
|
type ThemeExtensionsOptions,
|
|
22
|
-
mobileSlots,
|
|
23
22
|
createBasicExtensions,
|
|
24
23
|
createMarkdownExtensions,
|
|
25
24
|
createThemeExtensions,
|
|
26
|
-
dropFile,
|
|
27
25
|
documentSlots,
|
|
26
|
+
dropFile,
|
|
27
|
+
editorClassNames,
|
|
28
28
|
formattingListener,
|
|
29
|
+
mobileSlots,
|
|
29
30
|
processEditorPayload,
|
|
30
|
-
editorClassNames,
|
|
31
31
|
scrollbarAutohide,
|
|
32
32
|
} from '@dxos/ui-editor';
|
|
33
33
|
import { type EditorViewMode } from '@dxos/ui-editor/types';
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Surface, useOperationInvoker } from '@dxos/app-framework/ui';
|
|
8
|
+
import { LayoutOperation, Paths } from '@dxos/app-toolkit';
|
|
9
|
+
import { AppSurface } from '@dxos/app-toolkit/ui';
|
|
10
|
+
import { Obj } from '@dxos/echo';
|
|
11
|
+
import { URI } from '@dxos/keys';
|
|
12
|
+
import { useClient } from '@dxos/react-client';
|
|
13
|
+
import { Icon, IconButton } from '@dxos/react-ui';
|
|
14
|
+
import { ResizeHandle, type Size, resizeAttributes, sizeStyle } from '@dxos/react-ui-dnd';
|
|
15
|
+
import { type XmlWidgetProps } from '@dxos/ui-editor';
|
|
16
|
+
|
|
17
|
+
export type PreviewComponentProps = XmlWidgetProps<{
|
|
18
|
+
label: string;
|
|
19
|
+
dxn: string;
|
|
20
|
+
block?: boolean;
|
|
21
|
+
suggest?: boolean;
|
|
22
|
+
onOpen?: (dxn: URI.URI) => void;
|
|
23
|
+
}>;
|
|
24
|
+
|
|
25
|
+
// Persisted height (px) lives in the image alt text after the label, Obsidian-style: ``.
|
|
26
|
+
const HEIGHT_PATTERN = /^(.*)\|(\d+)$/;
|
|
27
|
+
|
|
28
|
+
const parseEmbedLabel = (alt: string): { baseLabel: string; height?: number } => {
|
|
29
|
+
const match = HEIGHT_PATTERN.exec(alt ?? '');
|
|
30
|
+
if (match) {
|
|
31
|
+
const height = Number.parseInt(match[2], 10);
|
|
32
|
+
if (Number.isFinite(height) && height > 0) {
|
|
33
|
+
return { baseLabel: match[1], height };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { baseLabel: alt ?? '' };
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const formatEmbedLabel = (baseLabel: string, height?: number): string =>
|
|
40
|
+
height != null ? `${baseLabel}|${height}` : baseLabel;
|
|
41
|
+
|
|
42
|
+
const MIN_SIZE = 6;
|
|
43
|
+
const FALLBACK_SIZE = 320;
|
|
44
|
+
|
|
45
|
+
/** Scroll the element's top into view (honoring its `scroll-margin`) only if that top is not already visible. */
|
|
46
|
+
const scrollTopIntoViewIfNeeded = (element: HTMLElement): void => {
|
|
47
|
+
let parent = element.parentElement;
|
|
48
|
+
while (parent) {
|
|
49
|
+
const { overflowY } = getComputedStyle(parent);
|
|
50
|
+
if (
|
|
51
|
+
(overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'overlay') &&
|
|
52
|
+
parent.scrollHeight > parent.clientHeight
|
|
53
|
+
) {
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
parent = parent.parentElement;
|
|
57
|
+
}
|
|
58
|
+
const elementTop = element.getBoundingClientRect().top;
|
|
59
|
+
const viewTop = parent ? parent.getBoundingClientRect().top : 0;
|
|
60
|
+
const viewBottom = parent ? parent.getBoundingClientRect().bottom : window.innerHeight;
|
|
61
|
+
if (elementTop < viewTop || elementTop > viewBottom) {
|
|
62
|
+
element.scrollIntoView({ block: 'start', inline: 'nearest' });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Registry-backed block widget for URL-scheme preview slots.
|
|
68
|
+
* Replaces the addBlockContainer callback pattern.
|
|
69
|
+
* Used as the Component entry in a urlSchemes XmlWidgetDef.
|
|
70
|
+
*/
|
|
71
|
+
export const PreviewComponent = ({ dxn, label: alt, onOpen, view, range }: PreviewComponentProps) => {
|
|
72
|
+
const client = useClient();
|
|
73
|
+
const { invokePromise } = useOperationInvoker();
|
|
74
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
75
|
+
const uri = dxn ? URI.make(dxn) : undefined;
|
|
76
|
+
const subject = uri ? client.graph.makeRef<Obj.Unknown>(uri).target : undefined;
|
|
77
|
+
|
|
78
|
+
// px per rem; ResizeHandle works in rem while the persisted height is in px.
|
|
79
|
+
const remSize = useMemo(() => parseFloat(getComputedStyle(document.documentElement).fontSize) || 16, []);
|
|
80
|
+
const { height } = parseEmbedLabel(alt);
|
|
81
|
+
|
|
82
|
+
// `min-content` keeps the embed at its intrinsic height until the user resizes it; the handle then
|
|
83
|
+
// measures the rendered box and switches to an explicit height.
|
|
84
|
+
const [size, setSize] = useState<Size>(height != null ? height / remSize : 'min-content');
|
|
85
|
+
|
|
86
|
+
// Tell the surface it is sized by its container (vs. intrinsic) so content (e.g. an image) can fit.
|
|
87
|
+
const extrinsic = size !== 'min-content';
|
|
88
|
+
const data = useMemo(
|
|
89
|
+
() => (subject ? { subject, attendableId: dxn, extrinsic } : undefined),
|
|
90
|
+
[subject, dxn, extrinsic],
|
|
91
|
+
);
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
setSize(height != null ? height / remSize : 'min-content');
|
|
94
|
+
}, [height, remSize]);
|
|
95
|
+
|
|
96
|
+
// Persist the height (px) into the alt text on drop by rewriting the image node in the source. The
|
|
97
|
+
// node bounds and base label are re-derived from the live document (the captured `range`/`label`
|
|
98
|
+
// can lag a prior edit before React re-renders the widget). When the same object is transcluded
|
|
99
|
+
// more than once, the node whose start is NEAREST the widget's range is chosen so a duplicate
|
|
100
|
+
// embed isn't rewritten by mistake.
|
|
101
|
+
const handleResize = useCallback(
|
|
102
|
+
(next: Size, commit?: boolean) => {
|
|
103
|
+
setSize(next);
|
|
104
|
+
if (!commit || typeof next !== 'number' || !view) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const doc = view.state.doc.toString();
|
|
108
|
+
const marker = `](${dxn})`;
|
|
109
|
+
let open = -1;
|
|
110
|
+
let close = -1;
|
|
111
|
+
for (let at = doc.indexOf(marker); at >= 0; at = doc.indexOf(marker, at + marker.length)) {
|
|
112
|
+
const start = doc.lastIndexOf('`;
|
|
123
|
+
view.dispatch({ changes: { from: open, to: close + marker.length, insert } });
|
|
124
|
+
// After the resized box has laid out, bring its top into frame — but only if that top scrolled
|
|
125
|
+
// out of view. Scroll the element itself (not the CM view) so it works whichever ancestor
|
|
126
|
+
// actually scrolls (cm-scroller or an outer panel); defer a frame so the new height applies first.
|
|
127
|
+
requestAnimationFrame(() => {
|
|
128
|
+
if (containerRef.current) {
|
|
129
|
+
scrollTopIntoViewIfNeeded(containerRef.current);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
[view, range, dxn, remSize],
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
// Open the referenced object: defer to the caller's handler when provided, else navigate to it.
|
|
137
|
+
const handleOpen = useCallback(() => {
|
|
138
|
+
if (!uri || !subject) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (onOpen) {
|
|
142
|
+
onOpen(uri);
|
|
143
|
+
} else {
|
|
144
|
+
void invokePromise?.(LayoutOperation.Open, {
|
|
145
|
+
subject: [Paths.getObjectPathFromObject(subject)],
|
|
146
|
+
navigation: 'immediate',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}, [uri, subject, onOpen, invokePromise]);
|
|
150
|
+
|
|
151
|
+
if (!uri || !subject || !data) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const objectLabel = Obj.getLabel(subject);
|
|
156
|
+
const objectIcon = Obj.getIcon(subject);
|
|
157
|
+
|
|
158
|
+
// Frame transcluded block embeds so they read as a self-contained card within the document flow.
|
|
159
|
+
// The clip/border live on an inner element so they don't clip the resize handle (which straddles the
|
|
160
|
+
// bottom edge); the inner grid stretches the surface to fill the resizable box, overriding any
|
|
161
|
+
// intrinsic aspect.
|
|
162
|
+
return (
|
|
163
|
+
<div
|
|
164
|
+
className='relative grid scroll-mt-16'
|
|
165
|
+
style={sizeStyle(size, 'vertical')}
|
|
166
|
+
{...resizeAttributes}
|
|
167
|
+
ref={containerRef}
|
|
168
|
+
>
|
|
169
|
+
<div className='grid overflow-hidden border border-subdued-separator rounded-md'>
|
|
170
|
+
<Surface.Surface type={AppSurface.Section} data={data} limit={1} />
|
|
171
|
+
</div>
|
|
172
|
+
<div className='absolute top-1 right-1 flex items-center justify-end gap-1'>
|
|
173
|
+
<span className='dx-tag dx-tag--neutral flex items-center gap-1'>
|
|
174
|
+
{objectIcon && <Icon icon={objectIcon.icon} size={4} />}
|
|
175
|
+
{objectLabel}
|
|
176
|
+
</span>
|
|
177
|
+
<IconButton
|
|
178
|
+
density='sm'
|
|
179
|
+
icon='ph--arrow-square-out--regular'
|
|
180
|
+
iconOnly
|
|
181
|
+
label='Open'
|
|
182
|
+
variant='ghost'
|
|
183
|
+
onClick={handleOpen}
|
|
184
|
+
/>
|
|
185
|
+
</div>
|
|
186
|
+
<ResizeHandle
|
|
187
|
+
side='block-end'
|
|
188
|
+
fallbackSize={FALLBACK_SIZE}
|
|
189
|
+
minSize={MIN_SIZE}
|
|
190
|
+
size={size}
|
|
191
|
+
onSizeChange={handleResize}
|
|
192
|
+
/>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -19,8 +19,8 @@ import { Text } from '@dxos/schema';
|
|
|
19
19
|
|
|
20
20
|
import {
|
|
21
21
|
MarkdownEditor,
|
|
22
|
-
MarkdownEditorProvider,
|
|
23
22
|
type MarkdownEditorContentProps,
|
|
23
|
+
MarkdownEditorProvider,
|
|
24
24
|
type MarkdownEditorProviderProps,
|
|
25
25
|
} from '#components';
|
|
26
26
|
import { useLinkQuery } from '#hooks';
|
|
@@ -90,7 +90,7 @@ export const MarkdownArticle = forwardRef<HTMLDivElement, MarkdownArticleProps>(
|
|
|
90
90
|
}, [db, upload]);
|
|
91
91
|
|
|
92
92
|
// Query for @ refs.
|
|
93
|
-
const handleLinkQuery = useLinkQuery(db);
|
|
93
|
+
const handleLinkQuery = useLinkQuery(db, Obj.isObject(object) ? object : undefined);
|
|
94
94
|
|
|
95
95
|
// Open linked objects.
|
|
96
96
|
const { invokePromise } = useOperationInvoker();
|
|
@@ -129,7 +129,7 @@ export const MarkdownArticle = forwardRef<HTMLDivElement, MarkdownArticleProps>(
|
|
|
129
129
|
<Editor.Root {...editorRootProps}>
|
|
130
130
|
<Panel.Root role={role} ref={forwardedRef}>
|
|
131
131
|
{settings.toolbar && (
|
|
132
|
-
<Panel.Toolbar
|
|
132
|
+
<Panel.Toolbar>
|
|
133
133
|
<MarkdownEditor.Toolbar classNames='dx-document' customActions={customActions} />
|
|
134
134
|
</Panel.Toolbar>
|
|
135
135
|
)}
|
|
@@ -29,7 +29,7 @@ export const MarkdownCard = ({ subject }: MarkdownCardProps) => {
|
|
|
29
29
|
return (
|
|
30
30
|
<Card.Body>
|
|
31
31
|
{snippet && (
|
|
32
|
-
<Card.Section className='relative'>
|
|
32
|
+
<Card.Section className='aspect-square relative'>
|
|
33
33
|
<Card.Row fullWidth>
|
|
34
34
|
<MarkdownEditorProvider id={subject.id} viewMode='readonly' extensions={extensions}>
|
|
35
35
|
{(editorRootProps) => (
|
|
@@ -11,7 +11,7 @@ import { translations } from '#translations';
|
|
|
11
11
|
import { MarkdownSettings } from './MarkdownSettings';
|
|
12
12
|
|
|
13
13
|
const meta = {
|
|
14
|
-
title: 'plugins/plugin-markdown/
|
|
14
|
+
title: 'plugins/plugin-markdown/containers/MarkdownSettings',
|
|
15
15
|
tags: ['settings'],
|
|
16
16
|
component: MarkdownSettings,
|
|
17
17
|
decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2023 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
|
|
7
|
+
import { type AppSurface } from '@dxos/app-toolkit/ui';
|
|
8
|
+
import { Input } from '@dxos/react-ui';
|
|
9
|
+
import { Form, type FormFieldRendererProps, FormRow } from '@dxos/react-ui-form';
|
|
10
|
+
|
|
11
|
+
import { meta } from '#meta';
|
|
12
|
+
import { Markdown } from '#types';
|
|
13
|
+
|
|
14
|
+
export type MarkdownSettingsProps = AppSurface.SettingsProps<Markdown.Settings>;
|
|
15
|
+
|
|
16
|
+
export const MarkdownSettings = ({ settings, onSettingsChange }: MarkdownSettingsProps) => {
|
|
17
|
+
return (
|
|
18
|
+
<Form.Root
|
|
19
|
+
variant='settings'
|
|
20
|
+
schema={Markdown.Settings}
|
|
21
|
+
readonly={!onSettingsChange}
|
|
22
|
+
values={settings}
|
|
23
|
+
onValuesChanged={(values) => onSettingsChange?.((current) => ({ ...current, ...values }))}
|
|
24
|
+
>
|
|
25
|
+
<Form.Viewport scroll>
|
|
26
|
+
<Form.Content>
|
|
27
|
+
<Form.Section title={meta.profile.name}>
|
|
28
|
+
<Form.FieldSet
|
|
29
|
+
fieldMap={{ snippets: SnippetsField }}
|
|
30
|
+
filter={(properties) =>
|
|
31
|
+
settings.debug ? properties : properties.filter((property) => property.name !== 'snippets')
|
|
32
|
+
}
|
|
33
|
+
/>
|
|
34
|
+
</Form.Section>
|
|
35
|
+
</Form.Content>
|
|
36
|
+
</Form.Viewport>
|
|
37
|
+
</Form.Root>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/** Multi-line snippet editor; replaces the single-line text input the schema would otherwise render. */
|
|
42
|
+
const SnippetsField = ({ type, readonly, onValueChange, onBlur, ...props }: FormFieldRendererProps<string>) => (
|
|
43
|
+
<FormRow<string> readonly={readonly} {...props}>
|
|
44
|
+
{({ value }) => (
|
|
45
|
+
<Input.TextArea
|
|
46
|
+
disabled={!!readonly}
|
|
47
|
+
rows={5}
|
|
48
|
+
value={value ?? ''}
|
|
49
|
+
onBlur={onBlur}
|
|
50
|
+
onChange={(event) => onValueChange(type, event.target.value)}
|
|
51
|
+
/>
|
|
52
|
+
)}
|
|
53
|
+
</FormRow>
|
|
54
|
+
);
|
package/src/containers/index.ts
CHANGED
|
@@ -9,3 +9,4 @@ export type { MarkdownArticleProps } from './MarkdownArticle';
|
|
|
9
9
|
export const MarkdownCard: ComponentType<any> = lazy(() => import('./MarkdownCard'));
|
|
10
10
|
export const EditableMarkdownCard: ComponentType<any> = lazy(() => import('./EditableMarkdownCard'));
|
|
11
11
|
export const MarkdownArticle: ComponentType<any> = lazy(() => import('./MarkdownArticle'));
|
|
12
|
+
export const MarkdownSettings: ComponentType<any> = lazy(() => import('./MarkdownSettings'));
|
|
@@ -39,7 +39,7 @@ export const useEditorMenuOptions = ({
|
|
|
39
39
|
|
|
40
40
|
case '/':
|
|
41
41
|
default: {
|
|
42
|
-
return filterMenuGroups([
|
|
42
|
+
return filterMenuGroups([linkSlashCommands, formattingCommands, ...(slashCommandGroups ?? [])], (item) =>
|
|
43
43
|
text ? toLocalizedString(item.label, t).toLowerCase().includes(text.toLowerCase()) : true,
|
|
44
44
|
);
|
|
45
45
|
}
|
|
@@ -8,21 +8,23 @@ import { useMemo } from 'react';
|
|
|
8
8
|
import { Paths } from '@dxos/app-toolkit';
|
|
9
9
|
import { debounceAndThrottle } from '@dxos/async';
|
|
10
10
|
import { Obj } from '@dxos/echo';
|
|
11
|
-
import {
|
|
11
|
+
import { Doc } from '@dxos/echo-doc';
|
|
12
12
|
import { invariant } from '@dxos/invariant';
|
|
13
13
|
import { getSpace, useObject } from '@dxos/react-client/echo';
|
|
14
14
|
import { useIdentity } from '@dxos/react-client/halo';
|
|
15
15
|
import { useThemeContext } from '@dxos/react-ui';
|
|
16
|
-
import {
|
|
16
|
+
import { type ViewStateManager, selectionAspect } from '@dxos/react-ui-attention';
|
|
17
17
|
import { Text } from '@dxos/schema';
|
|
18
18
|
import { Domino } from '@dxos/ui';
|
|
19
19
|
import {
|
|
20
|
+
AnchorWidget,
|
|
20
21
|
Cursor,
|
|
21
22
|
type EditorStateStore,
|
|
22
23
|
EditorView,
|
|
23
24
|
type Extension,
|
|
24
25
|
InputModeExtensions,
|
|
25
|
-
type
|
|
26
|
+
type XmlWidgetProps,
|
|
27
|
+
type XmlWidgetState,
|
|
26
28
|
createDataExtensions,
|
|
27
29
|
decorateMarkdown,
|
|
28
30
|
documentId,
|
|
@@ -30,16 +32,17 @@ import {
|
|
|
30
32
|
formattingKeymap,
|
|
31
33
|
linkTooltip,
|
|
32
34
|
listener,
|
|
33
|
-
preview,
|
|
34
35
|
replacer,
|
|
35
36
|
selectionState,
|
|
36
37
|
snippets,
|
|
38
|
+
xmlTags,
|
|
37
39
|
} from '@dxos/ui-editor';
|
|
38
40
|
import { type EditorViewMode, type RenderCallback } from '@dxos/ui-editor/types';
|
|
39
41
|
import { isTruthy, safeUrl } from '@dxos/util';
|
|
40
42
|
|
|
41
43
|
import { Markdown } from '#types';
|
|
42
44
|
|
|
45
|
+
import { PreviewComponent } from '../components/PreviewComponent/PreviewComponent';
|
|
43
46
|
import { setFallbackName } from '../util';
|
|
44
47
|
|
|
45
48
|
export type DocumentType = Markdown.Document | Text.Text | { id: string; text: string };
|
|
@@ -53,7 +56,7 @@ export type ExtensionsOptions = {
|
|
|
53
56
|
editable?: boolean;
|
|
54
57
|
viewState?: ViewStateManager;
|
|
55
58
|
editorStateStore?: EditorStateStore;
|
|
56
|
-
|
|
59
|
+
setWidgets?: (widgets: XmlWidgetState[]) => void;
|
|
57
60
|
platform?: 'mobile' | 'desktop';
|
|
58
61
|
/** Callback when an internal link is clicked. */
|
|
59
62
|
onSelectObject?: (objectId: string) => void;
|
|
@@ -68,7 +71,7 @@ export const useExtensions = ({
|
|
|
68
71
|
viewMode,
|
|
69
72
|
viewState,
|
|
70
73
|
editorStateStore,
|
|
71
|
-
|
|
74
|
+
setWidgets,
|
|
72
75
|
onSelectObject,
|
|
73
76
|
}: ExtensionsOptions): Extension[] => {
|
|
74
77
|
const { platform } = useThemeContext();
|
|
@@ -79,7 +82,7 @@ export const useExtensions = ({
|
|
|
79
82
|
const contentRef = Obj.instanceOf(Markdown.Document, object) ? (object as Markdown.Document).content : undefined;
|
|
80
83
|
// Use useObject to trigger re-render when the reference loads (returns snapshot for reactivity).
|
|
81
84
|
useObject(contentRef);
|
|
82
|
-
// Get the actual live object target via .target (needed for
|
|
85
|
+
// Get the actual live object target via .target (needed for Doc.createAccessor).
|
|
83
86
|
const target = contentRef?.target ?? (Obj.instanceOf(Text.Text, object) ? object : undefined);
|
|
84
87
|
|
|
85
88
|
// TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.
|
|
@@ -96,7 +99,7 @@ export const useExtensions = ({
|
|
|
96
99
|
compact,
|
|
97
100
|
viewMode,
|
|
98
101
|
viewState,
|
|
99
|
-
|
|
102
|
+
setWidgets,
|
|
100
103
|
platform,
|
|
101
104
|
onSelectObject,
|
|
102
105
|
}),
|
|
@@ -106,7 +109,7 @@ export const useExtensions = ({
|
|
|
106
109
|
compact,
|
|
107
110
|
viewMode,
|
|
108
111
|
viewState,
|
|
109
|
-
|
|
112
|
+
setWidgets,
|
|
110
113
|
settings,
|
|
111
114
|
settings?.debug,
|
|
112
115
|
settings?.editorInputMode,
|
|
@@ -125,7 +128,7 @@ export const useExtensions = ({
|
|
|
125
128
|
target &&
|
|
126
129
|
createDataExtensions({
|
|
127
130
|
id,
|
|
128
|
-
text:
|
|
131
|
+
text: Doc.createAccessor(target, ['content']),
|
|
129
132
|
messenger: space,
|
|
130
133
|
identity,
|
|
131
134
|
}),
|
|
@@ -156,7 +159,7 @@ const createBaseExtensions = ({
|
|
|
156
159
|
compact,
|
|
157
160
|
viewMode,
|
|
158
161
|
viewState,
|
|
159
|
-
|
|
162
|
+
setWidgets,
|
|
160
163
|
platform,
|
|
161
164
|
}: ExtensionsOptions): Extension[] => {
|
|
162
165
|
const extensions: Extension[] = [
|
|
@@ -177,9 +180,26 @@ const createBaseExtensions = ({
|
|
|
177
180
|
numberedHeadings: settings?.numberedHeadings ? { from: 2 } : undefined,
|
|
178
181
|
// TODO(wittjosiah): For internal links render the label of the object.
|
|
179
182
|
renderLinkButton: onSelectObject && createRenderLink(onSelectObject),
|
|
183
|
+
// xmlTags() handles dxn:/echo: links via url-scheme widgets; skip here to avoid double-processing.
|
|
184
|
+
skip: ({ url }) => url.startsWith('dxn:') || url.startsWith('echo:'),
|
|
180
185
|
}),
|
|
181
186
|
linkTooltip(renderLinkTooltip),
|
|
182
|
-
|
|
187
|
+
xmlTags({
|
|
188
|
+
registry: {
|
|
189
|
+
'dxn-preview': {
|
|
190
|
+
block: true,
|
|
191
|
+
urlSchemes: ['dxn:', 'echo:'],
|
|
192
|
+
Component: PreviewComponent,
|
|
193
|
+
},
|
|
194
|
+
'link-preview': {
|
|
195
|
+
block: false,
|
|
196
|
+
urlSchemes: ['dxn:', 'echo:'],
|
|
197
|
+
factory: ({ label, dxn }: XmlWidgetProps<{ label: string; dxn: string }>) =>
|
|
198
|
+
label && dxn ? new AnchorWidget(label, dxn) : null,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
setWidgets,
|
|
202
|
+
}),
|
|
183
203
|
replacer(),
|
|
184
204
|
],
|
|
185
205
|
);
|
|
@@ -14,7 +14,7 @@ import { insertAtCursor, insertAtLineStart } from '@dxos/ui-editor';
|
|
|
14
14
|
|
|
15
15
|
import { Markdown } from '../types';
|
|
16
16
|
|
|
17
|
-
export const useLinkQuery = (db: Database.Database | undefined) => {
|
|
17
|
+
export const useLinkQuery = (db: Database.Database | undefined, current?: Obj.Unknown) => {
|
|
18
18
|
const { t } = useTranslation();
|
|
19
19
|
|
|
20
20
|
const filter = useMemo(
|
|
@@ -41,7 +41,9 @@ export const useLinkQuery = (db: Database.Database | undefined) => {
|
|
|
41
41
|
|
|
42
42
|
const items =
|
|
43
43
|
results
|
|
44
|
-
|
|
44
|
+
// Exclude the current document; it cannot link to itself.
|
|
45
|
+
?.filter((object) => object.id !== current?.id)
|
|
46
|
+
.filter((object) => toLocalizedString(getLabel(object), t).toLowerCase().includes(name))
|
|
45
47
|
.map((object: Obj.Unknown): EditorMenuItem => {
|
|
46
48
|
const type = Obj.getType(object);
|
|
47
49
|
const icon = type
|
|
@@ -87,7 +89,7 @@ export const useLinkQuery = (db: Database.Database | undefined) => {
|
|
|
87
89
|
{ id: 'create', items: [createItem] },
|
|
88
90
|
];
|
|
89
91
|
},
|
|
90
|
-
[db, filter, t],
|
|
92
|
+
[db, filter, t, current],
|
|
91
93
|
);
|
|
92
94
|
|
|
93
95
|
return handleLinkQuery;
|