@dxos/plugin-markdown 0.8.4-main.2c6827d → 0.8.4-main.3c1ae3b

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 (142) hide show
  1. package/dist/lib/browser/MarkdownCard-THZFDOOV.mjs +13 -0
  2. package/dist/lib/browser/MarkdownContainer-VKPSVI5F.mjs +16 -0
  3. package/dist/lib/browser/{anchor-sort-3HGPGCOO.mjs → anchor-sort-3MYLO74J.mjs} +6 -5
  4. package/dist/lib/browser/anchor-sort-3MYLO74J.mjs.map +7 -0
  5. package/dist/lib/browser/{app-graph-serializer-POZN234F.mjs → app-graph-serializer-BZJ4TQOE.mjs} +3 -3
  6. package/dist/lib/browser/{blueprint-definition-GIPKFDY5.mjs → blueprint-definition-R5T6LTPN.mjs} +3 -3
  7. package/dist/lib/browser/{chunk-K3LXOU3E.mjs → chunk-56SUMOIZ.mjs} +102 -195
  8. package/dist/lib/browser/chunk-56SUMOIZ.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-6OMOMVO7.mjs +107 -0
  10. package/dist/lib/browser/chunk-6OMOMVO7.mjs.map +7 -0
  11. package/dist/lib/browser/{chunk-QYSEJ5GP.mjs → chunk-CN35HEBX.mjs} +6 -6
  12. package/dist/lib/browser/chunk-CN35HEBX.mjs.map +7 -0
  13. package/dist/lib/browser/{chunk-PBJLFIOX.mjs → chunk-KCOBZZIL.mjs} +38 -23
  14. package/dist/lib/browser/chunk-KCOBZZIL.mjs.map +7 -0
  15. package/dist/lib/browser/{chunk-GH6GQSBL.mjs → chunk-KPH4ZPQN.mjs} +53 -5
  16. package/dist/lib/browser/chunk-KPH4ZPQN.mjs.map +7 -0
  17. package/dist/lib/browser/{chunk-22XSSNBS.mjs → chunk-NXT2E2BG.mjs} +4 -3
  18. package/dist/lib/browser/chunk-NXT2E2BG.mjs.map +7 -0
  19. package/dist/lib/browser/{chunk-Y53FQREH.mjs → chunk-RJPOHSYN.mjs} +8 -6
  20. package/dist/lib/browser/chunk-RJPOHSYN.mjs.map +7 -0
  21. package/dist/lib/browser/{chunk-2MLGSYRN.mjs → chunk-U6Y53XZK.mjs} +7 -7
  22. package/dist/lib/browser/index.mjs +10 -24
  23. package/dist/lib/browser/index.mjs.map +3 -3
  24. package/dist/lib/browser/{intent-resolver-Z5L7TXUK.mjs → intent-resolver-55ASQRIW.mjs} +3 -3
  25. package/dist/lib/browser/{intent-resolver-Z5L7TXUK.mjs.map → intent-resolver-55ASQRIW.mjs.map} +1 -1
  26. package/dist/lib/browser/meta.json +1 -1
  27. package/dist/lib/browser/{react-surface-GO5ZOKNN.mjs → react-surface-Q3C5H2KT.mjs} +21 -17
  28. package/dist/lib/browser/react-surface-Q3C5H2KT.mjs.map +7 -0
  29. package/dist/lib/browser/{settings-TZUDB5EW.mjs → settings-G3ZOXJQY.mjs} +2 -2
  30. package/dist/lib/browser/toolkit.mjs +2 -2
  31. package/dist/lib/browser/types/index.mjs +1 -1
  32. package/dist/lib/node-esm/{MarkdownCard-ZXPJLUYO.mjs → MarkdownCard-QHSSZGIY.mjs} +5 -4
  33. package/dist/lib/node-esm/{MarkdownContainer-YRDSRDCS.mjs → MarkdownContainer-G3ZQJS7A.mjs} +7 -6
  34. package/dist/lib/node-esm/{anchor-sort-PCDXEBJ2.mjs → anchor-sort-W4HCTYUQ.mjs} +6 -5
  35. package/dist/lib/node-esm/anchor-sort-W4HCTYUQ.mjs.map +7 -0
  36. package/dist/lib/node-esm/{app-graph-serializer-NF65JYAS.mjs → app-graph-serializer-OCTHXWLF.mjs} +3 -3
  37. package/dist/lib/node-esm/{blueprint-definition-ENKJZYQS.mjs → blueprint-definition-2JV3WV22.mjs} +3 -3
  38. package/dist/lib/node-esm/{chunk-PLZ7EVCT.mjs → chunk-6F6FCTIA.mjs} +53 -5
  39. package/dist/lib/node-esm/chunk-6F6FCTIA.mjs.map +7 -0
  40. package/dist/lib/node-esm/{chunk-HAIEWPU7.mjs → chunk-C5KXP2ZE.mjs} +8 -6
  41. package/dist/lib/node-esm/chunk-C5KXP2ZE.mjs.map +7 -0
  42. package/dist/lib/node-esm/{chunk-CT7CFX5G.mjs → chunk-FR6RW6DH.mjs} +102 -195
  43. package/dist/lib/node-esm/chunk-FR6RW6DH.mjs.map +7 -0
  44. package/dist/lib/node-esm/{chunk-AMHACOXW.mjs → chunk-I5JSQBPI.mjs} +4 -3
  45. package/dist/lib/node-esm/chunk-I5JSQBPI.mjs.map +7 -0
  46. package/dist/lib/node-esm/{chunk-KCHUTL3Q.mjs → chunk-KM7KYV6W.mjs} +7 -7
  47. package/dist/lib/node-esm/chunk-KYWXTMKI.mjs +108 -0
  48. package/dist/lib/node-esm/chunk-KYWXTMKI.mjs.map +7 -0
  49. package/dist/lib/node-esm/{chunk-PIOOG7A5.mjs → chunk-R3SGV4ES.mjs} +38 -23
  50. package/dist/lib/node-esm/chunk-R3SGV4ES.mjs.map +7 -0
  51. package/dist/lib/node-esm/{chunk-NGYJNQ6A.mjs → chunk-YFRTKXTB.mjs} +6 -6
  52. package/dist/lib/node-esm/chunk-YFRTKXTB.mjs.map +7 -0
  53. package/dist/lib/node-esm/index.mjs +10 -24
  54. package/dist/lib/node-esm/index.mjs.map +3 -3
  55. package/dist/lib/node-esm/{intent-resolver-6B3PFQ5F.mjs → intent-resolver-DTBVWCNO.mjs} +3 -3
  56. package/dist/lib/node-esm/{intent-resolver-6B3PFQ5F.mjs.map → intent-resolver-DTBVWCNO.mjs.map} +1 -1
  57. package/dist/lib/node-esm/meta.json +1 -1
  58. package/dist/lib/node-esm/{react-surface-I46BPCWT.mjs → react-surface-QWRT4SD6.mjs} +21 -17
  59. package/dist/lib/node-esm/react-surface-QWRT4SD6.mjs.map +7 -0
  60. package/dist/lib/node-esm/{settings-CJ3T5EX4.mjs → settings-IBFFCGNL.mjs} +2 -2
  61. package/dist/lib/node-esm/toolkit.mjs +2 -2
  62. package/dist/lib/node-esm/types/index.mjs +1 -1
  63. package/dist/types/src/MarkdownPlugin.d.ts.map +1 -1
  64. package/dist/types/src/capabilities/anchor-sort.d.ts.map +1 -1
  65. package/dist/types/src/components/MarkdownCard/MarkdownCard.d.ts +14 -1
  66. package/dist/types/src/components/MarkdownCard/MarkdownCard.d.ts.map +1 -1
  67. package/dist/types/src/components/MarkdownContainer.d.ts +6 -1
  68. package/dist/types/src/components/MarkdownContainer.d.ts.map +1 -1
  69. package/dist/types/src/components/MarkdownContainer.stories.d.ts +1 -0
  70. package/dist/types/src/components/MarkdownContainer.stories.d.ts.map +1 -1
  71. package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts +8 -5
  72. package/dist/types/src/components/MarkdownEditor/MarkdownEditorContent.d.ts.map +1 -1
  73. package/dist/types/src/components/Suggestions.stories.d.ts.map +1 -1
  74. package/dist/types/src/components/index.d.ts +5 -2
  75. package/dist/types/src/components/index.d.ts.map +1 -1
  76. package/dist/types/src/functions/open.d.ts.map +1 -1
  77. package/dist/types/src/functions/update.d.ts.map +1 -1
  78. package/dist/types/src/testing.d.ts +2 -2
  79. package/dist/types/src/testing.d.ts.map +1 -1
  80. package/dist/types/src/translations.d.ts +1 -0
  81. package/dist/types/src/translations.d.ts.map +1 -1
  82. package/dist/types/src/types/Markdown.d.ts +6 -6
  83. package/dist/types/src/types/Markdown.d.ts.map +1 -1
  84. package/dist/types/src/types/MarkdownAction.d.ts +3 -3
  85. package/dist/types/src/util.d.ts +3 -0
  86. package/dist/types/src/util.d.ts.map +1 -1
  87. package/dist/types/src/util.test.d.ts +2 -0
  88. package/dist/types/src/util.test.d.ts.map +1 -0
  89. package/dist/types/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +44 -44
  91. package/src/MarkdownPlugin.tsx +5 -21
  92. package/src/capabilities/anchor-sort.ts +4 -3
  93. package/src/capabilities/artifact-definition.ts +1 -1
  94. package/src/capabilities/intent-resolver.ts +1 -1
  95. package/src/capabilities/react-surface.tsx +32 -28
  96. package/src/components/MarkdownCard/MarkdownCard.tsx +39 -32
  97. package/src/components/MarkdownContainer.tsx +68 -73
  98. package/src/components/MarkdownEditor/MarkdownEditor.tsx +5 -5
  99. package/src/components/MarkdownEditor/MarkdownEditorContent.tsx +24 -8
  100. package/src/components/Suggestions.stories.tsx +2 -1
  101. package/src/components/index.ts +8 -3
  102. package/src/functions/create.test.ts +14 -18
  103. package/src/functions/open.ts +3 -2
  104. package/src/functions/update.test.ts +17 -21
  105. package/src/functions/update.ts +3 -2
  106. package/src/hooks/useExtensions.tsx +2 -2
  107. package/src/hooks/useLinkQuery.ts +10 -10
  108. package/src/testing.ts +5 -5
  109. package/src/translations.ts +1 -0
  110. package/src/types/Markdown.ts +4 -5
  111. package/src/util.test.ts +44 -0
  112. package/src/util.tsx +72 -4
  113. package/dist/lib/browser/MarkdownCard-JYMDPKV5.mjs +0 -12
  114. package/dist/lib/browser/MarkdownContainer-Y75XSVBX.mjs +0 -15
  115. package/dist/lib/browser/anchor-sort-3HGPGCOO.mjs.map +0 -7
  116. package/dist/lib/browser/chunk-22XSSNBS.mjs.map +0 -7
  117. package/dist/lib/browser/chunk-GH6GQSBL.mjs.map +0 -7
  118. package/dist/lib/browser/chunk-K3LXOU3E.mjs.map +0 -7
  119. package/dist/lib/browser/chunk-PBJLFIOX.mjs.map +0 -7
  120. package/dist/lib/browser/chunk-QYSEJ5GP.mjs.map +0 -7
  121. package/dist/lib/browser/chunk-Y53FQREH.mjs.map +0 -7
  122. package/dist/lib/browser/react-surface-GO5ZOKNN.mjs.map +0 -7
  123. package/dist/lib/node-esm/anchor-sort-PCDXEBJ2.mjs.map +0 -7
  124. package/dist/lib/node-esm/chunk-AMHACOXW.mjs.map +0 -7
  125. package/dist/lib/node-esm/chunk-CT7CFX5G.mjs.map +0 -7
  126. package/dist/lib/node-esm/chunk-HAIEWPU7.mjs.map +0 -7
  127. package/dist/lib/node-esm/chunk-NGYJNQ6A.mjs.map +0 -7
  128. package/dist/lib/node-esm/chunk-PIOOG7A5.mjs.map +0 -7
  129. package/dist/lib/node-esm/chunk-PLZ7EVCT.mjs.map +0 -7
  130. package/dist/lib/node-esm/react-surface-I46BPCWT.mjs.map +0 -7
  131. /package/dist/lib/browser/{MarkdownCard-JYMDPKV5.mjs.map → MarkdownCard-THZFDOOV.mjs.map} +0 -0
  132. /package/dist/lib/browser/{MarkdownContainer-Y75XSVBX.mjs.map → MarkdownContainer-VKPSVI5F.mjs.map} +0 -0
  133. /package/dist/lib/browser/{app-graph-serializer-POZN234F.mjs.map → app-graph-serializer-BZJ4TQOE.mjs.map} +0 -0
  134. /package/dist/lib/browser/{blueprint-definition-GIPKFDY5.mjs.map → blueprint-definition-R5T6LTPN.mjs.map} +0 -0
  135. /package/dist/lib/browser/{chunk-2MLGSYRN.mjs.map → chunk-U6Y53XZK.mjs.map} +0 -0
  136. /package/dist/lib/browser/{settings-TZUDB5EW.mjs.map → settings-G3ZOXJQY.mjs.map} +0 -0
  137. /package/dist/lib/node-esm/{MarkdownCard-ZXPJLUYO.mjs.map → MarkdownCard-QHSSZGIY.mjs.map} +0 -0
  138. /package/dist/lib/node-esm/{MarkdownContainer-YRDSRDCS.mjs.map → MarkdownContainer-G3ZQJS7A.mjs.map} +0 -0
  139. /package/dist/lib/node-esm/{app-graph-serializer-NF65JYAS.mjs.map → app-graph-serializer-OCTHXWLF.mjs.map} +0 -0
  140. /package/dist/lib/node-esm/{blueprint-definition-ENKJZYQS.mjs.map → blueprint-definition-2JV3WV22.mjs.map} +0 -0
  141. /package/dist/lib/node-esm/{chunk-KCHUTL3Q.mjs.map → chunk-KM7KYV6W.mjs.map} +0 -0
  142. /package/dist/lib/node-esm/{settings-CJ3T5EX4.mjs.map → settings-IBFFCGNL.mjs.map} +0 -0
