@dxos/plugin-markdown 0.8.4-main.e098934 → 0.8.4-main.e8ec1fe
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/browser/MarkdownCard-JYMDPKV5.mjs +12 -0
- package/dist/lib/browser/MarkdownContainer-Y75XSVBX.mjs +15 -0
- package/dist/lib/browser/{anchor-sort-E33BSTYF.mjs → anchor-sort-3HGPGCOO.mjs} +6 -7
- package/dist/lib/browser/anchor-sort-3HGPGCOO.mjs.map +7 -0
- package/dist/lib/browser/{app-graph-serializer-OX62DNPT.mjs → app-graph-serializer-POZN234F.mjs} +10 -10
- package/dist/lib/browser/app-graph-serializer-POZN234F.mjs.map +7 -0
- package/dist/lib/browser/blueprint-definition-GIPKFDY5.mjs +13 -0
- package/dist/lib/browser/blueprint-definition-GIPKFDY5.mjs.map +7 -0
- package/dist/lib/browser/{chunk-Z7P6JGGW.mjs → chunk-22XSSNBS.mjs} +7 -4
- package/dist/lib/browser/{chunk-Z7P6JGGW.mjs.map → chunk-22XSSNBS.mjs.map} +2 -2
- package/dist/lib/browser/chunk-2MLGSYRN.mjs +20 -0
- package/dist/lib/browser/chunk-2MLGSYRN.mjs.map +7 -0
- package/dist/lib/browser/{chunk-ODB2PTBP.mjs → chunk-BQTYJOFB.mjs} +4 -4
- package/dist/lib/browser/chunk-BQTYJOFB.mjs.map +7 -0
- package/dist/lib/browser/{chunk-LAVZ2W6X.mjs → chunk-GH6GQSBL.mjs} +9 -8
- package/dist/lib/browser/chunk-GH6GQSBL.mjs.map +7 -0
- package/dist/lib/browser/{chunk-OY6CGPOO.mjs → chunk-IBCHVMZW.mjs} +2 -2
- package/dist/lib/browser/{chunk-OY6CGPOO.mjs.map → chunk-IBCHVMZW.mjs.map} +2 -2
- package/dist/lib/browser/chunk-K3LXOU3E.mjs +827 -0
- package/dist/lib/browser/chunk-K3LXOU3E.mjs.map +7 -0
- package/dist/lib/browser/chunk-PBJLFIOX.mjs +96 -0
- package/dist/lib/browser/chunk-PBJLFIOX.mjs.map +7 -0
- package/dist/lib/browser/{chunk-BEE7VQPU.mjs → chunk-QYSEJ5GP.mjs} +13 -12
- package/dist/lib/browser/chunk-QYSEJ5GP.mjs.map +7 -0
- package/dist/lib/browser/chunk-Y53FQREH.mjs +150 -0
- package/dist/lib/browser/chunk-Y53FQREH.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +25 -24
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-WDDH56JC.mjs → intent-resolver-Z5L7TXUK.mjs} +8 -8
- package/dist/lib/browser/intent-resolver-Z5L7TXUK.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-NY5K2I5R.mjs → react-surface-GO5ZOKNN.mjs} +59 -63
- package/dist/lib/browser/react-surface-GO5ZOKNN.mjs.map +7 -0
- package/dist/lib/browser/{settings-AABBTB4Q.mjs → settings-TZUDB5EW.mjs} +5 -5
- package/dist/lib/browser/{settings-AABBTB4Q.mjs.map → settings-TZUDB5EW.mjs.map} +1 -1
- package/dist/lib/browser/{state-FTHQQX7V.mjs → state-BTUKVZHY.mjs} +5 -5
- package/dist/lib/browser/{state-FTHQQX7V.mjs.map → state-BTUKVZHY.mjs.map} +1 -1
- package/dist/lib/browser/toolkit.mjs +13 -0
- package/dist/lib/browser/toolkit.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +2 -2
- package/dist/lib/node-esm/MarkdownCard-ZXPJLUYO.mjs +13 -0
- package/dist/lib/node-esm/MarkdownCard-ZXPJLUYO.mjs.map +7 -0
- package/dist/lib/node-esm/MarkdownContainer-YRDSRDCS.mjs +16 -0
- package/dist/lib/node-esm/MarkdownContainer-YRDSRDCS.mjs.map +7 -0
- package/dist/lib/node-esm/{anchor-sort-ALP2NH24.mjs → anchor-sort-PCDXEBJ2.mjs} +6 -7
- package/dist/lib/node-esm/anchor-sort-PCDXEBJ2.mjs.map +7 -0
- package/dist/lib/node-esm/{app-graph-serializer-56TD3BMX.mjs → app-graph-serializer-NF65JYAS.mjs} +10 -10
- package/dist/lib/node-esm/app-graph-serializer-NF65JYAS.mjs.map +7 -0
- package/dist/lib/node-esm/blueprint-definition-ENKJZYQS.mjs +14 -0
- package/dist/lib/node-esm/blueprint-definition-ENKJZYQS.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-J7A6TUB2.mjs → chunk-AMHACOXW.mjs} +7 -4
- package/dist/lib/node-esm/{chunk-J7A6TUB2.mjs.map → chunk-AMHACOXW.mjs.map} +2 -2
- package/dist/lib/node-esm/chunk-CT7CFX5G.mjs +828 -0
- package/dist/lib/node-esm/chunk-CT7CFX5G.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-CB2R4YIY.mjs → chunk-GMMVSXQ6.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-CB2R4YIY.mjs.map → chunk-GMMVSXQ6.mjs.map} +2 -2
- package/dist/lib/node-esm/chunk-HAIEWPU7.mjs +151 -0
- package/dist/lib/node-esm/chunk-HAIEWPU7.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-KCHUTL3Q.mjs +22 -0
- package/dist/lib/node-esm/chunk-KCHUTL3Q.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-FXILAQ5F.mjs → chunk-NGYJNQ6A.mjs} +13 -12
- package/dist/lib/node-esm/chunk-NGYJNQ6A.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-PIOOG7A5.mjs +97 -0
- package/dist/lib/node-esm/chunk-PIOOG7A5.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-O6EXWGGS.mjs → chunk-PLZ7EVCT.mjs} +9 -8
- package/dist/lib/node-esm/chunk-PLZ7EVCT.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-VCG2U522.mjs → chunk-SHAMSMKQ.mjs} +4 -4
- package/dist/lib/node-esm/chunk-SHAMSMKQ.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +25 -24
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-2I5HKCUU.mjs → intent-resolver-6B3PFQ5F.mjs} +8 -8
- package/dist/lib/node-esm/intent-resolver-6B3PFQ5F.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-AUWSLYJS.mjs → react-surface-I46BPCWT.mjs} +59 -63
- package/dist/lib/node-esm/react-surface-I46BPCWT.mjs.map +7 -0
- package/dist/lib/node-esm/{settings-CXGR6DH4.mjs → settings-CJ3T5EX4.mjs} +5 -5
- package/dist/lib/node-esm/{settings-CXGR6DH4.mjs.map → settings-CJ3T5EX4.mjs.map} +1 -1
- package/dist/lib/node-esm/{state-NWMQ3XAI.mjs → state-K6EH7SRZ.mjs} +5 -5
- package/dist/lib/node-esm/{state-NWMQ3XAI.mjs.map → state-K6EH7SRZ.mjs.map} +1 -1
- package/dist/lib/node-esm/toolkit.mjs +14 -0
- package/dist/lib/node-esm/toolkit.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +2 -2
- package/dist/types/src/MarkdownPlugin.d.ts +1 -1
- package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/anchor-sort.d.ts +2 -4
- package/dist/types/src/capabilities/anchor-sort.d.ts.map +1 -1
- package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -3
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +1 -5
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownCard/MarkdownCard.d.ts +3 -3
- package/dist/types/src/components/MarkdownCard/MarkdownCard.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownCard/MarkdownCard.stories.d.ts +0 -1
- package/dist/types/src/components/MarkdownCard/MarkdownCard.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.d.ts +8 -12
- package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownContainer.stories.d.ts +7 -4
- package/dist/types/src/components/MarkdownContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/FileUpload.d.ts +11 -0
- package/dist/types/src/components/MarkdownEditor/FileUpload.d.ts.map +1 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts +42 -23
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts +5 -110
- package/dist/types/src/components/MarkdownEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts +26 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts.map +1 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorToolbar.d.ts +12 -0
- package/dist/types/src/components/MarkdownEditor/MarkdownEditorToolbar.d.ts.map +1 -0
- package/dist/types/src/components/Suggestions.stories.d.ts +1 -2
- package/dist/types/src/components/Suggestions.stories.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +3 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/functions/create.d.ts +8 -0
- package/dist/types/src/functions/create.d.ts.map +1 -0
- package/dist/types/src/functions/create.test.d.ts +2 -0
- package/dist/types/src/functions/create.test.d.ts.map +1 -0
- package/dist/types/src/functions/index.d.ts +17 -2
- package/dist/types/src/functions/index.d.ts.map +1 -1
- package/dist/types/src/functions/open.d.ts +1 -1
- package/dist/types/src/functions/open.d.ts.map +1 -1
- package/dist/types/src/functions/{diff.d.ts → update.d.ts} +2 -2
- package/dist/types/src/functions/update.d.ts.map +1 -0
- package/dist/types/src/functions/update.test.d.ts +2 -0
- package/dist/types/src/functions/update.test.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +3 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useEditorMenuOptions.d.ts +9 -0
- package/dist/types/src/hooks/useEditorMenuOptions.d.ts.map +1 -0
- package/dist/types/src/hooks/useExtensions.d.ts +21 -0
- package/dist/types/src/hooks/useExtensions.d.ts.map +1 -0
- package/dist/types/src/hooks/useLinkQuery.d.ts +4 -0
- package/dist/types/src/hooks/useLinkQuery.d.ts.map +1 -0
- package/dist/types/src/hooks/useSelectCurrentThread.d.ts +1 -1
- package/dist/types/src/hooks/useSelectCurrentThread.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +6 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/dist/types/src/toolkit.d.ts +3 -0
- package/dist/types/src/toolkit.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +3 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Markdown.d.ts +6 -4
- package/dist/types/src/types/Markdown.d.ts.map +1 -1
- package/dist/types/src/types/MarkdownAction.d.ts +2 -1
- package/dist/types/src/types/MarkdownAction.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +3 -3
- package/dist/types/src/util.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +71 -55
- package/src/MarkdownPlugin.tsx +99 -101
- package/src/capabilities/anchor-sort.ts +3 -3
- package/src/capabilities/app-graph-serializer.ts +5 -5
- package/src/capabilities/artifact-definition.ts +6 -5
- package/src/capabilities/blueprint-definition.ts +30 -26
- package/src/capabilities/capabilities.ts +1 -0
- package/src/capabilities/index.ts +1 -2
- package/src/capabilities/intent-resolver.ts +3 -2
- package/src/capabilities/react-surface.tsx +44 -66
- package/src/components/MarkdownCard/MarkdownCard.stories.tsx +6 -9
- package/src/components/MarkdownCard/MarkdownCard.tsx +52 -38
- package/src/components/MarkdownContainer.stories.tsx +74 -38
- package/src/components/MarkdownContainer.tsx +78 -220
- package/src/components/MarkdownEditor/FileUpload.tsx +63 -0
- package/src/components/MarkdownEditor/MarkdownEditor.stories.tsx +55 -35
- package/src/components/MarkdownEditor/MarkdownEditor.tsx +221 -270
- package/src/components/MarkdownEditor/MarkdownEditorContent.tsx +136 -0
- package/src/components/MarkdownEditor/MarkdownEditorToolbar.tsx +63 -0
- package/src/components/Suggestions.stories.tsx +40 -33
- package/src/components/index.ts +3 -1
- package/src/functions/create.conversations.json +1 -0
- package/src/functions/create.test.ts +128 -0
- package/src/functions/create.ts +34 -0
- package/src/functions/index.ts +9 -2
- package/src/functions/open.ts +4 -2
- package/src/functions/update.conversations.json +1 -0
- package/src/functions/update.test.ts +151 -0
- package/src/functions/{diff.ts → update.ts} +4 -2
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useEditorMenuOptions.ts +71 -0
- package/src/{extensions.tsx → hooks/useExtensions.tsx} +60 -81
- package/src/hooks/useLinkQuery.ts +83 -0
- package/src/hooks/useSelectCurrentThread.tsx +15 -5
- package/src/meta.ts +3 -3
- package/src/testing.ts +27 -0
- package/src/toolkit.ts +6 -0
- package/src/translations.ts +3 -0
- package/src/types/Markdown.ts +9 -7
- package/src/types/MarkdownAction.ts +1 -1
- package/src/types/index.ts +1 -0
- package/src/util.tsx +10 -5
- package/dist/lib/browser/MarkdownCard-JLUQITYK.mjs +0 -80
- package/dist/lib/browser/MarkdownCard-JLUQITYK.mjs.map +0 -7
- package/dist/lib/browser/MarkdownContainer-HMPNQMNG.mjs +0 -751
- package/dist/lib/browser/MarkdownContainer-HMPNQMNG.mjs.map +0 -7
- package/dist/lib/browser/anchor-sort-E33BSTYF.mjs.map +0 -7
- package/dist/lib/browser/app-graph-serializer-OX62DNPT.mjs.map +0 -7
- package/dist/lib/browser/blueprint-definition-5YKFUHRU.mjs +0 -11
- package/dist/lib/browser/chunk-BEE7VQPU.mjs.map +0 -7
- package/dist/lib/browser/chunk-F6JJLKLN.mjs +0 -102
- package/dist/lib/browser/chunk-F6JJLKLN.mjs.map +0 -7
- package/dist/lib/browser/chunk-LAVZ2W6X.mjs.map +0 -7
- package/dist/lib/browser/chunk-ODB2PTBP.mjs.map +0 -7
- package/dist/lib/browser/chunk-XE66SH4O.mjs +0 -22
- package/dist/lib/browser/chunk-XE66SH4O.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-WDDH56JC.mjs.map +0 -7
- package/dist/lib/browser/react-surface-NY5K2I5R.mjs.map +0 -7
- package/dist/lib/browser/toolkit-2AJTHG74.mjs +0 -74
- package/dist/lib/browser/toolkit-2AJTHG74.mjs.map +0 -7
- package/dist/lib/node-esm/MarkdownCard-XL5EVSJ7.mjs +0 -81
- package/dist/lib/node-esm/MarkdownCard-XL5EVSJ7.mjs.map +0 -7
- package/dist/lib/node-esm/MarkdownContainer-5FTROSXN.mjs +0 -752
- package/dist/lib/node-esm/MarkdownContainer-5FTROSXN.mjs.map +0 -7
- package/dist/lib/node-esm/anchor-sort-ALP2NH24.mjs.map +0 -7
- package/dist/lib/node-esm/app-graph-serializer-56TD3BMX.mjs.map +0 -7
- package/dist/lib/node-esm/blueprint-definition-GVW67KGV.mjs +0 -12
- package/dist/lib/node-esm/chunk-DVK63TD3.mjs +0 -103
- package/dist/lib/node-esm/chunk-DVK63TD3.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-FXILAQ5F.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-O6EXWGGS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-Q2BREK2M.mjs +0 -24
- package/dist/lib/node-esm/chunk-Q2BREK2M.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-VCG2U522.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-2I5HKCUU.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-AUWSLYJS.mjs.map +0 -7
- package/dist/lib/node-esm/toolkit-RC44I2MI.mjs +0 -75
- package/dist/lib/node-esm/toolkit-RC44I2MI.mjs.map +0 -7
- package/dist/types/src/capabilities/toolkit.d.ts +0 -4
- package/dist/types/src/capabilities/toolkit.d.ts.map +0 -1
- package/dist/types/src/components/Toolbar.stories.d.ts +0 -48
- package/dist/types/src/components/Toolbar.stories.d.ts.map +0 -1
- package/dist/types/src/extensions.d.ts +0 -22
- package/dist/types/src/extensions.d.ts.map +0 -1
- package/dist/types/src/functions/diff.d.ts.map +0 -1
- package/src/capabilities/toolkit.ts +0 -47
- package/src/components/Toolbar.stories.tsx +0 -118
- /package/dist/lib/browser/{blueprint-definition-5YKFUHRU.mjs.map → MarkdownCard-JYMDPKV5.mjs.map} +0 -0
- /package/dist/lib/{node-esm/blueprint-definition-GVW67KGV.mjs.map → browser/MarkdownContainer-Y75XSVBX.mjs.map} +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, it } from '@effect/vitest';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import * as Layer from 'effect/Layer';
|
|
8
|
+
|
|
9
|
+
import { AiService, ConsolePrinter, MemoizedAiService } from '@dxos/ai';
|
|
10
|
+
import { TestAiService } from '@dxos/ai/testing';
|
|
11
|
+
import {
|
|
12
|
+
AiConversation,
|
|
13
|
+
type ContextBinding,
|
|
14
|
+
GenerationObserver,
|
|
15
|
+
makeToolExecutionServiceFromFunctions,
|
|
16
|
+
makeToolResolverFromFunctions,
|
|
17
|
+
} from '@dxos/assistant';
|
|
18
|
+
import { Blueprint } from '@dxos/blueprints';
|
|
19
|
+
import { PropertiesType } from '@dxos/client-protocol';
|
|
20
|
+
import { Obj, Query, Ref } from '@dxos/echo';
|
|
21
|
+
import { TestHelpers, acquireReleaseResource } from '@dxos/effect';
|
|
22
|
+
import {
|
|
23
|
+
CredentialsService,
|
|
24
|
+
DatabaseService,
|
|
25
|
+
FunctionInvocationService,
|
|
26
|
+
QueueService,
|
|
27
|
+
TracingService,
|
|
28
|
+
} from '@dxos/functions';
|
|
29
|
+
import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
|
|
30
|
+
import { invariant } from '@dxos/invariant';
|
|
31
|
+
import { ObjectId } from '@dxos/keys';
|
|
32
|
+
import { Markdown } from '@dxos/plugin-markdown/types';
|
|
33
|
+
import { Collection } from '@dxos/schema';
|
|
34
|
+
import { HasSubject, type Message } from '@dxos/types';
|
|
35
|
+
|
|
36
|
+
import { WithProperties, testToolkit } from '../testing';
|
|
37
|
+
import { MarkdownBlueprint, MarkdownFunction } from '../toolkit';
|
|
38
|
+
|
|
39
|
+
ObjectId.dangerouslyDisableRandomness();
|
|
40
|
+
|
|
41
|
+
const TestLayer = Layer.mergeAll(
|
|
42
|
+
AiService.model('@anthropic/claude-opus-4-0'),
|
|
43
|
+
makeToolResolverFromFunctions([MarkdownFunction.create, MarkdownFunction.open, MarkdownFunction.update], testToolkit),
|
|
44
|
+
makeToolExecutionServiceFromFunctions(testToolkit, testToolkit.toLayer({}) as any),
|
|
45
|
+
).pipe(
|
|
46
|
+
Layer.provideMerge(
|
|
47
|
+
FunctionInvocationServiceLayerTest({
|
|
48
|
+
functions: [MarkdownFunction.create, MarkdownFunction.open, MarkdownFunction.update],
|
|
49
|
+
}),
|
|
50
|
+
),
|
|
51
|
+
Layer.provideMerge(
|
|
52
|
+
Layer.mergeAll(
|
|
53
|
+
TestAiService(),
|
|
54
|
+
TestDatabaseLayer({
|
|
55
|
+
spaceKey: 'fixed',
|
|
56
|
+
indexing: { vector: true },
|
|
57
|
+
types: [PropertiesType, Collection.Collection, Blueprint.Blueprint, Markdown.Document, HasSubject.HasSubject],
|
|
58
|
+
}),
|
|
59
|
+
CredentialsService.configuredLayer([]),
|
|
60
|
+
TracingService.layerNoop,
|
|
61
|
+
),
|
|
62
|
+
),
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
describe('update', () => {
|
|
66
|
+
it.effect(
|
|
67
|
+
'call a function to update a markdown document',
|
|
68
|
+
Effect.fnUntraced(
|
|
69
|
+
function* (_) {
|
|
70
|
+
const doc = Markdown.make({
|
|
71
|
+
name: 'BlueYard',
|
|
72
|
+
content: 'Founders and portfolio of BlueYard.',
|
|
73
|
+
});
|
|
74
|
+
yield* DatabaseService.add(doc);
|
|
75
|
+
|
|
76
|
+
yield* FunctionInvocationService.invokeFunction(MarkdownFunction.update, {
|
|
77
|
+
id: doc.id,
|
|
78
|
+
diffs: ['- Founders', '+ # Founders'],
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const updatedDoc = yield* DatabaseService.resolve(Obj.getDXN(doc), Markdown.Document);
|
|
82
|
+
expect(updatedDoc.name).toBe(doc.name);
|
|
83
|
+
const text = yield* DatabaseService.load(updatedDoc.content);
|
|
84
|
+
expect(text.content).toBe('# Founders and portfolio of BlueYard.');
|
|
85
|
+
},
|
|
86
|
+
WithProperties,
|
|
87
|
+
Effect.provide(TestLayer),
|
|
88
|
+
TestHelpers.provideTestContext,
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
it.scoped(
|
|
93
|
+
'create and update a markdown document',
|
|
94
|
+
Effect.fnUntraced(
|
|
95
|
+
function* (_) {
|
|
96
|
+
const queue = yield* QueueService.createQueue<Message.Message | ContextBinding>();
|
|
97
|
+
const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
|
|
98
|
+
|
|
99
|
+
yield* DatabaseService.flush({ indexes: true });
|
|
100
|
+
const markdownBlueprint = yield* DatabaseService.add(Obj.clone(MarkdownBlueprint));
|
|
101
|
+
yield* Effect.promise(() =>
|
|
102
|
+
conversation.context.bind({
|
|
103
|
+
blueprints: [Ref.make(markdownBlueprint)],
|
|
104
|
+
}),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const observer = GenerationObserver.fromPrinter(new ConsolePrinter());
|
|
108
|
+
|
|
109
|
+
yield* conversation.createRequest({
|
|
110
|
+
observer,
|
|
111
|
+
prompt: `Create a document with a cookie recipe.`,
|
|
112
|
+
});
|
|
113
|
+
{
|
|
114
|
+
const { objects: docs } = yield* DatabaseService.runQuery(Query.type(Markdown.Document));
|
|
115
|
+
if (docs.length !== 1) {
|
|
116
|
+
throw new Error(`Expected 1 document; got ${docs.length}: ${docs.map((_) => _.name)}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const doc = docs[0];
|
|
120
|
+
invariant(Obj.instanceOf(Markdown.Document, doc));
|
|
121
|
+
console.log({
|
|
122
|
+
name: doc.name,
|
|
123
|
+
content: yield* DatabaseService.load(doc.content).pipe(Effect.map((_) => _.content)),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
yield* conversation.createRequest({
|
|
128
|
+
observer,
|
|
129
|
+
prompt: 'Add a section with a holiday-themed variation.',
|
|
130
|
+
});
|
|
131
|
+
{
|
|
132
|
+
const { objects: docs } = yield* DatabaseService.runQuery(Query.type(Markdown.Document));
|
|
133
|
+
if (docs.length !== 1) {
|
|
134
|
+
throw new Error(`Expected 1 document; got ${docs.length}: ${docs.map((_) => _.name)}`);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const doc = docs[0];
|
|
138
|
+
invariant(Obj.instanceOf(Markdown.Document, doc));
|
|
139
|
+
console.log({
|
|
140
|
+
name: doc.name,
|
|
141
|
+
content: yield* DatabaseService.load(doc.content).pipe(Effect.map((_) => _.content)),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
WithProperties,
|
|
146
|
+
Effect.provide(TestLayer),
|
|
147
|
+
TestHelpers.provideTestContext,
|
|
148
|
+
),
|
|
149
|
+
MemoizedAiService.isGenerationEnabled() ? 240_000 : 30_000,
|
|
150
|
+
);
|
|
151
|
+
});
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Effect from 'effect/Effect';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
6
7
|
|
|
7
8
|
import { ArtifactId, applyDiffs } from '@dxos/assistant';
|
|
8
9
|
import { createDocAccessor } from '@dxos/echo-db';
|
|
@@ -13,7 +14,8 @@ import { Markdown } from '../types';
|
|
|
13
14
|
|
|
14
15
|
// TODO(wittjosiah): Reconcile with ThreadAction.AddProposal.
|
|
15
16
|
export default defineFunction({
|
|
16
|
-
|
|
17
|
+
key: 'dxos.org/function/markdown/update',
|
|
18
|
+
name: 'Update',
|
|
17
19
|
description: trim`
|
|
18
20
|
Applies a set of diffs to the markdown document.
|
|
19
21
|
`,
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type EditorView } from '@codemirror/view';
|
|
6
|
+
import { useCallback, useMemo, useRef } from 'react';
|
|
7
|
+
|
|
8
|
+
import { Domino, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
import {
|
|
10
|
+
type EditorMenuGroup,
|
|
11
|
+
type UseEditorMenuProps,
|
|
12
|
+
filterMenuGroups,
|
|
13
|
+
formattingCommands,
|
|
14
|
+
linkSlashCommands,
|
|
15
|
+
} from '@dxos/react-ui-editor';
|
|
16
|
+
|
|
17
|
+
import { meta } from '../meta';
|
|
18
|
+
|
|
19
|
+
export type UseEditorMenuOptionsProps = {
|
|
20
|
+
editorView?: EditorView;
|
|
21
|
+
slashCommandGroups?: EditorMenuGroup[];
|
|
22
|
+
onLinkQuery?: (query?: string) => Promise<EditorMenuGroup[]>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const useEditorMenuOptions = ({
|
|
26
|
+
editorView,
|
|
27
|
+
slashCommandGroups,
|
|
28
|
+
onLinkQuery,
|
|
29
|
+
}: UseEditorMenuOptionsProps): UseEditorMenuProps => {
|
|
30
|
+
const { t } = useTranslation(meta.id);
|
|
31
|
+
|
|
32
|
+
const getMenu = useCallback<NonNullable<UseEditorMenuProps['getMenu']>>(
|
|
33
|
+
({ text, trigger }) => {
|
|
34
|
+
switch (trigger) {
|
|
35
|
+
case '@': {
|
|
36
|
+
return onLinkQuery?.(text) ?? [];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
case '/':
|
|
40
|
+
default: {
|
|
41
|
+
return filterMenuGroups([formattingCommands, linkSlashCommands, ...(slashCommandGroups ?? [])], (item) =>
|
|
42
|
+
text ? toLocalizedString(item.label, t).toLowerCase().includes(text.toLowerCase()) : true,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
[slashCommandGroups, onLinkQuery],
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const viewRef = useRef(editorView);
|
|
51
|
+
return useMemo<UseEditorMenuProps>(() => {
|
|
52
|
+
const trigger = onLinkQuery ? ['/', '@'] : ['/'];
|
|
53
|
+
const placeholder = {
|
|
54
|
+
delay: 3_000,
|
|
55
|
+
content: () =>
|
|
56
|
+
Domino.of('div')
|
|
57
|
+
.children(
|
|
58
|
+
Domino.of('span').text('Press'),
|
|
59
|
+
...trigger.map((text) =>
|
|
60
|
+
Domino.of('span')
|
|
61
|
+
.classNames('mx-1 pli-1.5 pt-[1px] pb-[2px] border border-separator rounded-sm')
|
|
62
|
+
.text(text),
|
|
63
|
+
),
|
|
64
|
+
Domino.of('span').text('for commands.'),
|
|
65
|
+
)
|
|
66
|
+
.build(),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return { viewRef, getMenu, trigger, placeholder };
|
|
70
|
+
}, [getMenu, onLinkQuery]);
|
|
71
|
+
};
|
|
@@ -6,16 +6,13 @@ import { type ViewUpdate } from '@codemirror/view';
|
|
|
6
6
|
import React, { type AnchorHTMLAttributes, type ReactNode, useMemo } from 'react';
|
|
7
7
|
import { createRoot } from 'react-dom/client';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
type PromiseIntentDispatcher,
|
|
12
|
-
createIntent,
|
|
13
|
-
useCapabilities,
|
|
14
|
-
useIntentDispatcher,
|
|
15
|
-
} from '@dxos/app-framework';
|
|
9
|
+
import { LayoutAction, type PromiseIntentDispatcher, createIntent } from '@dxos/app-framework';
|
|
10
|
+
import { useIntentDispatcher } from '@dxos/app-framework/react';
|
|
16
11
|
import { debounceAndThrottle } from '@dxos/async';
|
|
12
|
+
import { Obj } from '@dxos/echo';
|
|
17
13
|
import { invariant } from '@dxos/invariant';
|
|
18
|
-
import { createDocAccessor
|
|
14
|
+
import { createDocAccessor } from '@dxos/react-client/echo';
|
|
15
|
+
import { getSpace } from '@dxos/react-client/echo';
|
|
19
16
|
import { useIdentity } from '@dxos/react-client/halo';
|
|
20
17
|
import { Icon, ThemeProvider } from '@dxos/react-ui';
|
|
21
18
|
import { type SelectionManager } from '@dxos/react-ui-attention';
|
|
@@ -36,23 +33,24 @@ import {
|
|
|
36
33
|
linkTooltip,
|
|
37
34
|
listener,
|
|
38
35
|
preview,
|
|
36
|
+
replacer,
|
|
39
37
|
selectionState,
|
|
40
38
|
typewriter,
|
|
41
39
|
} from '@dxos/react-ui-editor';
|
|
42
40
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
41
|
+
import { Text } from '@dxos/schema';
|
|
42
|
+
import { isTruthy } from '@dxos/util';
|
|
43
|
+
|
|
44
|
+
import { Markdown } from '../types';
|
|
45
|
+
import { setFallbackName } from '../util';
|
|
45
46
|
|
|
46
|
-
|
|
47
|
-
import { type Markdown } from './types';
|
|
48
|
-
import { setFallbackName } from './util';
|
|
47
|
+
export type DocumentType = Markdown.Document | Text.Text | { id: string; text: string };
|
|
49
48
|
|
|
50
|
-
type ExtensionsOptions = {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
text?: DataType.Text;
|
|
49
|
+
export type ExtensionsOptions = {
|
|
50
|
+
id: string;
|
|
51
|
+
object?: DocumentType;
|
|
54
52
|
dispatch?: PromiseIntentDispatcher;
|
|
55
|
-
settings
|
|
53
|
+
settings?: Markdown.Settings;
|
|
56
54
|
selectionManager?: SelectionManager;
|
|
57
55
|
viewMode?: EditorViewMode;
|
|
58
56
|
editorStateStore?: EditorStateStore;
|
|
@@ -61,9 +59,8 @@ type ExtensionsOptions = {
|
|
|
61
59
|
|
|
62
60
|
// TODO(burdon): Merge with createBaseExtensions below.
|
|
63
61
|
export const useExtensions = ({
|
|
64
|
-
document,
|
|
65
62
|
id,
|
|
66
|
-
|
|
63
|
+
object,
|
|
67
64
|
settings,
|
|
68
65
|
selectionManager,
|
|
69
66
|
viewMode,
|
|
@@ -72,93 +69,72 @@ export const useExtensions = ({
|
|
|
72
69
|
}: ExtensionsOptions): Extension[] => {
|
|
73
70
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
74
71
|
const identity = useIdentity();
|
|
75
|
-
const space = getSpace(
|
|
72
|
+
const space = getSpace(object);
|
|
73
|
+
|
|
74
|
+
let target: Obj.Any | undefined;
|
|
75
|
+
if (Obj.instanceOf(Markdown.Document, object)) {
|
|
76
|
+
target = (object as Markdown.Document).content.target;
|
|
77
|
+
} else if (Obj.instanceOf(Text.Text, object)) {
|
|
78
|
+
target = object;
|
|
79
|
+
}
|
|
76
80
|
|
|
77
81
|
// TODO(wittjosiah): Autocomplete is not working and this query is causing performance issues.
|
|
78
82
|
// TODO(burdon): Unsubscribe.
|
|
79
83
|
// const query = space?.db.query(Filter.type(DocumentType));
|
|
80
84
|
// query?.subscribe();
|
|
85
|
+
|
|
81
86
|
const baseExtensions = useMemo(
|
|
82
87
|
() =>
|
|
83
88
|
createBaseExtensions({
|
|
84
|
-
document,
|
|
85
89
|
id,
|
|
86
|
-
|
|
90
|
+
object,
|
|
87
91
|
settings,
|
|
88
92
|
selectionManager,
|
|
89
93
|
viewMode,
|
|
90
94
|
previewOptions,
|
|
91
95
|
dispatch,
|
|
92
|
-
// query,
|
|
93
96
|
}),
|
|
94
97
|
[
|
|
95
|
-
document,
|
|
96
98
|
id,
|
|
97
|
-
|
|
99
|
+
object,
|
|
98
100
|
viewMode,
|
|
99
101
|
dispatch,
|
|
100
102
|
previewOptions,
|
|
101
103
|
settings,
|
|
102
|
-
settings
|
|
103
|
-
settings
|
|
104
|
-
settings
|
|
105
|
-
settings
|
|
106
|
-
settings
|
|
104
|
+
settings?.debug,
|
|
105
|
+
settings?.editorInputMode,
|
|
106
|
+
settings?.folding,
|
|
107
|
+
settings?.numberedHeadings,
|
|
108
|
+
settings?.typewriter,
|
|
107
109
|
selectionManager,
|
|
108
110
|
],
|
|
109
111
|
);
|
|
110
112
|
|
|
111
|
-
const extensionProviders = useCapabilities(MarkdownCapabilities.Extensions);
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
// External extensions from other plugins.
|
|
115
|
-
//
|
|
116
|
-
const pluginExtensions = useMemo<Extension[]>(() => {
|
|
117
|
-
if (!document) {
|
|
118
|
-
return [];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return extensionProviders.flat().reduce((acc: Extension[], provider) => {
|
|
122
|
-
const extension = typeof provider === 'function' ? provider({ document }) : provider;
|
|
123
|
-
if (extension) {
|
|
124
|
-
acc.push(extension);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return acc;
|
|
128
|
-
}, []);
|
|
129
|
-
}, [extensionProviders, document]);
|
|
130
|
-
|
|
131
|
-
//
|
|
132
|
-
// Basic plugins.
|
|
133
|
-
//
|
|
134
113
|
return useMemo<Extension[]>(
|
|
135
114
|
() =>
|
|
136
115
|
[
|
|
116
|
+
// TODO(burdon): Pass this in?
|
|
137
117
|
// NOTE: Data extensions must be first so that automerge is updated before other extensions compute their state.
|
|
138
|
-
|
|
139
|
-
createDataExtensions({
|
|
140
|
-
id: document.id,
|
|
141
|
-
text: document.content.target && createDocAccessor(document.content.target, ['content']),
|
|
142
|
-
space,
|
|
143
|
-
identity,
|
|
144
|
-
}),
|
|
145
|
-
text &&
|
|
146
|
-
id &&
|
|
118
|
+
target &&
|
|
147
119
|
createDataExtensions({
|
|
148
120
|
id,
|
|
149
|
-
text: createDocAccessor(
|
|
121
|
+
text: createDocAccessor(target, ['content']),
|
|
150
122
|
space,
|
|
151
123
|
identity,
|
|
152
124
|
}),
|
|
153
|
-
|
|
154
|
-
|
|
125
|
+
|
|
126
|
+
// TODO(burdon): Reconcile with effect in parent.
|
|
127
|
+
Obj.instanceOf(Markdown.Document, object) &&
|
|
155
128
|
listener({
|
|
156
|
-
onChange: (text) =>
|
|
129
|
+
onChange: ({ text }) => {
|
|
130
|
+
setFallbackName(object as Markdown.Document, text);
|
|
131
|
+
},
|
|
157
132
|
}),
|
|
133
|
+
|
|
158
134
|
baseExtensions,
|
|
159
|
-
|
|
160
|
-
].filter(
|
|
161
|
-
[
|
|
135
|
+
selectionState(editorStateStore),
|
|
136
|
+
].filter(isTruthy),
|
|
137
|
+
[identity, space, id, object, target, baseExtensions],
|
|
162
138
|
);
|
|
163
139
|
};
|
|
164
140
|
|
|
@@ -166,8 +142,8 @@ export const useExtensions = ({
|
|
|
166
142
|
* Create extension instances for editor.
|
|
167
143
|
*/
|
|
168
144
|
const createBaseExtensions = ({
|
|
169
|
-
document,
|
|
170
145
|
id,
|
|
146
|
+
object,
|
|
171
147
|
dispatch,
|
|
172
148
|
settings,
|
|
173
149
|
selectionManager,
|
|
@@ -176,9 +152,9 @@ const createBaseExtensions = ({
|
|
|
176
152
|
}: ExtensionsOptions): Extension[] => {
|
|
177
153
|
const extensions: Extension[] = [
|
|
178
154
|
selectionManager && selectionChange(selectionManager),
|
|
179
|
-
settings
|
|
180
|
-
settings
|
|
181
|
-
].filter(
|
|
155
|
+
settings?.editorInputMode && InputModeExtensions[settings.editorInputMode],
|
|
156
|
+
settings?.folding && folding(),
|
|
157
|
+
].filter(isTruthy);
|
|
182
158
|
|
|
183
159
|
//
|
|
184
160
|
// Markdown
|
|
@@ -189,17 +165,18 @@ const createBaseExtensions = ({
|
|
|
189
165
|
formattingKeymap(),
|
|
190
166
|
decorateMarkdown({
|
|
191
167
|
selectionChangeDelay: 100,
|
|
192
|
-
numberedHeadings: settings
|
|
168
|
+
numberedHeadings: settings?.numberedHeadings ? { from: 2 } : undefined,
|
|
193
169
|
// TODO(wittjosiah): For internal links, consider ignoring the link text and rendering the label of the object being linked to.
|
|
170
|
+
// TODO(burdon): Create dx-tag.
|
|
194
171
|
renderLinkButton:
|
|
195
|
-
dispatch && (
|
|
172
|
+
dispatch && (object || id)
|
|
196
173
|
? createLinkRenderer((id: string) => {
|
|
197
174
|
void dispatch(
|
|
198
175
|
createIntent(LayoutAction.Open, {
|
|
199
176
|
part: 'main',
|
|
200
177
|
subject: [id],
|
|
201
178
|
options: {
|
|
202
|
-
pivotId:
|
|
179
|
+
pivotId: object && Obj.isObject(object) ? Obj.getDXN(object).toString() : id,
|
|
203
180
|
},
|
|
204
181
|
}),
|
|
205
182
|
);
|
|
@@ -208,11 +185,12 @@ const createBaseExtensions = ({
|
|
|
208
185
|
}),
|
|
209
186
|
linkTooltip(renderLinkTooltip),
|
|
210
187
|
preview(previewOptions),
|
|
188
|
+
replacer(),
|
|
211
189
|
],
|
|
212
190
|
);
|
|
213
191
|
}
|
|
214
192
|
|
|
215
|
-
if (settings
|
|
193
|
+
if (settings?.debug) {
|
|
216
194
|
const items = settings.typewriter?.split(/[,\n]/) ?? '';
|
|
217
195
|
if (items) {
|
|
218
196
|
extensions.push(typewriter({ items }));
|
|
@@ -222,7 +200,7 @@ const createBaseExtensions = ({
|
|
|
222
200
|
return extensions;
|
|
223
201
|
};
|
|
224
202
|
|
|
225
|
-
|
|
203
|
+
const selectionChange = (selectionManager: SelectionManager) => {
|
|
226
204
|
return EditorView.updateListener.of(
|
|
227
205
|
debounceAndThrottle((update: ViewUpdate) => {
|
|
228
206
|
if (update.selectionSet) {
|
|
@@ -235,6 +213,7 @@ export const selectionChange = (selectionManager: SelectionManager) => {
|
|
|
235
213
|
to: cursorConverter.toCursor(range.to),
|
|
236
214
|
}))
|
|
237
215
|
.filter(({ from, to }) => to > from);
|
|
216
|
+
|
|
238
217
|
selectionManager.updateMultiRange(id, ranges);
|
|
239
218
|
}
|
|
240
219
|
}, 100),
|
|
@@ -293,8 +272,8 @@ const renderLinkTooltip: RenderCallback<{ url: string }> = (el, { url }) => {
|
|
|
293
272
|
);
|
|
294
273
|
};
|
|
295
274
|
|
|
296
|
-
// TODO(burdon):
|
|
297
|
-
|
|
275
|
+
// TODO(burdon): REMOVE.
|
|
276
|
+
const renderRoot = <T extends Element>(root: T, node: ReactNode): T => {
|
|
298
277
|
createRoot(root).render(<ThemeProvider tx={defaultTx}>{node}</ThemeProvider>);
|
|
299
278
|
return root;
|
|
300
279
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { useCallback, useMemo } from 'react';
|
|
6
|
+
|
|
7
|
+
import { Capabilities } from '@dxos/app-framework';
|
|
8
|
+
import { useCapabilities, usePluginManager } from '@dxos/app-framework/react';
|
|
9
|
+
import { Filter, Obj, Query, Type } from '@dxos/echo';
|
|
10
|
+
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
11
|
+
import { SpaceCapabilities } from '@dxos/plugin-space';
|
|
12
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
13
|
+
import { toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
14
|
+
import { type EditorMenuGroup, type EditorMenuItem, insertAtCursor, insertAtLineStart } from '@dxos/react-ui-editor';
|
|
15
|
+
|
|
16
|
+
export const useLinkQuery = (space: Space | undefined) => {
|
|
17
|
+
const { t } = useTranslation();
|
|
18
|
+
|
|
19
|
+
const manager = usePluginManager();
|
|
20
|
+
const resolve = useCallback(
|
|
21
|
+
(typename: string) =>
|
|
22
|
+
manager.context.getCapabilities(Capabilities.Metadata).find(({ id }) => id === typename)?.metadata ?? {},
|
|
23
|
+
[manager],
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const objectForms = useCapabilities(SpaceCapabilities.ObjectForm);
|
|
27
|
+
const schemaWhiteList = useCapabilities(ClientCapabilities.SchemaWhiteList);
|
|
28
|
+
const filter = useMemo(
|
|
29
|
+
() =>
|
|
30
|
+
Filter.or(
|
|
31
|
+
...objectForms.map((form) => Filter.type(form.objectSchema)),
|
|
32
|
+
...schemaWhiteList.flat().map((schema) => Filter.typename(Type.getTypename(schema))),
|
|
33
|
+
),
|
|
34
|
+
[objectForms, schemaWhiteList],
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const handleLinkQuery = useCallback(
|
|
38
|
+
async (query?: string): Promise<EditorMenuGroup[]> => {
|
|
39
|
+
const name = query?.startsWith('@') ? query.slice(1).toLowerCase() : (query?.toLowerCase() ?? '');
|
|
40
|
+
const results = await space?.db.query(Query.select(filter)).run();
|
|
41
|
+
|
|
42
|
+
// TODO(wittjosiah): Use `Obj.Any` type.
|
|
43
|
+
const getLabel = (object: any) => {
|
|
44
|
+
const label = Obj.getLabel(object);
|
|
45
|
+
if (label) {
|
|
46
|
+
return label;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// TODO(wittjosiah): Remove metadata labels.
|
|
50
|
+
const type = Obj.getTypename(object)!;
|
|
51
|
+
const metadata = resolve(type);
|
|
52
|
+
return metadata.label?.(object) || ['object name placeholder', { ns: type, default: 'New object' }];
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const items =
|
|
56
|
+
results?.objects
|
|
57
|
+
.filter((object) => toLocalizedString(getLabel(object), t).toLowerCase().includes(name))
|
|
58
|
+
// TODO(wittjosiah): Remove `any` type.
|
|
59
|
+
.map((object: any): EditorMenuItem => {
|
|
60
|
+
const metadata = resolve(Obj.getTypename(object)!);
|
|
61
|
+
const label = toLocalizedString(getLabel(object), t);
|
|
62
|
+
return {
|
|
63
|
+
id: object.id,
|
|
64
|
+
label,
|
|
65
|
+
icon: metadata.icon,
|
|
66
|
+
onSelect: ({ view, head }) => {
|
|
67
|
+
const link = `[${label}](${Obj.getDXN(object)})`;
|
|
68
|
+
if (query?.startsWith('@')) {
|
|
69
|
+
insertAtLineStart(view, head, `!${link}\n`);
|
|
70
|
+
} else {
|
|
71
|
+
insertAtCursor(view, head, `${link} `);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}) ?? [];
|
|
76
|
+
|
|
77
|
+
return [{ id: 'echo', items }];
|
|
78
|
+
},
|
|
79
|
+
[space, filter, resolve],
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
return handleLinkQuery;
|
|
83
|
+
};
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { EditorView } from '@codemirror/view';
|
|
6
|
-
import
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
7
|
import { useMemo } from 'react';
|
|
8
8
|
|
|
9
|
-
import { LayoutAction, createResolver
|
|
9
|
+
import { LayoutAction, createResolver } from '@dxos/app-framework';
|
|
10
|
+
import { useIntentResolver } from '@dxos/app-framework/react';
|
|
10
11
|
import { invariant } from '@dxos/invariant';
|
|
11
12
|
import { Cursor, setSelection } from '@dxos/react-ui-editor';
|
|
12
13
|
|
|
@@ -15,13 +16,19 @@ import { meta } from '../meta';
|
|
|
15
16
|
/**
|
|
16
17
|
* Handle scrolling and selection of the current thread in a markdown editor.
|
|
17
18
|
*/
|
|
18
|
-
export const useSelectCurrentThread = (editorView: EditorView |
|
|
19
|
+
export const useSelectCurrentThread = (editorView: EditorView | null, documentId: string) => {
|
|
19
20
|
const scrollIntoViewResolver = useMemo(
|
|
20
21
|
() =>
|
|
21
22
|
createResolver({
|
|
22
23
|
intent: LayoutAction.UpdateLayout,
|
|
23
24
|
position: 'hoist',
|
|
24
|
-
filter: (
|
|
25
|
+
filter: (
|
|
26
|
+
data,
|
|
27
|
+
): data is {
|
|
28
|
+
part: 'current';
|
|
29
|
+
subject: string;
|
|
30
|
+
options: { cursor: string };
|
|
31
|
+
} => {
|
|
25
32
|
if (!Schema.is(LayoutAction.ScrollIntoView.fields.input)(data)) {
|
|
26
33
|
return false;
|
|
27
34
|
}
|
|
@@ -35,7 +42,10 @@ export const useSelectCurrentThread = (editorView: EditorView | undefined, docum
|
|
|
35
42
|
const selection = editorView.state.selection.main.from !== range.from ? { anchor: range.from } : undefined;
|
|
36
43
|
const effects = [
|
|
37
44
|
// NOTE: This does not use the DOM scrollIntoView function.
|
|
38
|
-
EditorView.scrollIntoView(range.from, {
|
|
45
|
+
EditorView.scrollIntoView(range.from, {
|
|
46
|
+
y: 'start',
|
|
47
|
+
yMargin: 96,
|
|
48
|
+
}),
|
|
39
49
|
];
|
|
40
50
|
if (selection) {
|
|
41
51
|
// Update the editor selection to get bi-directional highlighting.
|
package/src/meta.ts
CHANGED
|
@@ -9,11 +9,11 @@ export const meta: PluginMeta = {
|
|
|
9
9
|
id: 'dxos.org/plugin/markdown',
|
|
10
10
|
name: 'Markdown',
|
|
11
11
|
description: trim`
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
You can use documents to extend the memory of your personal agents and add context for automated workflows.
|
|
12
|
+
Full-featured collaborative markdown editor with real-time editing, inline comments, and rich formatting.
|
|
13
|
+
Supports AI-powered editing assistance and seamlessly integrates with other workspace objects.
|
|
15
14
|
`,
|
|
16
15
|
icon: 'ph--text-aa--regular',
|
|
16
|
+
iconHue: 'indigo',
|
|
17
17
|
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-markdown',
|
|
18
18
|
screenshots: ['https://dxos.network/plugin-details-markdown-dark.png'],
|
|
19
19
|
};
|