@portabletext/editor 1.26.3 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/lib/_chunks-cjs/behavior.markdown.cjs +327 -0
- package/lib/_chunks-cjs/behavior.markdown.cjs.map +1 -0
- package/lib/_chunks-cjs/plugin.event-listener.cjs +6827 -0
- package/lib/_chunks-cjs/plugin.event-listener.cjs.map +1 -0
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs +88 -88
- package/lib/_chunks-cjs/selector.is-at-the-start-of-block.cjs.map +1 -1
- package/lib/_chunks-es/behavior.markdown.js +332 -0
- package/lib/_chunks-es/behavior.markdown.js.map +1 -0
- package/lib/_chunks-es/plugin.event-listener.js +6851 -0
- package/lib/_chunks-es/plugin.event-listener.js.map +1 -0
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +88 -88
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
- package/lib/behaviors/index.cjs +2 -325
- package/lib/behaviors/index.cjs.map +1 -1
- package/lib/behaviors/index.d.cts +1 -1
- package/lib/behaviors/index.d.ts +1 -1
- package/lib/behaviors/index.js +2 -326
- package/lib/behaviors/index.js.map +1 -1
- package/lib/index.cjs +261 -6782
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +3509 -2161
- package/lib/index.d.ts +3509 -2161
- package/lib/index.js +223 -6761
- package/lib/index.js.map +1 -1
- package/lib/plugins/index.cjs +29 -0
- package/lib/plugins/index.cjs.map +1 -0
- package/lib/plugins/index.d.cts +19411 -0
- package/lib/plugins/index.d.ts +19411 -0
- package/lib/plugins/index.js +29 -0
- package/lib/plugins/index.js.map +1 -0
- package/lib/selectors/index.cjs +15 -3
- package/lib/selectors/index.cjs.map +1 -1
- package/lib/selectors/index.d.cts +19 -1
- package/lib/selectors/index.d.ts +19 -1
- package/lib/selectors/index.js +17 -4
- package/lib/selectors/index.js.map +1 -1
- package/package.json +14 -8
- package/src/behavior-actions/behavior.action.insert-break.ts +93 -83
- package/src/editor/Editable.tsx +6 -6
- package/src/editor/PortableTextEditor.tsx +288 -1
- package/src/editor/__tests__/PortableTextEditor.test.tsx +0 -1
- package/src/editor/components/DefaultObject.tsx +21 -0
- package/src/editor/components/Element.tsx +5 -5
- package/src/editor/components/Leaf.tsx +1 -6
- package/src/editor/components/Synchronizer.tsx +16 -1
- package/src/editor/create-editor.ts +8 -48
- package/src/editor/editor-machine.ts +118 -131
- package/src/editor/plugins/create-with-event-listeners.ts +19 -38
- package/src/editor/plugins/createWithPatches.ts +1 -1
- package/src/editor/plugins/createWithPortableTextSelections.ts +2 -2
- package/src/editor/sync-machine.ts +3 -5
- package/src/index.ts +5 -11
- package/src/plugins/_exports/index.ts +1 -0
- package/src/plugins/index.ts +3 -0
- package/src/plugins/plugin.editor-ref.tsx +17 -0
- package/src/{editor/editor-event-listener.tsx → plugins/plugin.event-listener.tsx} +7 -6
- package/src/plugins/plugin.markdown.tsx +70 -0
- package/src/selectors/index.ts +4 -2
- package/src/selectors/selector.get-active-annotations.test.ts +122 -0
- package/src/selectors/selector.get-active-annotations.ts +30 -0
- package/src/selectors/selector.get-selection.ts +8 -0
- package/src/selectors/selector.get-value.ts +11 -0
- package/src/type-utils.ts +12 -2
- package/src/editor/nodes/DefaultAnnotation.tsx +0 -20
- package/src/editor/nodes/DefaultObject.tsx +0 -18
package/README.md
CHANGED
|
@@ -36,13 +36,12 @@ yarn add @portabletext/editor
|
|
|
36
36
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Next, in your app or the component you're building, import `EditorProvider`, `
|
|
39
|
+
Next, in your app or the component you're building, import `EditorProvider`, `PortableTextEditable`, `defineSchema`, `EventListenerPlugin`, and the types in the code below.
|
|
40
40
|
|
|
41
41
|
```tsx
|
|
42
42
|
// App.tsx
|
|
43
43
|
import {
|
|
44
44
|
defineSchema,
|
|
45
|
-
EditorEventListener,
|
|
46
45
|
EditorProvider,
|
|
47
46
|
PortableTextEditable,
|
|
48
47
|
} from '@portabletext/editor'
|
|
@@ -51,6 +50,7 @@ import type {
|
|
|
51
50
|
RenderDecoratorFunction,
|
|
52
51
|
RenderStyleFunction,
|
|
53
52
|
} from '@portabletext/editor'
|
|
53
|
+
import {EventListenerPlugin} from '@portabletext/editor/plugins'
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
### Define the Schema
|
|
@@ -104,7 +104,6 @@ Add `useState` from React, then scaffold out a basic application component. For
|
|
|
104
104
|
// app.tsx
|
|
105
105
|
import {
|
|
106
106
|
defineSchema,
|
|
107
|
-
EditorEventListener,
|
|
108
107
|
EditorProvider,
|
|
109
108
|
PortableTextEditable,
|
|
110
109
|
} from '@portabletext/editor'
|
|
@@ -113,6 +112,7 @@ import type {
|
|
|
113
112
|
RenderDecoratorFunction,
|
|
114
113
|
RenderStyleFunction,
|
|
115
114
|
} from '@portabletext/editor'
|
|
115
|
+
import {EventListenerPlugin} from '@portabletext/editor/plugins'
|
|
116
116
|
import {useState} from 'react'
|
|
117
117
|
|
|
118
118
|
const schemaDefinition = defineSchema({
|
|
@@ -133,7 +133,7 @@ function App() {
|
|
|
133
133
|
initialValue: value,
|
|
134
134
|
}}
|
|
135
135
|
>
|
|
136
|
-
<
|
|
136
|
+
<EventListenerPlugin
|
|
137
137
|
on={(event) => {
|
|
138
138
|
if (event.type === 'mutation') {
|
|
139
139
|
setValue(event.value)
|
|
@@ -311,7 +311,7 @@ function App() {
|
|
|
311
311
|
initialValue: value,
|
|
312
312
|
}}
|
|
313
313
|
>
|
|
314
|
-
<
|
|
314
|
+
<EventListenerPlugin
|
|
315
315
|
on={(event) => {
|
|
316
316
|
if (event.type === 'mutation') {
|
|
317
317
|
setValue(event.value)
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var types = require("@sanity/types"), selector_isAtTheStartOfBlock = require("./selector.is-at-the-start-of-block.cjs"), util_isEmptyTextBlock = require("./util.is-empty-text-block.cjs"), selector_getTextBefore = require("./selector.get-text-before.cjs"), behavior_core = require("./behavior.core.cjs");
|
|
3
|
+
function createMarkdownBehaviors(config) {
|
|
4
|
+
const automaticBlockquoteOnSpace = behavior_core.defineBehavior({
|
|
5
|
+
on: "insert.text",
|
|
6
|
+
guard: ({
|
|
7
|
+
context,
|
|
8
|
+
event
|
|
9
|
+
}) => {
|
|
10
|
+
if (event.text !== " ")
|
|
11
|
+
return !1;
|
|
12
|
+
const selectionCollapsed = selector_isAtTheStartOfBlock.isSelectionCollapsed({
|
|
13
|
+
context
|
|
14
|
+
}), focusTextBlock = selector_isAtTheStartOfBlock.getFocusTextBlock({
|
|
15
|
+
context
|
|
16
|
+
}), focusSpan = selector_isAtTheStartOfBlock.getFocusSpan({
|
|
17
|
+
context
|
|
18
|
+
});
|
|
19
|
+
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
20
|
+
return !1;
|
|
21
|
+
const blockOffset = util_isEmptyTextBlock.spanSelectionPointToBlockOffset({
|
|
22
|
+
value: context.value,
|
|
23
|
+
selectionPoint: {
|
|
24
|
+
path: [{
|
|
25
|
+
_key: focusTextBlock.node._key
|
|
26
|
+
}, "children", {
|
|
27
|
+
_key: focusSpan.node._key
|
|
28
|
+
}],
|
|
29
|
+
offset: context.selection?.focus.offset ?? 0
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (!blockOffset)
|
|
33
|
+
return !1;
|
|
34
|
+
const blockText = util_isEmptyTextBlock.getTextBlockText(focusTextBlock.node), caretAtTheEndOfQuote = blockOffset.offset === 1, looksLikeMarkdownQuote = /^>/.test(blockText), blockquoteStyle = config.blockquoteStyle?.(context);
|
|
35
|
+
return caretAtTheEndOfQuote && looksLikeMarkdownQuote && blockquoteStyle !== void 0 ? {
|
|
36
|
+
focusTextBlock,
|
|
37
|
+
style: blockquoteStyle
|
|
38
|
+
} : !1;
|
|
39
|
+
},
|
|
40
|
+
actions: [() => [{
|
|
41
|
+
type: "insert.text",
|
|
42
|
+
text: " "
|
|
43
|
+
}], (_, {
|
|
44
|
+
focusTextBlock,
|
|
45
|
+
style
|
|
46
|
+
}) => [{
|
|
47
|
+
type: "text block.unset",
|
|
48
|
+
props: ["listItem", "level"],
|
|
49
|
+
at: focusTextBlock.path
|
|
50
|
+
}, {
|
|
51
|
+
type: "text block.set",
|
|
52
|
+
style,
|
|
53
|
+
at: focusTextBlock.path
|
|
54
|
+
}, {
|
|
55
|
+
type: "delete.text",
|
|
56
|
+
anchor: {
|
|
57
|
+
path: focusTextBlock.path,
|
|
58
|
+
offset: 0
|
|
59
|
+
},
|
|
60
|
+
focus: {
|
|
61
|
+
path: focusTextBlock.path,
|
|
62
|
+
offset: 2
|
|
63
|
+
}
|
|
64
|
+
}]]
|
|
65
|
+
}), automaticHr = behavior_core.defineBehavior({
|
|
66
|
+
on: "insert.text",
|
|
67
|
+
guard: ({
|
|
68
|
+
context,
|
|
69
|
+
event
|
|
70
|
+
}) => {
|
|
71
|
+
const hrCharacter = event.text === "-" ? "-" : event.text === "*" ? "*" : event.text === "_" ? "_" : void 0;
|
|
72
|
+
if (hrCharacter === void 0)
|
|
73
|
+
return !1;
|
|
74
|
+
const hrObject = config.horizontalRuleObject?.(context), focusBlock = selector_isAtTheStartOfBlock.getFocusTextBlock({
|
|
75
|
+
context
|
|
76
|
+
}), selectionCollapsed = selector_isAtTheStartOfBlock.isSelectionCollapsed({
|
|
77
|
+
context
|
|
78
|
+
});
|
|
79
|
+
if (!hrObject || !focusBlock || !selectionCollapsed)
|
|
80
|
+
return !1;
|
|
81
|
+
const textBefore = selector_getTextBefore.getBlockTextBefore({
|
|
82
|
+
context
|
|
83
|
+
}), hrBlockOffsets = {
|
|
84
|
+
anchor: {
|
|
85
|
+
path: focusBlock.path,
|
|
86
|
+
offset: 0
|
|
87
|
+
},
|
|
88
|
+
focus: {
|
|
89
|
+
path: focusBlock.path,
|
|
90
|
+
offset: 3
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
return textBefore === `${hrCharacter}${hrCharacter}` ? {
|
|
94
|
+
hrObject,
|
|
95
|
+
focusBlock,
|
|
96
|
+
hrCharacter,
|
|
97
|
+
hrBlockOffsets
|
|
98
|
+
} : !1;
|
|
99
|
+
},
|
|
100
|
+
actions: [(_, {
|
|
101
|
+
hrCharacter
|
|
102
|
+
}) => [{
|
|
103
|
+
type: "insert.text",
|
|
104
|
+
text: hrCharacter
|
|
105
|
+
}], (_, {
|
|
106
|
+
hrObject,
|
|
107
|
+
hrBlockOffsets
|
|
108
|
+
}) => [{
|
|
109
|
+
type: "insert.block object",
|
|
110
|
+
placement: "before",
|
|
111
|
+
blockObject: hrObject
|
|
112
|
+
}, {
|
|
113
|
+
type: "delete.text",
|
|
114
|
+
...hrBlockOffsets
|
|
115
|
+
}]]
|
|
116
|
+
}), automaticHrOnPaste = behavior_core.defineBehavior({
|
|
117
|
+
on: "paste",
|
|
118
|
+
guard: ({
|
|
119
|
+
context,
|
|
120
|
+
event
|
|
121
|
+
}) => {
|
|
122
|
+
const text = event.data.getData("text/plain"), hrRegExp = /^(---)$|(___)$|(\*\*\*)$/gm, hrCharacters = text.match(hrRegExp)?.[0], hrObject = config.horizontalRuleObject?.(context), focusBlock = selector_isAtTheStartOfBlock.getFocusBlock({
|
|
123
|
+
context
|
|
124
|
+
});
|
|
125
|
+
return !hrCharacters || !hrObject || !focusBlock ? !1 : {
|
|
126
|
+
hrCharacters,
|
|
127
|
+
hrObject,
|
|
128
|
+
focusBlock
|
|
129
|
+
};
|
|
130
|
+
},
|
|
131
|
+
actions: [(_, {
|
|
132
|
+
hrCharacters
|
|
133
|
+
}) => [{
|
|
134
|
+
type: "insert.text",
|
|
135
|
+
text: hrCharacters
|
|
136
|
+
}], (_, {
|
|
137
|
+
hrObject,
|
|
138
|
+
focusBlock
|
|
139
|
+
}) => types.isPortableTextTextBlock(focusBlock.node) ? [{
|
|
140
|
+
type: "insert.text block",
|
|
141
|
+
textBlock: {
|
|
142
|
+
children: focusBlock.node.children
|
|
143
|
+
},
|
|
144
|
+
placement: "after"
|
|
145
|
+
}, {
|
|
146
|
+
type: "insert.block object",
|
|
147
|
+
blockObject: hrObject,
|
|
148
|
+
placement: "after"
|
|
149
|
+
}, {
|
|
150
|
+
type: "delete.block",
|
|
151
|
+
blockPath: focusBlock.path
|
|
152
|
+
}] : [{
|
|
153
|
+
type: "insert.block object",
|
|
154
|
+
blockObject: hrObject,
|
|
155
|
+
placement: "after"
|
|
156
|
+
}]]
|
|
157
|
+
}), automaticHeadingOnSpace = behavior_core.defineBehavior({
|
|
158
|
+
on: "insert.text",
|
|
159
|
+
guard: ({
|
|
160
|
+
context,
|
|
161
|
+
event
|
|
162
|
+
}) => {
|
|
163
|
+
if (event.text !== " ")
|
|
164
|
+
return !1;
|
|
165
|
+
const selectionCollapsed = selector_isAtTheStartOfBlock.isSelectionCollapsed({
|
|
166
|
+
context
|
|
167
|
+
}), focusTextBlock = selector_isAtTheStartOfBlock.getFocusTextBlock({
|
|
168
|
+
context
|
|
169
|
+
}), focusSpan = selector_isAtTheStartOfBlock.getFocusSpan({
|
|
170
|
+
context
|
|
171
|
+
});
|
|
172
|
+
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
173
|
+
return !1;
|
|
174
|
+
const blockOffset = util_isEmptyTextBlock.spanSelectionPointToBlockOffset({
|
|
175
|
+
value: context.value,
|
|
176
|
+
selectionPoint: {
|
|
177
|
+
path: [{
|
|
178
|
+
_key: focusTextBlock.node._key
|
|
179
|
+
}, "children", {
|
|
180
|
+
_key: focusSpan.node._key
|
|
181
|
+
}],
|
|
182
|
+
offset: context.selection?.focus.offset ?? 0
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
if (!blockOffset)
|
|
186
|
+
return !1;
|
|
187
|
+
const blockText = util_isEmptyTextBlock.getTextBlockText(focusTextBlock.node), markdownHeadingSearch = /^#+/.exec(blockText), level = markdownHeadingSearch ? markdownHeadingSearch[0].length : void 0;
|
|
188
|
+
if (blockOffset.offset !== level)
|
|
189
|
+
return !1;
|
|
190
|
+
const style = level !== void 0 ? config.headingStyle?.({
|
|
191
|
+
schema: context.schema,
|
|
192
|
+
level
|
|
193
|
+
}) : void 0;
|
|
194
|
+
return level !== void 0 && style !== void 0 ? {
|
|
195
|
+
focusTextBlock,
|
|
196
|
+
style,
|
|
197
|
+
level
|
|
198
|
+
} : !1;
|
|
199
|
+
},
|
|
200
|
+
actions: [({
|
|
201
|
+
event
|
|
202
|
+
}) => [event], (_, {
|
|
203
|
+
focusTextBlock,
|
|
204
|
+
style,
|
|
205
|
+
level
|
|
206
|
+
}) => [{
|
|
207
|
+
type: "text block.unset",
|
|
208
|
+
props: ["listItem", "level"],
|
|
209
|
+
at: focusTextBlock.path
|
|
210
|
+
}, {
|
|
211
|
+
type: "text block.set",
|
|
212
|
+
style,
|
|
213
|
+
at: focusTextBlock.path
|
|
214
|
+
}, {
|
|
215
|
+
type: "delete.text",
|
|
216
|
+
anchor: {
|
|
217
|
+
path: focusTextBlock.path,
|
|
218
|
+
offset: 0
|
|
219
|
+
},
|
|
220
|
+
focus: {
|
|
221
|
+
path: focusTextBlock.path,
|
|
222
|
+
offset: level + 1
|
|
223
|
+
}
|
|
224
|
+
}]]
|
|
225
|
+
}), clearStyleOnBackspace = behavior_core.defineBehavior({
|
|
226
|
+
on: "delete.backward",
|
|
227
|
+
guard: ({
|
|
228
|
+
context
|
|
229
|
+
}) => {
|
|
230
|
+
const selectionCollapsed = selector_isAtTheStartOfBlock.isSelectionCollapsed({
|
|
231
|
+
context
|
|
232
|
+
}), focusTextBlock = selector_isAtTheStartOfBlock.getFocusTextBlock({
|
|
233
|
+
context
|
|
234
|
+
}), focusSpan = selector_isAtTheStartOfBlock.getFocusSpan({
|
|
235
|
+
context
|
|
236
|
+
});
|
|
237
|
+
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
238
|
+
return !1;
|
|
239
|
+
const atTheBeginningOfBLock = focusTextBlock.node.children[0]._key === focusSpan.node._key && context.selection?.focus.offset === 0, defaultStyle = config.defaultStyle?.(context);
|
|
240
|
+
return atTheBeginningOfBLock && defaultStyle && focusTextBlock.node.style !== defaultStyle ? {
|
|
241
|
+
defaultStyle,
|
|
242
|
+
focusTextBlock
|
|
243
|
+
} : !1;
|
|
244
|
+
},
|
|
245
|
+
actions: [(_, {
|
|
246
|
+
defaultStyle,
|
|
247
|
+
focusTextBlock
|
|
248
|
+
}) => [{
|
|
249
|
+
type: "text block.set",
|
|
250
|
+
style: defaultStyle,
|
|
251
|
+
at: focusTextBlock.path
|
|
252
|
+
}]]
|
|
253
|
+
}), automaticListOnSpace = behavior_core.defineBehavior({
|
|
254
|
+
on: "insert.text",
|
|
255
|
+
guard: ({
|
|
256
|
+
context,
|
|
257
|
+
event
|
|
258
|
+
}) => {
|
|
259
|
+
if (event.text !== " ")
|
|
260
|
+
return !1;
|
|
261
|
+
const selectionCollapsed = selector_isAtTheStartOfBlock.isSelectionCollapsed({
|
|
262
|
+
context
|
|
263
|
+
}), focusTextBlock = selector_isAtTheStartOfBlock.getFocusTextBlock({
|
|
264
|
+
context
|
|
265
|
+
}), focusSpan = selector_isAtTheStartOfBlock.getFocusSpan({
|
|
266
|
+
context
|
|
267
|
+
});
|
|
268
|
+
if (!selectionCollapsed || !focusTextBlock || !focusSpan)
|
|
269
|
+
return !1;
|
|
270
|
+
const blockOffset = util_isEmptyTextBlock.spanSelectionPointToBlockOffset({
|
|
271
|
+
value: context.value,
|
|
272
|
+
selectionPoint: {
|
|
273
|
+
path: [{
|
|
274
|
+
_key: focusTextBlock.node._key
|
|
275
|
+
}, "children", {
|
|
276
|
+
_key: focusSpan.node._key
|
|
277
|
+
}],
|
|
278
|
+
offset: context.selection?.focus.offset ?? 0
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
if (!blockOffset)
|
|
282
|
+
return !1;
|
|
283
|
+
const blockText = util_isEmptyTextBlock.getTextBlockText(focusTextBlock.node), defaultStyle = config.defaultStyle?.(context), looksLikeUnorderedList = /^(-|\*)/.test(blockText), unorderedListStyle = config.unorderedListStyle?.(context), caretAtTheEndOfUnorderedList = blockOffset.offset === 1;
|
|
284
|
+
if (defaultStyle && caretAtTheEndOfUnorderedList && looksLikeUnorderedList && unorderedListStyle !== void 0)
|
|
285
|
+
return {
|
|
286
|
+
focusTextBlock,
|
|
287
|
+
listItem: unorderedListStyle,
|
|
288
|
+
listItemLength: 1,
|
|
289
|
+
style: defaultStyle
|
|
290
|
+
};
|
|
291
|
+
const looksLikeOrderedList = /^1\./.test(blockText), orderedListStyle = config.orderedListStyle?.(context), caretAtTheEndOfOrderedList = blockOffset.offset === 2;
|
|
292
|
+
return defaultStyle && caretAtTheEndOfOrderedList && looksLikeOrderedList && orderedListStyle !== void 0 ? {
|
|
293
|
+
focusTextBlock,
|
|
294
|
+
listItem: orderedListStyle,
|
|
295
|
+
listItemLength: 2,
|
|
296
|
+
style: defaultStyle
|
|
297
|
+
} : !1;
|
|
298
|
+
},
|
|
299
|
+
actions: [({
|
|
300
|
+
event
|
|
301
|
+
}) => [event], (_, {
|
|
302
|
+
focusTextBlock,
|
|
303
|
+
style,
|
|
304
|
+
listItem,
|
|
305
|
+
listItemLength
|
|
306
|
+
}) => [{
|
|
307
|
+
type: "text block.set",
|
|
308
|
+
listItem,
|
|
309
|
+
level: 1,
|
|
310
|
+
style,
|
|
311
|
+
at: focusTextBlock.path
|
|
312
|
+
}, {
|
|
313
|
+
type: "delete.text",
|
|
314
|
+
anchor: {
|
|
315
|
+
path: focusTextBlock.path,
|
|
316
|
+
offset: 0
|
|
317
|
+
},
|
|
318
|
+
focus: {
|
|
319
|
+
path: focusTextBlock.path,
|
|
320
|
+
offset: listItemLength + 1
|
|
321
|
+
}
|
|
322
|
+
}]]
|
|
323
|
+
});
|
|
324
|
+
return [automaticBlockquoteOnSpace, automaticHeadingOnSpace, automaticHr, automaticHrOnPaste, clearStyleOnBackspace, automaticListOnSpace];
|
|
325
|
+
}
|
|
326
|
+
exports.createMarkdownBehaviors = createMarkdownBehaviors;
|
|
327
|
+
//# sourceMappingURL=behavior.markdown.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"behavior.markdown.cjs","sources":["../../src/behaviors/behavior.markdown.ts"],"sourcesContent":["import {isPortableTextTextBlock} from '@sanity/types'\nimport type {EditorSchema} from '../editor/define-schema'\nimport * as selectors from '../selectors'\nimport {getBlockTextBefore} from '../selectors/selector.get-text-before'\nimport {spanSelectionPointToBlockOffset} from '../utils/util.block-offset'\nimport {getTextBlockText} from '../utils/util.get-text-block-text'\nimport {defineBehavior} from './behavior.types'\n\n/**\n * @beta\n */\nexport type MarkdownBehaviorsConfig = {\n horizontalRuleObject?: (context: {\n schema: EditorSchema\n }) => {name: string; value?: {[prop: string]: unknown}} | undefined\n defaultStyle?: (context: {schema: EditorSchema}) => string | undefined\n headingStyle?: (context: {\n schema: EditorSchema\n level: number\n }) => string | undefined\n blockquoteStyle?: (context: {schema: EditorSchema}) => string | undefined\n unorderedListStyle?: (context: {schema: EditorSchema}) => string | undefined\n orderedListStyle?: (context: {schema: EditorSchema}) => string | undefined\n}\n\n/**\n * @beta\n * Create markdown behaviors for common markdown actions such as converting ### to headings, --- to HRs, and more.\n *\n * @example\n * Configure the bundled markdown behaviors\n * ```ts\n * import {EditorProvider} from '@portabletext/editor'\n * import {createMarkdownBehaviors, coreBehaviors} from '@portabletext/editor/behaviors'\n *\n * function App() {\n * return (\n * <EditorProvider\n * initialConfig={{\n * behaviors: [\n * ...coreBehaviors,\n * ...createMarkdownBehaviors({\n * horizontalRuleObject: ({schema}) => {\n * const name = schema.blockObjects.find(\n * (object) => object.name === 'break',\n * )?.name\n * return name ? {name} : undefined\n * },\n * defaultStyle: ({schema}) => schema.styles[0].value,\n * headingStyle: ({schema, level}) =>\n * schema.styles.find((style) => style.value === `h${level}`)\n * ?.value,\n * blockquoteStyle: ({schema}) =>\n * schema.styles.find((style) => style.value === 'blockquote')\n * ?.value,\n * unorderedListStyle: ({schema}) =>\n * schema.lists.find((list) => list.value === 'bullet')?.value,\n * orderedListStyle: ({schema}) =>\n * schema.lists.find((list) => list.value === 'number')?.value,\n * }),\n * ]\n * }}\n * >\n * {...}\n * </EditorProvider>\n * )\n * }\n * ```\n *\n */\nexport function createMarkdownBehaviors(config: MarkdownBehaviorsConfig) {\n const automaticBlockquoteOnSpace = defineBehavior({\n on: 'insert.text',\n guard: ({context, event}) => {\n const isSpace = event.text === ' '\n\n if (!isSpace) {\n return false\n }\n\n const selectionCollapsed = selectors.isSelectionCollapsed({context})\n const focusTextBlock = selectors.getFocusTextBlock({context})\n const focusSpan = selectors.getFocusSpan({context})\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const blockOffset = spanSelectionPointToBlockOffset({\n value: context.value,\n selectionPoint: {\n path: [\n {_key: focusTextBlock.node._key},\n 'children',\n {_key: focusSpan.node._key},\n ],\n offset: context.selection?.focus.offset ?? 0,\n },\n })\n\n if (!blockOffset) {\n return false\n }\n\n const blockText = getTextBlockText(focusTextBlock.node)\n const caretAtTheEndOfQuote = blockOffset.offset === 1\n const looksLikeMarkdownQuote = /^>/.test(blockText)\n const blockquoteStyle = config.blockquoteStyle?.(context)\n\n if (\n caretAtTheEndOfQuote &&\n looksLikeMarkdownQuote &&\n blockquoteStyle !== undefined\n ) {\n return {focusTextBlock, style: blockquoteStyle}\n }\n\n return false\n },\n actions: [\n () => [\n {\n type: 'insert.text',\n text: ' ',\n },\n ],\n (_, {focusTextBlock, style}) => [\n {\n type: 'text block.unset',\n props: ['listItem', 'level'],\n at: focusTextBlock.path,\n },\n {\n type: 'text block.set',\n style,\n at: focusTextBlock.path,\n },\n {\n type: 'delete.text',\n anchor: {\n path: focusTextBlock.path,\n offset: 0,\n },\n focus: {\n path: focusTextBlock.path,\n offset: 2,\n },\n },\n ],\n ],\n })\n const automaticHr = defineBehavior({\n on: 'insert.text',\n guard: ({context, event}) => {\n const hrCharacter =\n event.text === '-'\n ? '-'\n : event.text === '*'\n ? '*'\n : event.text === '_'\n ? '_'\n : undefined\n\n if (hrCharacter === undefined) {\n return false\n }\n\n const hrObject = config.horizontalRuleObject?.(context)\n const focusBlock = selectors.getFocusTextBlock({context})\n const selectionCollapsed = selectors.isSelectionCollapsed({context})\n\n if (!hrObject || !focusBlock || !selectionCollapsed) {\n return false\n }\n\n const textBefore = getBlockTextBefore({context})\n const hrBlockOffsets = {\n anchor: {\n path: focusBlock.path,\n offset: 0,\n },\n focus: {\n path: focusBlock.path,\n offset: 3,\n },\n }\n\n if (textBefore === `${hrCharacter}${hrCharacter}`) {\n return {hrObject, focusBlock, hrCharacter, hrBlockOffsets}\n }\n\n return false\n },\n actions: [\n (_, {hrCharacter}) => [\n {\n type: 'insert.text',\n text: hrCharacter,\n },\n ],\n (_, {hrObject, hrBlockOffsets}) => [\n {\n type: 'insert.block object',\n placement: 'before',\n blockObject: hrObject,\n },\n {\n type: 'delete.text',\n ...hrBlockOffsets,\n },\n ],\n ],\n })\n const automaticHrOnPaste = defineBehavior({\n on: 'paste',\n guard: ({context, event}) => {\n const text = event.data.getData('text/plain')\n const hrRegExp = /^(---)$|(___)$|(\\*\\*\\*)$/gm\n const hrCharacters = text.match(hrRegExp)?.[0]\n const hrObject = config.horizontalRuleObject?.(context)\n const focusBlock = selectors.getFocusBlock({context})\n\n if (!hrCharacters || !hrObject || !focusBlock) {\n return false\n }\n\n return {hrCharacters, hrObject, focusBlock}\n },\n actions: [\n (_, {hrCharacters}) => [\n {\n type: 'insert.text',\n text: hrCharacters,\n },\n ],\n (_, {hrObject, focusBlock}) =>\n isPortableTextTextBlock(focusBlock.node)\n ? [\n {\n type: 'insert.text block',\n textBlock: {children: focusBlock.node.children},\n placement: 'after',\n },\n {\n type: 'insert.block object',\n blockObject: hrObject,\n placement: 'after',\n },\n {type: 'delete.block', blockPath: focusBlock.path},\n ]\n : [\n {\n type: 'insert.block object',\n blockObject: hrObject,\n placement: 'after',\n },\n ],\n ],\n })\n const automaticHeadingOnSpace = defineBehavior({\n on: 'insert.text',\n guard: ({context, event}) => {\n const isSpace = event.text === ' '\n\n if (!isSpace) {\n return false\n }\n\n const selectionCollapsed = selectors.isSelectionCollapsed({context})\n const focusTextBlock = selectors.getFocusTextBlock({context})\n const focusSpan = selectors.getFocusSpan({context})\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const blockOffset = spanSelectionPointToBlockOffset({\n value: context.value,\n selectionPoint: {\n path: [\n {_key: focusTextBlock.node._key},\n 'children',\n {_key: focusSpan.node._key},\n ],\n offset: context.selection?.focus.offset ?? 0,\n },\n })\n\n if (!blockOffset) {\n return false\n }\n\n const blockText = getTextBlockText(focusTextBlock.node)\n const markdownHeadingSearch = /^#+/.exec(blockText)\n const level = markdownHeadingSearch\n ? markdownHeadingSearch[0].length\n : undefined\n const caretAtTheEndOfHeading = blockOffset.offset === level\n\n if (!caretAtTheEndOfHeading) {\n return false\n }\n\n const style =\n level !== undefined\n ? config.headingStyle?.({schema: context.schema, level})\n : undefined\n\n if (level !== undefined && style !== undefined) {\n return {\n focusTextBlock,\n style: style,\n level,\n }\n }\n\n return false\n },\n actions: [\n ({event}) => [event],\n (_, {focusTextBlock, style, level}) => [\n {\n type: 'text block.unset',\n props: ['listItem', 'level'],\n at: focusTextBlock.path,\n },\n {\n type: 'text block.set',\n style,\n at: focusTextBlock.path,\n },\n {\n type: 'delete.text',\n anchor: {\n path: focusTextBlock.path,\n offset: 0,\n },\n focus: {\n path: focusTextBlock.path,\n offset: level + 1,\n },\n },\n ],\n ],\n })\n const clearStyleOnBackspace = defineBehavior({\n on: 'delete.backward',\n guard: ({context}) => {\n const selectionCollapsed = selectors.isSelectionCollapsed({context})\n const focusTextBlock = selectors.getFocusTextBlock({context})\n const focusSpan = selectors.getFocusSpan({context})\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const atTheBeginningOfBLock =\n focusTextBlock.node.children[0]._key === focusSpan.node._key &&\n context.selection?.focus.offset === 0\n\n const defaultStyle = config.defaultStyle?.(context)\n\n if (\n atTheBeginningOfBLock &&\n defaultStyle &&\n focusTextBlock.node.style !== defaultStyle\n ) {\n return {defaultStyle, focusTextBlock}\n }\n\n return false\n },\n actions: [\n (_, {defaultStyle, focusTextBlock}) => [\n {\n type: 'text block.set',\n style: defaultStyle,\n at: focusTextBlock.path,\n },\n ],\n ],\n })\n const automaticListOnSpace = defineBehavior({\n on: 'insert.text',\n guard: ({context, event}) => {\n const isSpace = event.text === ' '\n\n if (!isSpace) {\n return false\n }\n\n const selectionCollapsed = selectors.isSelectionCollapsed({context})\n const focusTextBlock = selectors.getFocusTextBlock({context})\n const focusSpan = selectors.getFocusSpan({context})\n\n if (!selectionCollapsed || !focusTextBlock || !focusSpan) {\n return false\n }\n\n const blockOffset = spanSelectionPointToBlockOffset({\n value: context.value,\n selectionPoint: {\n path: [\n {_key: focusTextBlock.node._key},\n 'children',\n {_key: focusSpan.node._key},\n ],\n offset: context.selection?.focus.offset ?? 0,\n },\n })\n\n if (!blockOffset) {\n return false\n }\n\n const blockText = getTextBlockText(focusTextBlock.node)\n const defaultStyle = config.defaultStyle?.(context)\n const looksLikeUnorderedList = /^(-|\\*)/.test(blockText)\n const unorderedListStyle = config.unorderedListStyle?.(context)\n const caretAtTheEndOfUnorderedList = blockOffset.offset === 1\n\n if (\n defaultStyle &&\n caretAtTheEndOfUnorderedList &&\n looksLikeUnorderedList &&\n unorderedListStyle !== undefined\n ) {\n return {\n focusTextBlock,\n listItem: unorderedListStyle,\n listItemLength: 1,\n style: defaultStyle,\n }\n }\n\n const looksLikeOrderedList = /^1\\./.test(blockText)\n const orderedListStyle = config.orderedListStyle?.(context)\n const caretAtTheEndOfOrderedList = blockOffset.offset === 2\n\n if (\n defaultStyle &&\n caretAtTheEndOfOrderedList &&\n looksLikeOrderedList &&\n orderedListStyle !== undefined\n ) {\n return {\n focusTextBlock,\n listItem: orderedListStyle,\n listItemLength: 2,\n style: defaultStyle,\n }\n }\n\n return false\n },\n actions: [\n ({event}) => [event],\n (_, {focusTextBlock, style, listItem, listItemLength}) => [\n {\n type: 'text block.set',\n listItem,\n level: 1,\n style,\n at: focusTextBlock.path,\n },\n {\n type: 'delete.text',\n anchor: {\n path: focusTextBlock.path,\n offset: 0,\n },\n focus: {\n path: focusTextBlock.path,\n offset: listItemLength + 1,\n },\n },\n ],\n ],\n })\n\n const markdownBehaviors = [\n automaticBlockquoteOnSpace,\n automaticHeadingOnSpace,\n automaticHr,\n automaticHrOnPaste,\n clearStyleOnBackspace,\n automaticListOnSpace,\n ]\n\n return markdownBehaviors\n}\n"],"names":["createMarkdownBehaviors","config","automaticBlockquoteOnSpace","defineBehavior","on","guard","context","event","text","selectionCollapsed","selectors","focusTextBlock","focusSpan","blockOffset","spanSelectionPointToBlockOffset","value","selectionPoint","path","_key","node","offset","selection","focus","blockText","getTextBlockText","caretAtTheEndOfQuote","looksLikeMarkdownQuote","test","blockquoteStyle","undefined","style","actions","type","_","props","at","anchor","automaticHr","hrCharacter","hrObject","horizontalRuleObject","focusBlock","textBefore","getBlockTextBefore","hrBlockOffsets","placement","blockObject","automaticHrOnPaste","data","getData","hrRegExp","hrCharacters","match","isPortableTextTextBlock","textBlock","children","blockPath","automaticHeadingOnSpace","markdownHeadingSearch","exec","level","length","headingStyle","schema","clearStyleOnBackspace","atTheBeginningOfBLock","defaultStyle","automaticListOnSpace","looksLikeUnorderedList","unorderedListStyle","caretAtTheEndOfUnorderedList","listItem","listItemLength","looksLikeOrderedList","orderedListStyle","caretAtTheEndOfOrderedList"],"mappings":"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"}
|