@@ -6,25 +6,26 @@ import { type EditorView } from '@codemirror/view';
6
6
  import React, { forwardRef, useEffect, useImperativeHandle, useMemo } from 'react';
7
7
 
8
8
  import { type Live } from '@dxos/live-object';
9
- import { useDynamicRef, useThemeContext, useTranslation } from '@dxos/react-ui';
9
+ import { type ThemedClassName, useDynamicRef, useThemeContext, useTranslation } from '@dxos/react-ui';
10
10
  import {
11
11
  type EditorMenuGroup,
12
12
  type EditorSelectionState,
13
13
  type EditorStateStore,
14
14
  type EditorToolbarState,
15
15
  type EditorViewMode,
16
+ type ThemeExtensionsOptions,
16
17
  type UseTextEditorProps,
17
18
  createBasicExtensions,
18
19
  createMarkdownExtensions,
19
20
  createThemeExtensions,
20
21
  dropFile,
21
- editorGutter,
22
22
  editorSlots,
23
23
  formattingListener,
24
24
  processEditorPayload,
25
25
  stackItemContentEditorClassNames,
26
26
  useTextEditor,
27
27
  } from '@dxos/react-ui-editor';
28
+ import { mx } from '@dxos/react-ui-theme';
28
29
  import { isTruthy } from '@dxos/util';
29
30
 
30
31
  import { useSelectCurrentThread } from '../../hooks';
@@ -32,7 +33,7 @@ import { meta } from '../../meta';
32
33
 
33
34
  import { type MarkdownEditorToolbarProps } from './MarkdownEditorToolbar';
34
35
 
35
- export type MarkdownEditorContentProps = {
36
+ export type MarkdownEditorContentProps = ThemedClassName<{
36
37
  id: string;
37
38
  role?: string;
38
39
  viewMode?: EditorViewMode;
@@ -41,11 +42,27 @@ export type MarkdownEditorContentProps = {
41
42
  editorStateStore?: EditorStateStore;
42
43
  toolbarState?: Live<EditorToolbarState>;
43
44
  onLinkQuery?: (query?: string) => Promise<EditorMenuGroup[]>;
44
- } & (Pick<UseTextEditorProps, 'initialValue' | 'extensions'> & Pick<MarkdownEditorToolbarProps, 'onFileUpload'>);
45
+ }> &
46
+ // prettier-ignore
47
+ Pick<UseTextEditorProps, 'initialValue' | 'extensions'> &
48
+ Pick<MarkdownEditorToolbarProps, 'onFileUpload'> &
49
+ Pick<ThemeExtensionsOptions, 'slots'>;
45
50
 
46
51
  export const MarkdownEditorContent = forwardRef<EditorView | null, MarkdownEditorContentProps>(
47
52
  (
48
- { id, role, initialValue, editorStateStore, toolbarState, extensions, viewMode, scrollPastEnd, onFileUpload },
53
+ {
54
+ classNames,
55
+ id,
56
+ role,
57
+ viewMode,
58
+ initialValue,
59
+ editorStateStore,
60
+ toolbarState,
61
+ extensions,
62
+ scrollPastEnd,
63
+ slots = editorSlots,
64
+ onFileUpload,
65
+ },
49
66
  forwardedRef,
50
67
  ) => {
51
68
  const { t } = useTranslation(meta.id);
@@ -81,12 +98,11 @@ export const MarkdownEditorContent = forwardRef<EditorView | null, MarkdownEdito
81
98
  }),
82
99
  createThemeExtensions({
83
100
  themeMode,
84
- slots: editorSlots,
101
+ slots,
85
102
  syntaxHighlighting: true,
86
103
  }),
87
104
  createMarkdownExtensions(),
88
105
  formattingListener(() => toolbarStateRef.current),
89
- editorGutter,
90
106
  role !== 'section' &&
91
107
  onFileUpload &&
92
108
  dropFile({
@@ -116,7 +132,7 @@ export const MarkdownEditorContent = forwardRef<EditorView | null, MarkdownEdito
116
132
  role='none'
117
133
  ref={parentRef}
118
134
  data-testid='composer.markdownRoot'
119
- className={stackItemContentEditorClassNames(role)}
135
+ className={mx(stackItemContentEditorClassNames(role), classNames)}
120
136
  data-popover-collision-boundary={true}
121
137
  {...focusAttributes}
122
138
  />
@@ -13,6 +13,7 @@ import { Capabilities, IntentPlugin, SettingsPlugin } from '@dxos/app-framework'
13
13
  import { useCapability, useIntentDispatcher } from '@dxos/app-framework/react';
14
14
  import { withPluginManager } from '@dxos/app-framework/testing';
15
15
  import { Obj, Ref, Type } from '@dxos/echo';
16
+ import { createDocAccessor, toCursorRange } from '@dxos/echo-db';
16
17
  import { invariant } from '@dxos/invariant';
17
18
  import { ClientPlugin } from '@dxos/plugin-client';
18
19
  import { GraphPlugin } from '@dxos/plugin-graph';
@@ -21,7 +22,7 @@ import { SpacePlugin } from '@dxos/plugin-space';
21
22
  import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
22
23
  import { ThemePlugin } from '@dxos/plugin-theme';
23
24
  import { faker } from '@dxos/random';
24
- import { createDocAccessor, toCursorRange, useQueue, useSpace } from '@dxos/react-client/echo';
25
+ import { useQueue, useSpace } from '@dxos/react-client/echo';
25
26
  import { IconButton, Toolbar } from '@dxos/react-ui';
26
27
  import { withTheme } from '@dxos/react-ui/testing';
27
28
  import { type EditorSelection, type Range, useTextEditor } from '@dxos/react-ui-editor';
@@ -2,11 +2,16 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { lazy } from 'react';
5
+ import { type LazyExoticComponent, lazy } from 'react';
6
+
7
+ import { type MarkdownCard as MarkdownCardType } from './MarkdownCard';
8
+ import { type MarkdownContainer as MarkdownContainerType } from './MarkdownContainer';
6
9
 
7
10
  export * from './MarkdownCard';
8
11
  export * from './MarkdownContainer';
9
12
  export * from './MarkdownSettings';
10
13
 
11
- export const MarkdownCard = lazy(() => import('./MarkdownCard'));
12
- export const MarkdownContainer = lazy(() => import('./MarkdownContainer'));
14
+ export const MarkdownCard: LazyExoticComponent<typeof MarkdownCardType> = lazy(() => import('./MarkdownCard'));
15
+ export const MarkdownContainer: LazyExoticComponent<typeof MarkdownContainerType> = lazy(
16
+ () => import('./MarkdownContainer'),
17
+ );
@@ -6,8 +6,8 @@ import { describe, expect, it } from '@effect/vitest';
6
6
  import * as Effect from 'effect/Effect';
7
7
  import * as Layer from 'effect/Layer';
8
8
 
9
- import { AiService, ConsolePrinter, MemoizedAiService } from '@dxos/ai';
10
- import { TestAiService } from '@dxos/ai/testing';
9
+ import { AiService, ConsolePrinter } from '@dxos/ai';
10
+ import { MemoizedAiService, TestAiService } from '@dxos/ai/testing';
11
11
  import {
12
12
  AiConversation,
13
13
  type ContextBinding,
@@ -16,16 +16,12 @@ import {
16
16
  makeToolResolverFromFunctions,
17
17
  } from '@dxos/assistant';
18
18
  import { Blueprint } from '@dxos/blueprints';
19
- import { PropertiesType } from '@dxos/client-protocol';
19
+ import { SpaceProperties } from '@dxos/client-protocol';
20
20
  import { DXN, 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';
21
+ import { Database } from '@dxos/echo';
22
+ import { acquireReleaseResource } from '@dxos/effect';
23
+ import { TestHelpers } from '@dxos/effect/testing';
24
+ import { CredentialsService, FunctionInvocationService, QueueService, TracingService } from '@dxos/functions';
29
25
  import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
30
26
  import { invariant } from '@dxos/invariant';
31
27
  import { ObjectId } from '@dxos/keys';
@@ -54,7 +50,7 @@ const TestLayer = Layer.mergeAll(
54
50
  TestDatabaseLayer({
55
51
  spaceKey: 'fixed',
56
52
  indexing: { vector: true },
57
- types: [PropertiesType, Collection.Collection, Blueprint.Blueprint, Markdown.Document, HasSubject.HasSubject],
53
+ types: [SpaceProperties, Collection.Collection, Blueprint.Blueprint, Markdown.Document, HasSubject.HasSubject],
58
54
  }),
59
55
  CredentialsService.configuredLayer([]),
60
56
  TracingService.layerNoop,
@@ -74,9 +70,9 @@ describe('create', () => {
74
70
  content,
75
71
  });
76
72
 
77
- const doc = yield* DatabaseService.resolve(DXN.parse(result.id), Markdown.Document);
73
+ const doc = yield* Database.Service.resolve(DXN.parse(result.id), Markdown.Document);
78
74
  expect(doc.name).toBe(name);
79
- const text = yield* DatabaseService.load(doc.content);
75
+ const text = yield* Database.Service.load(doc.content);
80
76
  expect(text.content).toBe(content);
81
77
  },
82
78
  WithProperties,
@@ -92,8 +88,8 @@ describe('create', () => {
92
88
  const queue = yield* QueueService.createQueue<Message.Message | ContextBinding>();
93
89
  const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
94
90
 
95
- yield* DatabaseService.flush({ indexes: true });
96
- const markdownBlueprint = yield* DatabaseService.add(Obj.clone(MarkdownBlueprint));
91
+ yield* Database.Service.flush({ indexes: true });
92
+ const markdownBlueprint = yield* Database.Service.add(Obj.clone(MarkdownBlueprint));
97
93
  yield* Effect.promise(() =>
98
94
  conversation.context.bind({
99
95
  blueprints: [Ref.make(markdownBlueprint)],
@@ -106,7 +102,7 @@ describe('create', () => {
106
102
  prompt: `Create a document with a cookie recipe.`,
107
103
  });
108
104
  {
109
- const { objects: docs } = yield* DatabaseService.runQuery(Query.type(Markdown.Document));
105
+ const docs = yield* Database.Service.runQuery(Query.type(Markdown.Document));
110
106
  if (docs.length !== 1) {
111
107
  throw new Error(`Expected 1 document; got ${docs.length}: ${docs.map((_) => _.name)}`);
112
108
  }
@@ -115,7 +111,7 @@ describe('create', () => {
115
111
  invariant(Obj.instanceOf(Markdown.Document, doc));
116
112
  console.log({
117
113
  name: doc.name,
118
- content: yield* DatabaseService.load(doc.content).pipe(Effect.map((_) => _.content)),
114
+ content: yield* Database.Service.load(doc.content).pipe(Effect.map((_) => _.content)),
119
115
  });
120
116
  }
121
117
  },
@@ -6,7 +6,8 @@ import * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
8
  import { ArtifactId } from '@dxos/assistant';
9
- import { DatabaseService, defineFunction } from '@dxos/functions';
9
+ import { Database } from '@dxos/echo';
10
+ import { defineFunction } from '@dxos/functions';
10
11
 
11
12
  import { Markdown } from '../types';
12
13
 
@@ -23,7 +24,7 @@ export default defineFunction({
23
24
  content: Schema.String,
24
25
  }),
25
26
  handler: Effect.fn(function* ({ data: { id } }) {
26
- const object = yield* DatabaseService.resolve(ArtifactId.toDXN(id), Markdown.Document);
27
+ const object = yield* Database.Service.resolve(ArtifactId.toDXN(id), Markdown.Document);
27
28
  const { content } = yield* Effect.promise(() => object.content.load());
28
29
  return {
29
30
  content,
@@ -6,8 +6,8 @@ import { describe, expect, it } from '@effect/vitest';
6
6
  import * as Effect from 'effect/Effect';
7
7
  import * as Layer from 'effect/Layer';
8
8
 
9
- import { AiService, ConsolePrinter, MemoizedAiService } from '@dxos/ai';
10
- import { TestAiService } from '@dxos/ai/testing';
9
+ import { AiService, ConsolePrinter } from '@dxos/ai';
10
+ import { MemoizedAiService, TestAiService } from '@dxos/ai/testing';
11
11
  import {
12
12
  AiConversation,
13
13
  type ContextBinding,
@@ -16,16 +16,12 @@ import {
16
16
  makeToolResolverFromFunctions,
17
17
  } from '@dxos/assistant';
18
18
  import { Blueprint } from '@dxos/blueprints';
19
- import { PropertiesType } from '@dxos/client-protocol';
19
+ import { SpaceProperties } from '@dxos/client-protocol';
20
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';
21
+ import { Database } from '@dxos/echo';
22
+ import { acquireReleaseResource } from '@dxos/effect';
23
+ import { TestHelpers } from '@dxos/effect/testing';
24
+ import { CredentialsService, FunctionInvocationService, QueueService, TracingService } from '@dxos/functions';
29
25
  import { FunctionInvocationServiceLayerTest, TestDatabaseLayer } from '@dxos/functions-runtime/testing';
30
26
  import { invariant } from '@dxos/invariant';
31
27
  import { ObjectId } from '@dxos/keys';
@@ -54,7 +50,7 @@ const TestLayer = Layer.mergeAll(
54
50
  TestDatabaseLayer({
55
51
  spaceKey: 'fixed',
56
52
  indexing: { vector: true },
57
- types: [PropertiesType, Collection.Collection, Blueprint.Blueprint, Markdown.Document, HasSubject.HasSubject],
53
+ types: [SpaceProperties, Collection.Collection, Blueprint.Blueprint, Markdown.Document, HasSubject.HasSubject],
58
54
  }),
59
55
  CredentialsService.configuredLayer([]),
60
56
  TracingService.layerNoop,
@@ -71,16 +67,16 @@ describe('update', () => {
71
67
  name: 'BlueYard',
72
68
  content: 'Founders and portfolio of BlueYard.',
73
69
  });
74
- yield* DatabaseService.add(doc);
70
+ yield* Database.Service.add(doc);
75
71
 
76
72
  yield* FunctionInvocationService.invokeFunction(MarkdownFunction.update, {
77
73
  id: doc.id,
78
74
  diffs: ['- Founders', '+ # Founders'],
79
75
  });
80
76
 
81
- const updatedDoc = yield* DatabaseService.resolve(Obj.getDXN(doc), Markdown.Document);
77
+ const updatedDoc = yield* Database.Service.resolve(Obj.getDXN(doc), Markdown.Document);
82
78
  expect(updatedDoc.name).toBe(doc.name);
83
- const text = yield* DatabaseService.load(updatedDoc.content);
79
+ const text = yield* Database.Service.load(updatedDoc.content);
84
80
  expect(text.content).toBe('# Founders and portfolio of BlueYard.');
85
81
  },
86
82
  WithProperties,
@@ -96,8 +92,8 @@ describe('update', () => {
96
92
  const queue = yield* QueueService.createQueue<Message.Message | ContextBinding>();
97
93
  const conversation = yield* acquireReleaseResource(() => new AiConversation(queue));
98
94
 
99
- yield* DatabaseService.flush({ indexes: true });
100
- const markdownBlueprint = yield* DatabaseService.add(Obj.clone(MarkdownBlueprint));
95
+ yield* Database.Service.flush({ indexes: true });
96
+ const markdownBlueprint = yield* Database.Service.add(Obj.clone(MarkdownBlueprint));
101
97
  yield* Effect.promise(() =>
102
98
  conversation.context.bind({
103
99
  blueprints: [Ref.make(markdownBlueprint)],
@@ -111,7 +107,7 @@ describe('update', () => {
111
107
  prompt: `Create a document with a cookie recipe.`,
112
108
  });
113
109
  {
114
- const { objects: docs } = yield* DatabaseService.runQuery(Query.type(Markdown.Document));
110
+ const docs = yield* Database.Service.runQuery(Query.type(Markdown.Document));
115
111
  if (docs.length !== 1) {
116
112
  throw new Error(`Expected 1 document; got ${docs.length}: ${docs.map((_) => _.name)}`);
117
113
  }
@@ -120,7 +116,7 @@ describe('update', () => {
120
116
  invariant(Obj.instanceOf(Markdown.Document, doc));
121
117
  console.log({
122
118
  name: doc.name,
123
- content: yield* DatabaseService.load(doc.content).pipe(Effect.map((_) => _.content)),
119
+ content: yield* Database.Service.load(doc.content).pipe(Effect.map((_) => _.content)),
124
120
  });
125
121
  }
126
122
 
@@ -129,7 +125,7 @@ describe('update', () => {
129
125
  prompt: 'Add a section with a holiday-themed variation.',
130
126
  });
131
127
  {
132
- const { objects: docs } = yield* DatabaseService.runQuery(Query.type(Markdown.Document));
128
+ const docs = yield* Database.Service.runQuery(Query.type(Markdown.Document));
133
129
  if (docs.length !== 1) {
134
130
  throw new Error(`Expected 1 document; got ${docs.length}: ${docs.map((_) => _.name)}`);
135
131
  }
@@ -138,7 +134,7 @@ describe('update', () => {
138
134
  invariant(Obj.instanceOf(Markdown.Document, doc));
139
135
  console.log({
140
136
  name: doc.name,
141
- content: yield* DatabaseService.load(doc.content).pipe(Effect.map((_) => _.content)),
137
+ content: yield* Database.Service.load(doc.content).pipe(Effect.map((_) => _.content)),
142
138
  });
143
139
  }
144
140
  },
@@ -6,8 +6,9 @@ import * as Effect from 'effect/Effect';
6
6
  import * as Schema from 'effect/Schema';
7
7
 
8
8
  import { ArtifactId, applyDiffs } from '@dxos/assistant';
9
+ import { Database } from '@dxos/echo';
9
10
  import { createDocAccessor } from '@dxos/echo-db';
10
- import { DatabaseService, defineFunction } from '@dxos/functions';
11
+ import { defineFunction } from '@dxos/functions';
11
12
  import { trim } from '@dxos/util';
12
13
 
13
14
  import { Markdown } from '../types';
@@ -29,7 +30,7 @@ export default defineFunction({
29
30
  }),
30
31
  outputSchema: Schema.Void,
31
32
  handler: Effect.fn(function* ({ data: { id, diffs } }) {
32
- const object = yield* DatabaseService.resolve(ArtifactId.toDXN(id), Markdown.Document);
33
+ const object = yield* Database.Service.resolve(ArtifactId.toDXN(id), Markdown.Document);
33
34
  const content = yield* Effect.promise(() => object.content.load());
34
35
  const accessor = createDocAccessor(content, ['content']);
35
36
  applyDiffs(accessor, diffs);
@@ -10,8 +10,8 @@ import { LayoutAction, type PromiseIntentDispatcher, createIntent } from '@dxos/
10
10
  import { useIntentDispatcher } from '@dxos/app-framework/react';
11
11
  import { debounceAndThrottle } from '@dxos/async';
12
12
  import { Obj } from '@dxos/echo';
13
+ import { createDocAccessor } from '@dxos/echo-db';
13
14
  import { invariant } from '@dxos/invariant';
14
- import { createDocAccessor } from '@dxos/react-client/echo';
15
15
  import { getSpace } from '@dxos/react-client/echo';
16
16
  import { useIdentity } from '@dxos/react-client/halo';
17
17
  import { Icon, ThemeProvider } from '@dxos/react-ui';
@@ -119,7 +119,7 @@ export const useExtensions = ({
119
119
  createDataExtensions({
120
120
  id,
121
121
  text: createDocAccessor(target, ['content']),
122
- space,
122
+ messenger: space,
123
123
  identity,
124
124
  }),
125
125
 
@@ -2,13 +2,13 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
+ import * as Option from 'effect/Option';
5
6
  import { useCallback, useMemo } from 'react';
6
7
 
7
8
  import { Capabilities } from '@dxos/app-framework';
8
- import { useCapabilities, usePluginManager } from '@dxos/app-framework/react';
9
+ import { usePluginManager } from '@dxos/app-framework/react';
9
10
  import { Filter, Obj, Query, Type } from '@dxos/echo';
10
- import { ClientCapabilities } from '@dxos/plugin-client';
11
- import { SpaceCapabilities } from '@dxos/plugin-space';
11
+ import { EntityKind, SystemTypeAnnotation, getTypeAnnotation } from '@dxos/echo/internal';
12
12
  import { type Space } from '@dxos/react-client/echo';
13
13
  import { toLocalizedString, useTranslation } from '@dxos/react-ui';
14
14
  import { type EditorMenuGroup, type EditorMenuItem, insertAtCursor, insertAtLineStart } from '@dxos/react-ui-editor';
@@ -23,15 +23,15 @@ export const useLinkQuery = (space: Space | undefined) => {
23
23
  [manager],
24
24
  );
25
25
 
26
- const objectForms = useCapabilities(SpaceCapabilities.ObjectForm);
27
- const schemaWhiteList = useCapabilities(ClientCapabilities.SchemaWhiteList);
28
26
  const filter = useMemo(
29
27
  () =>
30
28
  Filter.or(
31
- ...objectForms.map((form) => Filter.type(form.objectSchema)),
32
- ...schemaWhiteList.flat().map((schema) => Filter.typename(Type.getTypename(schema))),
29
+ ...(space?.db.schemaRegistry.query({ location: ['database', 'runtime'] }).runSync() ?? [])
30
+ .filter((schema) => getTypeAnnotation(schema)?.kind !== EntityKind.Relation)
31
+ .filter((schema) => !SystemTypeAnnotation.get(schema).pipe(Option.getOrElse(() => false)))
32
+ .map((schema) => Filter.typename(Type.getTypename(schema))),
33
33
  ),
34
- [objectForms, schemaWhiteList],
34
+ [space],
35
35
  );
36
36
 
37
37
  const handleLinkQuery = useCallback(
@@ -53,8 +53,8 @@ export const useLinkQuery = (space: Space | undefined) => {
53
53
  };
54
54
 
55
55
  const items =
56
- results?.objects
57
- .filter((object) => toLocalizedString(getLabel(object), t).toLowerCase().includes(name))
56
+ results
57
+ ?.filter((object) => toLocalizedString(getLabel(object), t).toLowerCase().includes(name))
58
58
  // TODO(wittjosiah): Remove `any` type.
59
59
  .map((object: any): EditorMenuItem => {
60
60
  const metadata = resolve(Obj.getTypename(object)!);
package/src/testing.ts CHANGED
@@ -5,18 +5,18 @@
5
5
  import * as Toolkit from '@effect/ai/Toolkit';
6
6
  import * as Effect from 'effect/Effect';
7
7
 
8
- import { PropertiesType } from '@dxos/client-protocol';
8
+ import { SpaceProperties } from '@dxos/client-protocol';
9
9
  import { Obj, Ref } from '@dxos/echo';
10
- import { DatabaseService } from '@dxos/functions';
10
+ import { Database } from '@dxos/echo';
11
11
  import { Collection } from '@dxos/schema';
12
12
 
13
13
  // TODO(wittjosiah): Factor out.
14
- export const WithProperties = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R | DatabaseService> =>
14
+ export const WithProperties = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R | Database.Service> =>
15
15
  Effect.zipRight(
16
16
  Effect.gen(function* () {
17
17
  // TODO(wittjosiah): Remove cast.
18
- yield* DatabaseService.add(
19
- Obj.make(PropertiesType as any, {
18
+ yield* Database.Service.add(
19
+ Obj.make(SpaceProperties, {
20
20
  [Collection.Collection.typename]: Ref.make(Collection.make()),
21
21
  }) as any,
22
22
  );
@@ -18,6 +18,7 @@ export const translations = [
18
18
  'object name placeholder': 'New document',
19
19
  'rename object label': 'Rename document',
20
20
  'delete object label': 'Delete document',
21
+ 'object deleted label': 'Document deleted',
21
22
  },
22
23
  [meta.id]: {
23
24
  'plugin name': 'Editor',
@@ -5,9 +5,9 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
 
7
7
  import { Obj, Ref, Type } from '@dxos/echo';
8
- import { DescriptionAnnotation, FormAnnotation, LabelAnnotation } from '@dxos/echo/internal';
8
+ import { DescriptionAnnotation, FormInputAnnotation, LabelAnnotation } from '@dxos/echo/internal';
9
9
  import { EditorInputMode, EditorViewMode } from '@dxos/react-ui-editor/types';
10
- import { ItemAnnotation, Text } from '@dxos/schema';
10
+ import { Text } from '@dxos/schema';
11
11
 
12
12
  /**
13
13
  * Document Item type.
@@ -15,8 +15,8 @@ import { ItemAnnotation, Text } from '@dxos/schema';
15
15
  export const Document = Schema.Struct({
16
16
  name: Schema.optional(Schema.String),
17
17
  description: Schema.optional(Schema.String),
18
- fallbackName: Schema.String.pipe(FormAnnotation.set(false), Schema.optional),
19
- content: Type.Ref(Text.Text).pipe(FormAnnotation.set(false)),
18
+ fallbackName: Schema.String.pipe(FormInputAnnotation.set(false), Schema.optional),
19
+ content: Type.Ref(Text.Text).pipe(FormInputAnnotation.set(false)),
20
20
  }).pipe(
21
21
  Type.Obj({
22
22
  typename: 'dxos.org/type/Document',
@@ -24,7 +24,6 @@ export const Document = Schema.Struct({
24
24
  }),
25
25
  LabelAnnotation.set(['name', 'fallbackName']),
26
26
  DescriptionAnnotation.set('description'),
27
- ItemAnnotation.set(true),
28
27
  );
29
28
 
30
29
  export type Document = Schema.Schema.Type<typeof Document>;
@@ -0,0 +1,44 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { describe, expect, it } from 'vitest';
6
+
7
+ import { trim } from '@dxos/util';
8
+
9
+ import { getFallbackName } from './util';
10
+
11
+ describe('markdown utils', () => {
12
+ it('getFallbackName', () => {
13
+ const tests = [
14
+ {
15
+ content: '',
16
+ expected: '',
17
+ },
18
+ {
19
+ content: trim`
20
+ ![img](https://dxos.network/dxos-logotype-blue.png)
21
+
22
+ # Welcome to Composer by DXOS
23
+
24
+ ## What is Composer?
25
+ `,
26
+ expected: 'Welcome to Composer by DXOS',
27
+ },
28
+ {
29
+ content: trim`
30
+ ![img](https://dxos.network/dxos-logotype-blue.png)
31
+
32
+ ---
33
+
34
+ This document is about the decetralized platform DXOS.
35
+ `,
36
+ expected: 'This document is about the…',
37
+ },
38
+ ];
39
+
40
+ tests.forEach(({ content, expected }) => {
41
+ expect(getFallbackName(content)).toBe(expected);
42
+ });
43
+ });
44
+ });
package/src/util.tsx CHANGED
@@ -32,17 +32,85 @@ export const isMarkdownProperties = (data: unknown): data is MarkdownProperties
32
32
 
33
33
  const nonTitleChars = /[^\w ]/g;
34
34
 
35
- export const getFallbackName = (content = '') => {
36
- return content.substring(0, 31).split('\n')[0].replaceAll(nonTitleChars, '').trim();
35
+ // Lines matching these patterns are skipped.
36
+ const skipPatterns = [
37
+ /^!\[/, // Image.
38
+ /^---\s*$/, // Horizontal rule.
39
+ /^```/, // Code block fence.
40
+ /^\s*$/, // Empty or whitespace-only.
41
+ ];
42
+
43
+ // Patterns to extract title text (first capture group is used).
44
+ const titlePatterns = [
45
+ /^#{1,6}\s+(.+)/, // Heading.
46
+ ];
47
+
48
+ /**
49
+ * Extracts a fallback name by scanning lines for the first heading or text fragment.
50
+ */
51
+ export const getFallbackName = (content = ''): string => {
52
+ const len = content.length;
53
+
54
+ let i = 0;
55
+ while (i < len) {
56
+ // Find end of line.
57
+ let lineEnd = i;
58
+ while (lineEnd < len && content[lineEnd] !== '\n') {
59
+ lineEnd++;
60
+ }
61
+
62
+ const line = content.slice(i, lineEnd).trim();
63
+ i = lineEnd + 1;
64
+
65
+ // Skip lines matching skip patterns.
66
+ if (skipPatterns.some((pattern) => pattern.test(line))) {
67
+ continue;
68
+ }
69
+
70
+ // Check for title patterns.
71
+ for (const pattern of titlePatterns) {
72
+ const match = pattern.exec(line);
73
+ if (match) {
74
+ const text = match[1].replaceAll(nonTitleChars, '').trim();
75
+ if (text.length > 0) {
76
+ return text;
77
+ }
78
+ }
79
+ }
80
+
81
+ // Use line as plain text fallback.
82
+ const maxLen = 32;
83
+ const text = line.replaceAll(nonTitleChars, '').trim();
84
+ if (text.length > 0) {
85
+ if (text.length > maxLen) {
86
+ const words = text.split(/\s+/);
87
+ let result = '';
88
+ for (const word of words) {
89
+ const next = result.length === 0 ? word : result + ' ' + word;
90
+ if (next.length > maxLen) {
91
+ break;
92
+ }
93
+ result = next;
94
+ }
95
+
96
+ return result + '…';
97
+ }
98
+
99
+ return text;
100
+ }
101
+ }
102
+
103
+ return '';
37
104
  };
38
105
 
106
+ // TODO(burdon): Option to strip Markdown.
39
107
  export const getContentSnippet = (content = '') => {
40
108
  const abstract = content
41
109
  .split('\n')
42
- .filter((line) => !line.startsWith('#'))
110
+ .filter((line) => !line.startsWith('!'))
43
111
  .filter((line) => line.trim() !== '');
44
112
 
45
- return abstract.length > 0 ? abstract[0].replaceAll(nonTitleChars, '').trim() + '...' : '';
113
+ return abstract.slice(0, 3).join('\n') ?? '';
46
114
  };
47
115
 
48
116
  export const setFallbackName = debounce((doc: Markdown.Document, content = '') => {
@@ -1,12 +0,0 @@
1
- import {
2
- MarkdownCard,
3
- MarkdownCard_default
4
- } from "./chunk-PBJLFIOX.mjs";
5
- import "./chunk-GH6GQSBL.mjs";
6
- import "./chunk-QYSEJ5GP.mjs";
7
- import "./chunk-BQTYJOFB.mjs";
8
- export {
9
- MarkdownCard,
10
- MarkdownCard_default as default
11
- };
12
- //# sourceMappingURL=MarkdownCard-JYMDPKV5.mjs.map
@@ -1,15 +0,0 @@
1
- import {
2
- MarkdownContainer,
3
- MarkdownContainer_default
4
- } from "./chunk-K3LXOU3E.mjs";
5
- import "./chunk-2MLGSYRN.mjs";
6
- import "./chunk-Y53FQREH.mjs";
7
- import "./chunk-IBCHVMZW.mjs";
8
- import "./chunk-GH6GQSBL.mjs";
9
- import "./chunk-QYSEJ5GP.mjs";
10
- import "./chunk-BQTYJOFB.mjs";
11
- export {
12
- MarkdownContainer,
13
- MarkdownContainer_default as default
14
- };
15
- //# sourceMappingURL=MarkdownContainer-Y75XSVBX.mjs.map