@portabletext/plugin-character-pair-decorator 1.0.17 → 1.1.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/dist/index.cjs +117 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +117 -86
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: !0 });
|
|
3
|
-
var editor = require("@portabletext/editor"), behaviors = require("@portabletext/editor/behaviors"), utils = require("@portabletext/editor/utils"), react = require("@xstate/react"), remeda = require("remeda"), xstate = require("xstate"), selectors = require("@portabletext/editor/selectors");
|
|
3
|
+
var compilerRuntime = require("react/compiler-runtime"), editor = require("@portabletext/editor"), behaviors = require("@portabletext/editor/behaviors"), utils = require("@portabletext/editor/utils"), react = require("@xstate/react"), remeda = require("remeda"), xstate = require("xstate"), selectors = require("@portabletext/editor/selectors");
|
|
4
4
|
function _interopNamespaceCompat(e) {
|
|
5
5
|
if (e && typeof e == "object" && "default" in e) return e;
|
|
6
6
|
var n = /* @__PURE__ */ Object.create(null);
|
|
@@ -22,19 +22,19 @@ function createCharacterPairRegex(char, amount) {
|
|
|
22
22
|
return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`;
|
|
23
23
|
}
|
|
24
24
|
function createCharacterPairDecoratorBehavior(config) {
|
|
25
|
-
config.pair.amount < 1 && console.warn(
|
|
26
|
-
|
|
27
|
-
);
|
|
28
|
-
const pairRegex = createCharacterPairRegex(
|
|
29
|
-
config.pair.char,
|
|
30
|
-
config.pair.amount
|
|
31
|
-
), regEx = new RegExp(`(${pairRegex})$`);
|
|
25
|
+
config.pair.amount < 1 && console.warn("The amount of characters in the pair should be greater than 0");
|
|
26
|
+
const pairRegex = createCharacterPairRegex(config.pair.char, config.pair.amount), regEx = new RegExp(`(${pairRegex})$`);
|
|
32
27
|
return behaviors.defineBehavior({
|
|
33
28
|
on: "insert.text",
|
|
34
|
-
guard: ({
|
|
29
|
+
guard: ({
|
|
30
|
+
snapshot,
|
|
31
|
+
event
|
|
32
|
+
}) => {
|
|
35
33
|
if (config.pair.amount < 1)
|
|
36
34
|
return !1;
|
|
37
|
-
const decorator = config.decorator({
|
|
35
|
+
const decorator = config.decorator({
|
|
36
|
+
schema: snapshot.context.schema
|
|
37
|
+
});
|
|
38
38
|
if (decorator === void 0)
|
|
39
39
|
return !1;
|
|
40
40
|
const focusTextBlock = selectors__namespace.getFocusTextBlock(snapshot), selectionStartPoint = selectors__namespace.getSelectionStartPoint(snapshot), selectionStartOffset = selectionStartPoint ? utils__namespace.spanSelectionPointToBlockOffset({
|
|
@@ -73,18 +73,16 @@ function createCharacterPairDecoratorBehavior(config) {
|
|
|
73
73
|
const prefixSelection = utils__namespace.blockOffsetsToSelection({
|
|
74
74
|
context: snapshot.context,
|
|
75
75
|
offsets: prefixOffsets
|
|
76
|
-
}), inlineObjectBeforePrefixFocus = selectors__namespace.getPreviousInlineObject(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
context
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
} : null
|
|
85
|
-
}
|
|
76
|
+
}), inlineObjectBeforePrefixFocus = selectors__namespace.getPreviousInlineObject({
|
|
77
|
+
...snapshot,
|
|
78
|
+
context: {
|
|
79
|
+
...snapshot.context,
|
|
80
|
+
selection: prefixSelection ? {
|
|
81
|
+
anchor: prefixSelection.focus,
|
|
82
|
+
focus: prefixSelection.focus
|
|
83
|
+
} : null
|
|
86
84
|
}
|
|
87
|
-
), inlineObjectBeforePrefixFocusOffset = inlineObjectBeforePrefixFocus ? utils__namespace.childSelectionPointToBlockOffset({
|
|
85
|
+
}), inlineObjectBeforePrefixFocusOffset = inlineObjectBeforePrefixFocus ? utils__namespace.childSelectionPointToBlockOffset({
|
|
88
86
|
context: snapshot.context,
|
|
89
87
|
selectionPoint: {
|
|
90
88
|
path: inlineObjectBeforePrefixFocus.path,
|
|
@@ -113,8 +111,14 @@ function createCharacterPairDecoratorBehavior(config) {
|
|
|
113
111
|
},
|
|
114
112
|
actions: [
|
|
115
113
|
// Insert the text as usual in its own undo step
|
|
116
|
-
({
|
|
117
|
-
|
|
114
|
+
({
|
|
115
|
+
event
|
|
116
|
+
}) => [behaviors.execute(event)],
|
|
117
|
+
(_, {
|
|
118
|
+
prefixOffsets,
|
|
119
|
+
suffixOffsets,
|
|
120
|
+
decorator
|
|
121
|
+
}) => [
|
|
118
122
|
// Decorate the text between the prefix and suffix
|
|
119
123
|
behaviors.execute({
|
|
120
124
|
type: "decorator.add",
|
|
@@ -150,29 +154,44 @@ function createCharacterPairDecoratorBehavior(config) {
|
|
|
150
154
|
});
|
|
151
155
|
}
|
|
152
156
|
function CharacterPairDecoratorPlugin(config) {
|
|
153
|
-
const editor$1 = editor.useEditor();
|
|
154
|
-
|
|
157
|
+
const $ = compilerRuntime.c(4), editor$1 = editor.useEditor();
|
|
158
|
+
let t0;
|
|
159
|
+
return $[0] !== config.decorator || $[1] !== config.pair || $[2] !== editor$1 ? (t0 = {
|
|
155
160
|
input: {
|
|
156
161
|
editor: editor$1,
|
|
157
162
|
decorator: config.decorator,
|
|
158
163
|
pair: config.pair
|
|
159
164
|
}
|
|
160
|
-
}), null;
|
|
165
|
+
}, $[0] = config.decorator, $[1] = config.pair, $[2] = editor$1, $[3] = t0) : t0 = $[3], react.useActorRef(decoratorPairMachine, t0), null;
|
|
161
166
|
}
|
|
162
|
-
const decorateListener = ({
|
|
167
|
+
const decorateListener = ({
|
|
168
|
+
sendBack,
|
|
169
|
+
input
|
|
170
|
+
}) => input.editor.registerBehavior({
|
|
163
171
|
behavior: createCharacterPairDecoratorBehavior({
|
|
164
172
|
decorator: input.decorator,
|
|
165
173
|
pair: input.pair,
|
|
166
174
|
onDecorate: (offset) => {
|
|
167
|
-
sendBack({
|
|
175
|
+
sendBack({
|
|
176
|
+
type: "decorator.add",
|
|
177
|
+
blockOffset: offset
|
|
178
|
+
});
|
|
168
179
|
}
|
|
169
180
|
})
|
|
170
|
-
}), selectionListenerCallback = ({
|
|
181
|
+
}), selectionListenerCallback = ({
|
|
182
|
+
sendBack,
|
|
183
|
+
input
|
|
184
|
+
}) => input.editor.registerBehavior({
|
|
171
185
|
behavior: behaviors.defineBehavior({
|
|
172
186
|
on: "select",
|
|
173
|
-
guard: ({
|
|
187
|
+
guard: ({
|
|
188
|
+
snapshot,
|
|
189
|
+
event
|
|
190
|
+
}) => {
|
|
174
191
|
if (!event.at)
|
|
175
|
-
return {
|
|
192
|
+
return {
|
|
193
|
+
blockOffsets: void 0
|
|
194
|
+
};
|
|
176
195
|
const anchor = utils__namespace.spanSelectionPointToBlockOffset({
|
|
177
196
|
context: snapshot.context,
|
|
178
197
|
selectionPoint: event.at.anchor
|
|
@@ -180,38 +199,42 @@ const decorateListener = ({ sendBack, input }) => input.editor.registerBehavior(
|
|
|
180
199
|
context: snapshot.context,
|
|
181
200
|
selectionPoint: event.at.focus
|
|
182
201
|
});
|
|
183
|
-
return !anchor || !focus ? {
|
|
202
|
+
return !anchor || !focus ? {
|
|
203
|
+
blockOffsets: void 0
|
|
204
|
+
} : {
|
|
184
205
|
blockOffsets: {
|
|
185
206
|
anchor,
|
|
186
207
|
focus
|
|
187
208
|
}
|
|
188
209
|
};
|
|
189
210
|
},
|
|
190
|
-
actions: [
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
211
|
+
actions: [({
|
|
212
|
+
event
|
|
213
|
+
}, {
|
|
214
|
+
blockOffsets
|
|
215
|
+
}) => [{
|
|
216
|
+
type: "effect",
|
|
217
|
+
effect: () => {
|
|
218
|
+
sendBack({
|
|
219
|
+
type: "selection",
|
|
220
|
+
blockOffsets
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}, behaviors.forward(event)]]
|
|
201
224
|
})
|
|
202
|
-
}), deleteBackwardListenerCallback = ({
|
|
225
|
+
}), deleteBackwardListenerCallback = ({
|
|
226
|
+
sendBack,
|
|
227
|
+
input
|
|
228
|
+
}) => input.editor.registerBehavior({
|
|
203
229
|
behavior: behaviors.defineBehavior({
|
|
204
230
|
on: "delete.backward",
|
|
205
|
-
actions: [
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
})
|
|
213
|
-
]
|
|
214
|
-
]
|
|
231
|
+
actions: [() => [behaviors.execute({
|
|
232
|
+
type: "history.undo"
|
|
233
|
+
}), behaviors.effect(() => {
|
|
234
|
+
sendBack({
|
|
235
|
+
type: "delete.backward"
|
|
236
|
+
});
|
|
237
|
+
})]]
|
|
215
238
|
})
|
|
216
239
|
}), decoratorPairMachine = xstate.setup({
|
|
217
240
|
types: {
|
|
@@ -226,7 +249,9 @@ const decorateListener = ({ sendBack, input }) => input.editor.registerBehavior(
|
|
|
226
249
|
}
|
|
227
250
|
}).createMachine({
|
|
228
251
|
id: "decorator pair",
|
|
229
|
-
context: ({
|
|
252
|
+
context: ({
|
|
253
|
+
input
|
|
254
|
+
}) => ({
|
|
230
255
|
decorator: input.decorator,
|
|
231
256
|
editor: input.editor,
|
|
232
257
|
pair: input.pair
|
|
@@ -234,51 +259,56 @@ const decorateListener = ({ sendBack, input }) => input.editor.registerBehavior(
|
|
|
234
259
|
initial: "idle",
|
|
235
260
|
states: {
|
|
236
261
|
idle: {
|
|
237
|
-
invoke: [
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
],
|
|
262
|
+
invoke: [{
|
|
263
|
+
src: "decorate listener",
|
|
264
|
+
input: ({
|
|
265
|
+
context
|
|
266
|
+
}) => ({
|
|
267
|
+
decorator: context.decorator,
|
|
268
|
+
editor: context.editor,
|
|
269
|
+
pair: context.pair
|
|
270
|
+
})
|
|
271
|
+
}],
|
|
247
272
|
on: {
|
|
248
273
|
"decorator.add": {
|
|
249
274
|
target: "decorator added",
|
|
250
275
|
actions: xstate.assign({
|
|
251
|
-
offsetAfterDecorator: ({
|
|
276
|
+
offsetAfterDecorator: ({
|
|
277
|
+
event
|
|
278
|
+
}) => event.blockOffset
|
|
252
279
|
})
|
|
253
280
|
}
|
|
254
281
|
}
|
|
255
282
|
},
|
|
256
283
|
"decorator added": {
|
|
257
|
-
exit: [
|
|
258
|
-
|
|
259
|
-
|
|
284
|
+
exit: [xstate.assign({
|
|
285
|
+
offsetAfterDecorator: void 0
|
|
286
|
+
})],
|
|
287
|
+
invoke: [{
|
|
288
|
+
src: "selection listener",
|
|
289
|
+
input: ({
|
|
290
|
+
context
|
|
291
|
+
}) => ({
|
|
292
|
+
editor: context.editor
|
|
260
293
|
})
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
{
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
input: ({ context }) => ({ editor: context.editor })
|
|
270
|
-
}
|
|
271
|
-
],
|
|
294
|
+
}, {
|
|
295
|
+
src: "delete.backward listener",
|
|
296
|
+
input: ({
|
|
297
|
+
context
|
|
298
|
+
}) => ({
|
|
299
|
+
editor: context.editor
|
|
300
|
+
})
|
|
301
|
+
}],
|
|
272
302
|
on: {
|
|
273
303
|
selection: {
|
|
274
304
|
target: "idle",
|
|
275
|
-
guard: ({
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
)
|
|
305
|
+
guard: ({
|
|
306
|
+
context,
|
|
307
|
+
event
|
|
308
|
+
}) => !remeda.isDeepEqual({
|
|
309
|
+
anchor: context.offsetAfterDecorator,
|
|
310
|
+
focus: context.offsetAfterDecorator
|
|
311
|
+
}, event.blockOffsets)
|
|
282
312
|
},
|
|
283
313
|
"delete.backward": {
|
|
284
314
|
target: "idle"
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/regex.character-pair.ts","../src/behavior.character-pair-decorator.ts","../src/plugin.character-pair-decorator.ts"],"sourcesContent":["export function createCharacterPairRegex(char: string, amount: number) {\n // Negative lookbehind: Ensures that the matched sequence is not preceded by the same character\n const prePrefix = `(?<!\\\\${char})`\n\n // Repeats the character `amount` times\n const prefix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the opening pair (**, *, etc.) is not followed by a space\n const postPrefix = `(?!\\\\s)`\n\n // Captures the content inside the pair\n const content = `([^${char}\\\\n]+?)`\n\n // Negative lookbehind: Ensures that the content is not followed by a space\n const preSuffix = `(?<!\\\\s)`\n\n // Repeats the character `amount` times\n const suffix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the matched sequence is not followed by the same character\n const postSuffix = `(?!\\\\${char})`\n\n return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`\n}\n","import type {BlockOffset, EditorSchema} from '@portabletext/editor'\nimport {defineBehavior, effect, execute} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport * as utils from '@portabletext/editor/utils'\nimport {createCharacterPairRegex} from './regex.character-pair'\n\nexport function createCharacterPairDecoratorBehavior(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n onDecorate: (offset: BlockOffset) => void\n}) {\n if (config.pair.amount < 1) {\n console.warn(\n `The amount of characters in the pair should be greater than 0`,\n )\n }\n\n const pairRegex = createCharacterPairRegex(\n config.pair.char,\n config.pair.amount,\n )\n const regEx = new RegExp(`(${pairRegex})$`)\n\n return defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n if (config.pair.amount < 1) {\n return false\n }\n\n const decorator = config.decorator({schema: snapshot.context.schema})\n\n if (decorator === undefined) {\n return false\n }\n\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const selectionStartPoint = selectors.getSelectionStartPoint(snapshot)\n const selectionStartOffset = selectionStartPoint\n ? utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: selectionStartPoint,\n })\n : undefined\n\n if (!focusTextBlock || !selectionStartOffset) {\n return false\n }\n\n const textBefore = selectors.getBlockTextBefore(snapshot)\n const newText = `${textBefore}${event.text}`\n const textToDecorate = newText.match(regEx)?.at(0)\n\n if (textToDecorate === undefined) {\n return false\n }\n\n const prefixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length = 4\n offset: newText.length - textToDecorate.length,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length + \"*\".length * 2 = 6\n offset:\n newText.length -\n textToDecorate.length +\n config.pair.char.length * config.pair.amount,\n },\n }\n\n const suffixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length - 2 = 9\n offset:\n selectionStartOffset.offset +\n event.text.length -\n config.pair.char.length * config.pair.amount,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length = 11\n offset: selectionStartOffset.offset + event.text.length,\n },\n }\n\n // If the prefix is more than one character, then we need to check if\n // there is an inline object inside it\n if (prefixOffsets.focus.offset - prefixOffsets.anchor.offset > 1) {\n const prefixSelection = utils.blockOffsetsToSelection({\n context: snapshot.context,\n offsets: prefixOffsets,\n })\n const inlineObjectBeforePrefixFocus = selectors.getPreviousInlineObject(\n {\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: prefixSelection\n ? {\n anchor: prefixSelection.focus,\n focus: prefixSelection.focus,\n }\n : null,\n },\n },\n )\n const inlineObjectBeforePrefixFocusOffset =\n inlineObjectBeforePrefixFocus\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: inlineObjectBeforePrefixFocus.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n inlineObjectBeforePrefixFocusOffset &&\n inlineObjectBeforePrefixFocusOffset.offset >\n prefixOffsets.anchor.offset &&\n inlineObjectBeforePrefixFocusOffset.offset <\n prefixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n // If the suffix is more than one character, then we need to check if\n // there is an inline object inside it\n if (suffixOffsets.focus.offset - suffixOffsets.anchor.offset > 1) {\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const previousInlineObjectOffset = previousInlineObject\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: previousInlineObject.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n previousInlineObjectOffset &&\n previousInlineObjectOffset.offset > suffixOffsets.anchor.offset &&\n previousInlineObjectOffset.offset < suffixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n return {\n prefixOffsets,\n suffixOffsets,\n decorator,\n }\n },\n actions: [\n // Insert the text as usual in its own undo step\n ({event}) => [execute(event)],\n (_, {prefixOffsets, suffixOffsets, decorator}) => [\n // Decorate the text between the prefix and suffix\n execute({\n type: 'decorator.add',\n decorator,\n at: {\n anchor: prefixOffsets.focus,\n focus: suffixOffsets.anchor,\n },\n }),\n // Delete the suffix\n execute({\n type: 'delete.text',\n at: suffixOffsets,\n }),\n // Delete the prefix\n execute({\n type: 'delete.text',\n at: prefixOffsets,\n }),\n // Toggle the decorator off so the next inserted text isn't emphasized\n execute({\n type: 'decorator.remove',\n decorator,\n }),\n effect(() => {\n config.onDecorate({\n ...suffixOffsets.anchor,\n offset:\n suffixOffsets.anchor.offset -\n (prefixOffsets.focus.offset - prefixOffsets.anchor.offset),\n })\n }),\n ],\n ],\n })\n}\n","import type {BlockOffset, Editor, EditorSchema} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n execute,\n forward,\n} from '@portabletext/editor/behaviors'\nimport * as utils from '@portabletext/editor/utils'\nimport {useActorRef} from '@xstate/react'\nimport {isDeepEqual} from 'remeda'\nimport {\n assign,\n fromCallback,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport {createCharacterPairDecoratorBehavior} from './behavior.character-pair-decorator'\n\n/**\n * @beta\n */\nexport function CharacterPairDecoratorPlugin(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n}) {\n const editor = useEditor()\n\n useActorRef(decoratorPairMachine, {\n input: {\n editor,\n decorator: config.decorator,\n pair: config.pair,\n },\n })\n\n return null\n}\n\ntype DecoratorPairEvent =\n | {\n type: 'decorator.add'\n blockOffset: BlockOffset\n }\n | {\n type: 'selection'\n blockOffsets?: {\n anchor: BlockOffset\n focus: BlockOffset\n }\n }\n | {\n type: 'delete.backward'\n }\n\nconst decorateListener: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n }\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: createCharacterPairDecoratorBehavior({\n decorator: input.decorator,\n pair: input.pair,\n onDecorate: (offset) => {\n sendBack({type: 'decorator.add', blockOffset: offset})\n },\n }),\n })\n\n return unregister\n}\n\nconst selectionListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'select',\n guard: ({snapshot, event}) => {\n if (!event.at) {\n return {blockOffsets: undefined}\n }\n\n const anchor = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.anchor,\n })\n const focus = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.focus,\n })\n\n if (!anchor || !focus) {\n return {blockOffsets: undefined}\n }\n\n return {\n blockOffsets: {\n anchor,\n focus,\n },\n }\n },\n actions: [\n ({event}, {blockOffsets}) => [\n {\n type: 'effect',\n effect: () => {\n sendBack({type: 'selection', blockOffsets})\n },\n },\n forward(event),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst deleteBackwardListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'delete.backward',\n actions: [\n () => [\n execute({\n type: 'history.undo',\n }),\n effect(() => {\n sendBack({type: 'delete.backward'})\n }),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst decoratorPairMachine = setup({\n types: {\n context: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n offsetAfterDecorator?: BlockOffset\n pair: {char: string; amount: number}\n },\n input: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n },\n events: {} as DecoratorPairEvent,\n },\n actors: {\n 'decorate listener': fromCallback(decorateListener),\n 'delete.backward listener': fromCallback(deleteBackwardListenerCallback),\n 'selection listener': fromCallback(selectionListenerCallback),\n },\n}).createMachine({\n id: 'decorator pair',\n context: ({input}) => ({\n decorator: input.decorator,\n editor: input.editor,\n pair: input.pair,\n }),\n initial: 'idle',\n states: {\n 'idle': {\n invoke: [\n {\n src: 'decorate listener',\n input: ({context}) => ({\n decorator: context.decorator,\n editor: context.editor,\n pair: context.pair,\n }),\n },\n ],\n on: {\n 'decorator.add': {\n target: 'decorator added',\n actions: assign({\n offsetAfterDecorator: ({event}) => event.blockOffset,\n }),\n },\n },\n },\n 'decorator added': {\n exit: [\n assign({\n offsetAfterDecorator: undefined,\n }),\n ],\n invoke: [\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'delete.backward listener',\n input: ({context}) => ({editor: context.editor}),\n },\n ],\n on: {\n 'selection': {\n target: 'idle',\n guard: ({context, event}) => {\n const selectionChanged = !isDeepEqual(\n {\n anchor: context.offsetAfterDecorator,\n focus: context.offsetAfterDecorator,\n },\n event.blockOffsets,\n )\n\n return selectionChanged\n },\n },\n 'delete.backward': {\n target: 'idle',\n },\n },\n },\n },\n})\n"],"names":["defineBehavior","selectors","utils","execute","effect","editor","useEditor","useActorRef","forward","setup","fromCallback","assign","isDeepEqual"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/regex.character-pair.ts","../src/behavior.character-pair-decorator.ts","../src/plugin.character-pair-decorator.ts"],"sourcesContent":["export function createCharacterPairRegex(char: string, amount: number) {\n // Negative lookbehind: Ensures that the matched sequence is not preceded by the same character\n const prePrefix = `(?<!\\\\${char})`\n\n // Repeats the character `amount` times\n const prefix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the opening pair (**, *, etc.) is not followed by a space\n const postPrefix = `(?!\\\\s)`\n\n // Captures the content inside the pair\n const content = `([^${char}\\\\n]+?)`\n\n // Negative lookbehind: Ensures that the content is not followed by a space\n const preSuffix = `(?<!\\\\s)`\n\n // Repeats the character `amount` times\n const suffix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the matched sequence is not followed by the same character\n const postSuffix = `(?!\\\\${char})`\n\n return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`\n}\n","import type {BlockOffset, EditorSchema} from '@portabletext/editor'\nimport {defineBehavior, effect, execute} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport * as utils from '@portabletext/editor/utils'\nimport {createCharacterPairRegex} from './regex.character-pair'\n\nexport function createCharacterPairDecoratorBehavior(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n onDecorate: (offset: BlockOffset) => void\n}) {\n if (config.pair.amount < 1) {\n console.warn(\n `The amount of characters in the pair should be greater than 0`,\n )\n }\n\n const pairRegex = createCharacterPairRegex(\n config.pair.char,\n config.pair.amount,\n )\n const regEx = new RegExp(`(${pairRegex})$`)\n\n return defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n if (config.pair.amount < 1) {\n return false\n }\n\n const decorator = config.decorator({schema: snapshot.context.schema})\n\n if (decorator === undefined) {\n return false\n }\n\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const selectionStartPoint = selectors.getSelectionStartPoint(snapshot)\n const selectionStartOffset = selectionStartPoint\n ? utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: selectionStartPoint,\n })\n : undefined\n\n if (!focusTextBlock || !selectionStartOffset) {\n return false\n }\n\n const textBefore = selectors.getBlockTextBefore(snapshot)\n const newText = `${textBefore}${event.text}`\n const textToDecorate = newText.match(regEx)?.at(0)\n\n if (textToDecorate === undefined) {\n return false\n }\n\n const prefixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length = 4\n offset: newText.length - textToDecorate.length,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length + \"*\".length * 2 = 6\n offset:\n newText.length -\n textToDecorate.length +\n config.pair.char.length * config.pair.amount,\n },\n }\n\n const suffixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length - 2 = 9\n offset:\n selectionStartOffset.offset +\n event.text.length -\n config.pair.char.length * config.pair.amount,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length = 11\n offset: selectionStartOffset.offset + event.text.length,\n },\n }\n\n // If the prefix is more than one character, then we need to check if\n // there is an inline object inside it\n if (prefixOffsets.focus.offset - prefixOffsets.anchor.offset > 1) {\n const prefixSelection = utils.blockOffsetsToSelection({\n context: snapshot.context,\n offsets: prefixOffsets,\n })\n const inlineObjectBeforePrefixFocus = selectors.getPreviousInlineObject(\n {\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: prefixSelection\n ? {\n anchor: prefixSelection.focus,\n focus: prefixSelection.focus,\n }\n : null,\n },\n },\n )\n const inlineObjectBeforePrefixFocusOffset =\n inlineObjectBeforePrefixFocus\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: inlineObjectBeforePrefixFocus.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n inlineObjectBeforePrefixFocusOffset &&\n inlineObjectBeforePrefixFocusOffset.offset >\n prefixOffsets.anchor.offset &&\n inlineObjectBeforePrefixFocusOffset.offset <\n prefixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n // If the suffix is more than one character, then we need to check if\n // there is an inline object inside it\n if (suffixOffsets.focus.offset - suffixOffsets.anchor.offset > 1) {\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const previousInlineObjectOffset = previousInlineObject\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: previousInlineObject.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n previousInlineObjectOffset &&\n previousInlineObjectOffset.offset > suffixOffsets.anchor.offset &&\n previousInlineObjectOffset.offset < suffixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n return {\n prefixOffsets,\n suffixOffsets,\n decorator,\n }\n },\n actions: [\n // Insert the text as usual in its own undo step\n ({event}) => [execute(event)],\n (_, {prefixOffsets, suffixOffsets, decorator}) => [\n // Decorate the text between the prefix and suffix\n execute({\n type: 'decorator.add',\n decorator,\n at: {\n anchor: prefixOffsets.focus,\n focus: suffixOffsets.anchor,\n },\n }),\n // Delete the suffix\n execute({\n type: 'delete.text',\n at: suffixOffsets,\n }),\n // Delete the prefix\n execute({\n type: 'delete.text',\n at: prefixOffsets,\n }),\n // Toggle the decorator off so the next inserted text isn't emphasized\n execute({\n type: 'decorator.remove',\n decorator,\n }),\n effect(() => {\n config.onDecorate({\n ...suffixOffsets.anchor,\n offset:\n suffixOffsets.anchor.offset -\n (prefixOffsets.focus.offset - prefixOffsets.anchor.offset),\n })\n }),\n ],\n ],\n })\n}\n","import type {BlockOffset, Editor, EditorSchema} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n execute,\n forward,\n} from '@portabletext/editor/behaviors'\nimport * as utils from '@portabletext/editor/utils'\nimport {useActorRef} from '@xstate/react'\nimport {isDeepEqual} from 'remeda'\nimport {\n assign,\n fromCallback,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport {createCharacterPairDecoratorBehavior} from './behavior.character-pair-decorator'\n\n/**\n * @beta\n */\nexport function CharacterPairDecoratorPlugin(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n}) {\n const editor = useEditor()\n\n useActorRef(decoratorPairMachine, {\n input: {\n editor,\n decorator: config.decorator,\n pair: config.pair,\n },\n })\n\n return null\n}\n\ntype DecoratorPairEvent =\n | {\n type: 'decorator.add'\n blockOffset: BlockOffset\n }\n | {\n type: 'selection'\n blockOffsets?: {\n anchor: BlockOffset\n focus: BlockOffset\n }\n }\n | {\n type: 'delete.backward'\n }\n\nconst decorateListener: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n }\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: createCharacterPairDecoratorBehavior({\n decorator: input.decorator,\n pair: input.pair,\n onDecorate: (offset) => {\n sendBack({type: 'decorator.add', blockOffset: offset})\n },\n }),\n })\n\n return unregister\n}\n\nconst selectionListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'select',\n guard: ({snapshot, event}) => {\n if (!event.at) {\n return {blockOffsets: undefined}\n }\n\n const anchor = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.anchor,\n })\n const focus = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.focus,\n })\n\n if (!anchor || !focus) {\n return {blockOffsets: undefined}\n }\n\n return {\n blockOffsets: {\n anchor,\n focus,\n },\n }\n },\n actions: [\n ({event}, {blockOffsets}) => [\n {\n type: 'effect',\n effect: () => {\n sendBack({type: 'selection', blockOffsets})\n },\n },\n forward(event),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst deleteBackwardListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'delete.backward',\n actions: [\n () => [\n execute({\n type: 'history.undo',\n }),\n effect(() => {\n sendBack({type: 'delete.backward'})\n }),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst decoratorPairMachine = setup({\n types: {\n context: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n offsetAfterDecorator?: BlockOffset\n pair: {char: string; amount: number}\n },\n input: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n },\n events: {} as DecoratorPairEvent,\n },\n actors: {\n 'decorate listener': fromCallback(decorateListener),\n 'delete.backward listener': fromCallback(deleteBackwardListenerCallback),\n 'selection listener': fromCallback(selectionListenerCallback),\n },\n}).createMachine({\n id: 'decorator pair',\n context: ({input}) => ({\n decorator: input.decorator,\n editor: input.editor,\n pair: input.pair,\n }),\n initial: 'idle',\n states: {\n 'idle': {\n invoke: [\n {\n src: 'decorate listener',\n input: ({context}) => ({\n decorator: context.decorator,\n editor: context.editor,\n pair: context.pair,\n }),\n },\n ],\n on: {\n 'decorator.add': {\n target: 'decorator added',\n actions: assign({\n offsetAfterDecorator: ({event}) => event.blockOffset,\n }),\n },\n },\n },\n 'decorator added': {\n exit: [\n assign({\n offsetAfterDecorator: undefined,\n }),\n ],\n invoke: [\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'delete.backward listener',\n input: ({context}) => ({editor: context.editor}),\n },\n ],\n on: {\n 'selection': {\n target: 'idle',\n guard: ({context, event}) => {\n const selectionChanged = !isDeepEqual(\n {\n anchor: context.offsetAfterDecorator,\n focus: context.offsetAfterDecorator,\n },\n event.blockOffsets,\n )\n\n return selectionChanged\n },\n },\n 'delete.backward': {\n target: 'idle',\n },\n },\n },\n },\n})\n"],"names":["createCharacterPairRegex","char","amount","prePrefix","prefix","repeat","Math","max","postPrefix","content","preSuffix","suffix","postSuffix","createCharacterPairDecoratorBehavior","config","pair","console","warn","pairRegex","regEx","RegExp","defineBehavior","on","guard","snapshot","event","decorator","schema","context","undefined","focusTextBlock","selectors","getFocusTextBlock","selectionStartPoint","getSelectionStartPoint","selectionStartOffset","utils","spanSelectionPointToBlockOffset","selectionPoint","newText","getBlockTextBefore","text","textToDecorate","match","at","prefixOffsets","anchor","path","offset","length","focus","suffixOffsets","prefixSelection","blockOffsetsToSelection","offsets","inlineObjectBeforePrefixFocus","getPreviousInlineObject","selection","inlineObjectBeforePrefixFocusOffset","childSelectionPointToBlockOffset","previousInlineObject","previousInlineObjectOffset","actions","execute","_","type","effect","onDecorate","CharacterPairDecoratorPlugin","$","_c","editor","useEditor","t0","input","useActorRef","decoratorPairMachine","decorateListener","sendBack","registerBehavior","behavior","blockOffset","selectionListenerCallback","blockOffsets","forward","deleteBackwardListenerCallback","setup","types","events","actors","fromCallback","createMachine","id","initial","states","invoke","src","target","assign","offsetAfterDecorator","exit","isDeepEqual"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { c } from "react/compiler-runtime";
|
|
1
2
|
import { useEditor } from "@portabletext/editor";
|
|
2
3
|
import { defineBehavior, execute, effect, forward } from "@portabletext/editor/behaviors";
|
|
3
4
|
import * as utils from "@portabletext/editor/utils";
|
|
@@ -10,19 +11,19 @@ function createCharacterPairRegex(char, amount) {
|
|
|
10
11
|
return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`;
|
|
11
12
|
}
|
|
12
13
|
function createCharacterPairDecoratorBehavior(config) {
|
|
13
|
-
config.pair.amount < 1 && console.warn(
|
|
14
|
-
|
|
15
|
-
);
|
|
16
|
-
const pairRegex = createCharacterPairRegex(
|
|
17
|
-
config.pair.char,
|
|
18
|
-
config.pair.amount
|
|
19
|
-
), regEx = new RegExp(`(${pairRegex})$`);
|
|
14
|
+
config.pair.amount < 1 && console.warn("The amount of characters in the pair should be greater than 0");
|
|
15
|
+
const pairRegex = createCharacterPairRegex(config.pair.char, config.pair.amount), regEx = new RegExp(`(${pairRegex})$`);
|
|
20
16
|
return defineBehavior({
|
|
21
17
|
on: "insert.text",
|
|
22
|
-
guard: ({
|
|
18
|
+
guard: ({
|
|
19
|
+
snapshot,
|
|
20
|
+
event
|
|
21
|
+
}) => {
|
|
23
22
|
if (config.pair.amount < 1)
|
|
24
23
|
return !1;
|
|
25
|
-
const decorator = config.decorator({
|
|
24
|
+
const decorator = config.decorator({
|
|
25
|
+
schema: snapshot.context.schema
|
|
26
|
+
});
|
|
26
27
|
if (decorator === void 0)
|
|
27
28
|
return !1;
|
|
28
29
|
const focusTextBlock = selectors.getFocusTextBlock(snapshot), selectionStartPoint = selectors.getSelectionStartPoint(snapshot), selectionStartOffset = selectionStartPoint ? utils.spanSelectionPointToBlockOffset({
|
|
@@ -61,18 +62,16 @@ function createCharacterPairDecoratorBehavior(config) {
|
|
|
61
62
|
const prefixSelection = utils.blockOffsetsToSelection({
|
|
62
63
|
context: snapshot.context,
|
|
63
64
|
offsets: prefixOffsets
|
|
64
|
-
}), inlineObjectBeforePrefixFocus = selectors.getPreviousInlineObject(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
context
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} : null
|
|
73
|
-
}
|
|
65
|
+
}), inlineObjectBeforePrefixFocus = selectors.getPreviousInlineObject({
|
|
66
|
+
...snapshot,
|
|
67
|
+
context: {
|
|
68
|
+
...snapshot.context,
|
|
69
|
+
selection: prefixSelection ? {
|
|
70
|
+
anchor: prefixSelection.focus,
|
|
71
|
+
focus: prefixSelection.focus
|
|
72
|
+
} : null
|
|
74
73
|
}
|
|
75
|
-
), inlineObjectBeforePrefixFocusOffset = inlineObjectBeforePrefixFocus ? utils.childSelectionPointToBlockOffset({
|
|
74
|
+
}), inlineObjectBeforePrefixFocusOffset = inlineObjectBeforePrefixFocus ? utils.childSelectionPointToBlockOffset({
|
|
76
75
|
context: snapshot.context,
|
|
77
76
|
selectionPoint: {
|
|
78
77
|
path: inlineObjectBeforePrefixFocus.path,
|
|
@@ -101,8 +100,14 @@ function createCharacterPairDecoratorBehavior(config) {
|
|
|
101
100
|
},
|
|
102
101
|
actions: [
|
|
103
102
|
// Insert the text as usual in its own undo step
|
|
104
|
-
({
|
|
105
|
-
|
|
103
|
+
({
|
|
104
|
+
event
|
|
105
|
+
}) => [execute(event)],
|
|
106
|
+
(_, {
|
|
107
|
+
prefixOffsets,
|
|
108
|
+
suffixOffsets,
|
|
109
|
+
decorator
|
|
110
|
+
}) => [
|
|
106
111
|
// Decorate the text between the prefix and suffix
|
|
107
112
|
execute({
|
|
108
113
|
type: "decorator.add",
|
|
@@ -138,29 +143,44 @@ function createCharacterPairDecoratorBehavior(config) {
|
|
|
138
143
|
});
|
|
139
144
|
}
|
|
140
145
|
function CharacterPairDecoratorPlugin(config) {
|
|
141
|
-
const editor = useEditor();
|
|
142
|
-
|
|
146
|
+
const $ = c(4), editor = useEditor();
|
|
147
|
+
let t0;
|
|
148
|
+
return $[0] !== config.decorator || $[1] !== config.pair || $[2] !== editor ? (t0 = {
|
|
143
149
|
input: {
|
|
144
150
|
editor,
|
|
145
151
|
decorator: config.decorator,
|
|
146
152
|
pair: config.pair
|
|
147
153
|
}
|
|
148
|
-
}), null;
|
|
154
|
+
}, $[0] = config.decorator, $[1] = config.pair, $[2] = editor, $[3] = t0) : t0 = $[3], useActorRef(decoratorPairMachine, t0), null;
|
|
149
155
|
}
|
|
150
|
-
const decorateListener = ({
|
|
156
|
+
const decorateListener = ({
|
|
157
|
+
sendBack,
|
|
158
|
+
input
|
|
159
|
+
}) => input.editor.registerBehavior({
|
|
151
160
|
behavior: createCharacterPairDecoratorBehavior({
|
|
152
161
|
decorator: input.decorator,
|
|
153
162
|
pair: input.pair,
|
|
154
163
|
onDecorate: (offset) => {
|
|
155
|
-
sendBack({
|
|
164
|
+
sendBack({
|
|
165
|
+
type: "decorator.add",
|
|
166
|
+
blockOffset: offset
|
|
167
|
+
});
|
|
156
168
|
}
|
|
157
169
|
})
|
|
158
|
-
}), selectionListenerCallback = ({
|
|
170
|
+
}), selectionListenerCallback = ({
|
|
171
|
+
sendBack,
|
|
172
|
+
input
|
|
173
|
+
}) => input.editor.registerBehavior({
|
|
159
174
|
behavior: defineBehavior({
|
|
160
175
|
on: "select",
|
|
161
|
-
guard: ({
|
|
176
|
+
guard: ({
|
|
177
|
+
snapshot,
|
|
178
|
+
event
|
|
179
|
+
}) => {
|
|
162
180
|
if (!event.at)
|
|
163
|
-
return {
|
|
181
|
+
return {
|
|
182
|
+
blockOffsets: void 0
|
|
183
|
+
};
|
|
164
184
|
const anchor = utils.spanSelectionPointToBlockOffset({
|
|
165
185
|
context: snapshot.context,
|
|
166
186
|
selectionPoint: event.at.anchor
|
|
@@ -168,38 +188,42 @@ const decorateListener = ({ sendBack, input }) => input.editor.registerBehavior(
|
|
|
168
188
|
context: snapshot.context,
|
|
169
189
|
selectionPoint: event.at.focus
|
|
170
190
|
});
|
|
171
|
-
return !anchor || !focus ? {
|
|
191
|
+
return !anchor || !focus ? {
|
|
192
|
+
blockOffsets: void 0
|
|
193
|
+
} : {
|
|
172
194
|
blockOffsets: {
|
|
173
195
|
anchor,
|
|
174
196
|
focus
|
|
175
197
|
}
|
|
176
198
|
};
|
|
177
199
|
},
|
|
178
|
-
actions: [
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
200
|
+
actions: [({
|
|
201
|
+
event
|
|
202
|
+
}, {
|
|
203
|
+
blockOffsets
|
|
204
|
+
}) => [{
|
|
205
|
+
type: "effect",
|
|
206
|
+
effect: () => {
|
|
207
|
+
sendBack({
|
|
208
|
+
type: "selection",
|
|
209
|
+
blockOffsets
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}, forward(event)]]
|
|
189
213
|
})
|
|
190
|
-
}), deleteBackwardListenerCallback = ({
|
|
214
|
+
}), deleteBackwardListenerCallback = ({
|
|
215
|
+
sendBack,
|
|
216
|
+
input
|
|
217
|
+
}) => input.editor.registerBehavior({
|
|
191
218
|
behavior: defineBehavior({
|
|
192
219
|
on: "delete.backward",
|
|
193
|
-
actions: [
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
})
|
|
201
|
-
]
|
|
202
|
-
]
|
|
220
|
+
actions: [() => [execute({
|
|
221
|
+
type: "history.undo"
|
|
222
|
+
}), effect(() => {
|
|
223
|
+
sendBack({
|
|
224
|
+
type: "delete.backward"
|
|
225
|
+
});
|
|
226
|
+
})]]
|
|
203
227
|
})
|
|
204
228
|
}), decoratorPairMachine = setup({
|
|
205
229
|
types: {
|
|
@@ -214,7 +238,9 @@ const decorateListener = ({ sendBack, input }) => input.editor.registerBehavior(
|
|
|
214
238
|
}
|
|
215
239
|
}).createMachine({
|
|
216
240
|
id: "decorator pair",
|
|
217
|
-
context: ({
|
|
241
|
+
context: ({
|
|
242
|
+
input
|
|
243
|
+
}) => ({
|
|
218
244
|
decorator: input.decorator,
|
|
219
245
|
editor: input.editor,
|
|
220
246
|
pair: input.pair
|
|
@@ -222,51 +248,56 @@ const decorateListener = ({ sendBack, input }) => input.editor.registerBehavior(
|
|
|
222
248
|
initial: "idle",
|
|
223
249
|
states: {
|
|
224
250
|
idle: {
|
|
225
|
-
invoke: [
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
234
|
-
],
|
|
251
|
+
invoke: [{
|
|
252
|
+
src: "decorate listener",
|
|
253
|
+
input: ({
|
|
254
|
+
context
|
|
255
|
+
}) => ({
|
|
256
|
+
decorator: context.decorator,
|
|
257
|
+
editor: context.editor,
|
|
258
|
+
pair: context.pair
|
|
259
|
+
})
|
|
260
|
+
}],
|
|
235
261
|
on: {
|
|
236
262
|
"decorator.add": {
|
|
237
263
|
target: "decorator added",
|
|
238
264
|
actions: assign({
|
|
239
|
-
offsetAfterDecorator: ({
|
|
265
|
+
offsetAfterDecorator: ({
|
|
266
|
+
event
|
|
267
|
+
}) => event.blockOffset
|
|
240
268
|
})
|
|
241
269
|
}
|
|
242
270
|
}
|
|
243
271
|
},
|
|
244
272
|
"decorator added": {
|
|
245
|
-
exit: [
|
|
246
|
-
|
|
247
|
-
|
|
273
|
+
exit: [assign({
|
|
274
|
+
offsetAfterDecorator: void 0
|
|
275
|
+
})],
|
|
276
|
+
invoke: [{
|
|
277
|
+
src: "selection listener",
|
|
278
|
+
input: ({
|
|
279
|
+
context
|
|
280
|
+
}) => ({
|
|
281
|
+
editor: context.editor
|
|
248
282
|
})
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
{
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
input: ({ context }) => ({ editor: context.editor })
|
|
258
|
-
}
|
|
259
|
-
],
|
|
283
|
+
}, {
|
|
284
|
+
src: "delete.backward listener",
|
|
285
|
+
input: ({
|
|
286
|
+
context
|
|
287
|
+
}) => ({
|
|
288
|
+
editor: context.editor
|
|
289
|
+
})
|
|
290
|
+
}],
|
|
260
291
|
on: {
|
|
261
292
|
selection: {
|
|
262
293
|
target: "idle",
|
|
263
|
-
guard: ({
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
)
|
|
294
|
+
guard: ({
|
|
295
|
+
context,
|
|
296
|
+
event
|
|
297
|
+
}) => !isDeepEqual({
|
|
298
|
+
anchor: context.offsetAfterDecorator,
|
|
299
|
+
focus: context.offsetAfterDecorator
|
|
300
|
+
}, event.blockOffsets)
|
|
270
301
|
},
|
|
271
302
|
"delete.backward": {
|
|
272
303
|
target: "idle"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/regex.character-pair.ts","../src/behavior.character-pair-decorator.ts","../src/plugin.character-pair-decorator.ts"],"sourcesContent":["export function createCharacterPairRegex(char: string, amount: number) {\n // Negative lookbehind: Ensures that the matched sequence is not preceded by the same character\n const prePrefix = `(?<!\\\\${char})`\n\n // Repeats the character `amount` times\n const prefix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the opening pair (**, *, etc.) is not followed by a space\n const postPrefix = `(?!\\\\s)`\n\n // Captures the content inside the pair\n const content = `([^${char}\\\\n]+?)`\n\n // Negative lookbehind: Ensures that the content is not followed by a space\n const preSuffix = `(?<!\\\\s)`\n\n // Repeats the character `amount` times\n const suffix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the matched sequence is not followed by the same character\n const postSuffix = `(?!\\\\${char})`\n\n return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`\n}\n","import type {BlockOffset, EditorSchema} from '@portabletext/editor'\nimport {defineBehavior, effect, execute} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport * as utils from '@portabletext/editor/utils'\nimport {createCharacterPairRegex} from './regex.character-pair'\n\nexport function createCharacterPairDecoratorBehavior(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n onDecorate: (offset: BlockOffset) => void\n}) {\n if (config.pair.amount < 1) {\n console.warn(\n `The amount of characters in the pair should be greater than 0`,\n )\n }\n\n const pairRegex = createCharacterPairRegex(\n config.pair.char,\n config.pair.amount,\n )\n const regEx = new RegExp(`(${pairRegex})$`)\n\n return defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n if (config.pair.amount < 1) {\n return false\n }\n\n const decorator = config.decorator({schema: snapshot.context.schema})\n\n if (decorator === undefined) {\n return false\n }\n\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const selectionStartPoint = selectors.getSelectionStartPoint(snapshot)\n const selectionStartOffset = selectionStartPoint\n ? utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: selectionStartPoint,\n })\n : undefined\n\n if (!focusTextBlock || !selectionStartOffset) {\n return false\n }\n\n const textBefore = selectors.getBlockTextBefore(snapshot)\n const newText = `${textBefore}${event.text}`\n const textToDecorate = newText.match(regEx)?.at(0)\n\n if (textToDecorate === undefined) {\n return false\n }\n\n const prefixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length = 4\n offset: newText.length - textToDecorate.length,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length + \"*\".length * 2 = 6\n offset:\n newText.length -\n textToDecorate.length +\n config.pair.char.length * config.pair.amount,\n },\n }\n\n const suffixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length - 2 = 9\n offset:\n selectionStartOffset.offset +\n event.text.length -\n config.pair.char.length * config.pair.amount,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length = 11\n offset: selectionStartOffset.offset + event.text.length,\n },\n }\n\n // If the prefix is more than one character, then we need to check if\n // there is an inline object inside it\n if (prefixOffsets.focus.offset - prefixOffsets.anchor.offset > 1) {\n const prefixSelection = utils.blockOffsetsToSelection({\n context: snapshot.context,\n offsets: prefixOffsets,\n })\n const inlineObjectBeforePrefixFocus = selectors.getPreviousInlineObject(\n {\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: prefixSelection\n ? {\n anchor: prefixSelection.focus,\n focus: prefixSelection.focus,\n }\n : null,\n },\n },\n )\n const inlineObjectBeforePrefixFocusOffset =\n inlineObjectBeforePrefixFocus\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: inlineObjectBeforePrefixFocus.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n inlineObjectBeforePrefixFocusOffset &&\n inlineObjectBeforePrefixFocusOffset.offset >\n prefixOffsets.anchor.offset &&\n inlineObjectBeforePrefixFocusOffset.offset <\n prefixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n // If the suffix is more than one character, then we need to check if\n // there is an inline object inside it\n if (suffixOffsets.focus.offset - suffixOffsets.anchor.offset > 1) {\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const previousInlineObjectOffset = previousInlineObject\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: previousInlineObject.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n previousInlineObjectOffset &&\n previousInlineObjectOffset.offset > suffixOffsets.anchor.offset &&\n previousInlineObjectOffset.offset < suffixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n return {\n prefixOffsets,\n suffixOffsets,\n decorator,\n }\n },\n actions: [\n // Insert the text as usual in its own undo step\n ({event}) => [execute(event)],\n (_, {prefixOffsets, suffixOffsets, decorator}) => [\n // Decorate the text between the prefix and suffix\n execute({\n type: 'decorator.add',\n decorator,\n at: {\n anchor: prefixOffsets.focus,\n focus: suffixOffsets.anchor,\n },\n }),\n // Delete the suffix\n execute({\n type: 'delete.text',\n at: suffixOffsets,\n }),\n // Delete the prefix\n execute({\n type: 'delete.text',\n at: prefixOffsets,\n }),\n // Toggle the decorator off so the next inserted text isn't emphasized\n execute({\n type: 'decorator.remove',\n decorator,\n }),\n effect(() => {\n config.onDecorate({\n ...suffixOffsets.anchor,\n offset:\n suffixOffsets.anchor.offset -\n (prefixOffsets.focus.offset - prefixOffsets.anchor.offset),\n })\n }),\n ],\n ],\n })\n}\n","import type {BlockOffset, Editor, EditorSchema} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n execute,\n forward,\n} from '@portabletext/editor/behaviors'\nimport * as utils from '@portabletext/editor/utils'\nimport {useActorRef} from '@xstate/react'\nimport {isDeepEqual} from 'remeda'\nimport {\n assign,\n fromCallback,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport {createCharacterPairDecoratorBehavior} from './behavior.character-pair-decorator'\n\n/**\n * @beta\n */\nexport function CharacterPairDecoratorPlugin(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n}) {\n const editor = useEditor()\n\n useActorRef(decoratorPairMachine, {\n input: {\n editor,\n decorator: config.decorator,\n pair: config.pair,\n },\n })\n\n return null\n}\n\ntype DecoratorPairEvent =\n | {\n type: 'decorator.add'\n blockOffset: BlockOffset\n }\n | {\n type: 'selection'\n blockOffsets?: {\n anchor: BlockOffset\n focus: BlockOffset\n }\n }\n | {\n type: 'delete.backward'\n }\n\nconst decorateListener: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n }\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: createCharacterPairDecoratorBehavior({\n decorator: input.decorator,\n pair: input.pair,\n onDecorate: (offset) => {\n sendBack({type: 'decorator.add', blockOffset: offset})\n },\n }),\n })\n\n return unregister\n}\n\nconst selectionListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'select',\n guard: ({snapshot, event}) => {\n if (!event.at) {\n return {blockOffsets: undefined}\n }\n\n const anchor = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.anchor,\n })\n const focus = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.focus,\n })\n\n if (!anchor || !focus) {\n return {blockOffsets: undefined}\n }\n\n return {\n blockOffsets: {\n anchor,\n focus,\n },\n }\n },\n actions: [\n ({event}, {blockOffsets}) => [\n {\n type: 'effect',\n effect: () => {\n sendBack({type: 'selection', blockOffsets})\n },\n },\n forward(event),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst deleteBackwardListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'delete.backward',\n actions: [\n () => [\n execute({\n type: 'history.undo',\n }),\n effect(() => {\n sendBack({type: 'delete.backward'})\n }),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst decoratorPairMachine = setup({\n types: {\n context: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n offsetAfterDecorator?: BlockOffset\n pair: {char: string; amount: number}\n },\n input: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n },\n events: {} as DecoratorPairEvent,\n },\n actors: {\n 'decorate listener': fromCallback(decorateListener),\n 'delete.backward listener': fromCallback(deleteBackwardListenerCallback),\n 'selection listener': fromCallback(selectionListenerCallback),\n },\n}).createMachine({\n id: 'decorator pair',\n context: ({input}) => ({\n decorator: input.decorator,\n editor: input.editor,\n pair: input.pair,\n }),\n initial: 'idle',\n states: {\n 'idle': {\n invoke: [\n {\n src: 'decorate listener',\n input: ({context}) => ({\n decorator: context.decorator,\n editor: context.editor,\n pair: context.pair,\n }),\n },\n ],\n on: {\n 'decorator.add': {\n target: 'decorator added',\n actions: assign({\n offsetAfterDecorator: ({event}) => event.blockOffset,\n }),\n },\n },\n },\n 'decorator added': {\n exit: [\n assign({\n offsetAfterDecorator: undefined,\n }),\n ],\n invoke: [\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'delete.backward listener',\n input: ({context}) => ({editor: context.editor}),\n },\n ],\n on: {\n 'selection': {\n target: 'idle',\n guard: ({context, event}) => {\n const selectionChanged = !isDeepEqual(\n {\n anchor: context.offsetAfterDecorator,\n focus: context.offsetAfterDecorator,\n },\n event.blockOffsets,\n )\n\n return selectionChanged\n },\n },\n 'delete.backward': {\n target: 'idle',\n },\n },\n },\n },\n})\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/regex.character-pair.ts","../src/behavior.character-pair-decorator.ts","../src/plugin.character-pair-decorator.ts"],"sourcesContent":["export function createCharacterPairRegex(char: string, amount: number) {\n // Negative lookbehind: Ensures that the matched sequence is not preceded by the same character\n const prePrefix = `(?<!\\\\${char})`\n\n // Repeats the character `amount` times\n const prefix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the opening pair (**, *, etc.) is not followed by a space\n const postPrefix = `(?!\\\\s)`\n\n // Captures the content inside the pair\n const content = `([^${char}\\\\n]+?)`\n\n // Negative lookbehind: Ensures that the content is not followed by a space\n const preSuffix = `(?<!\\\\s)`\n\n // Repeats the character `amount` times\n const suffix = `\\\\${char}`.repeat(Math.max(amount, 1))\n\n // Negative lookahead: Ensures that the matched sequence is not followed by the same character\n const postSuffix = `(?!\\\\${char})`\n\n return `${prePrefix}${prefix}${postPrefix}${content}${preSuffix}${suffix}${postSuffix}`\n}\n","import type {BlockOffset, EditorSchema} from '@portabletext/editor'\nimport {defineBehavior, effect, execute} from '@portabletext/editor/behaviors'\nimport * as selectors from '@portabletext/editor/selectors'\nimport * as utils from '@portabletext/editor/utils'\nimport {createCharacterPairRegex} from './regex.character-pair'\n\nexport function createCharacterPairDecoratorBehavior(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n onDecorate: (offset: BlockOffset) => void\n}) {\n if (config.pair.amount < 1) {\n console.warn(\n `The amount of characters in the pair should be greater than 0`,\n )\n }\n\n const pairRegex = createCharacterPairRegex(\n config.pair.char,\n config.pair.amount,\n )\n const regEx = new RegExp(`(${pairRegex})$`)\n\n return defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event}) => {\n if (config.pair.amount < 1) {\n return false\n }\n\n const decorator = config.decorator({schema: snapshot.context.schema})\n\n if (decorator === undefined) {\n return false\n }\n\n const focusTextBlock = selectors.getFocusTextBlock(snapshot)\n const selectionStartPoint = selectors.getSelectionStartPoint(snapshot)\n const selectionStartOffset = selectionStartPoint\n ? utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: selectionStartPoint,\n })\n : undefined\n\n if (!focusTextBlock || !selectionStartOffset) {\n return false\n }\n\n const textBefore = selectors.getBlockTextBefore(snapshot)\n const newText = `${textBefore}${event.text}`\n const textToDecorate = newText.match(regEx)?.at(0)\n\n if (textToDecorate === undefined) {\n return false\n }\n\n const prefixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length = 4\n offset: newText.length - textToDecorate.length,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar**\".length - \"**bar**\".length + \"*\".length * 2 = 6\n offset:\n newText.length -\n textToDecorate.length +\n config.pair.char.length * config.pair.amount,\n },\n }\n\n const suffixOffsets = {\n anchor: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length - 2 = 9\n offset:\n selectionStartOffset.offset +\n event.text.length -\n config.pair.char.length * config.pair.amount,\n },\n focus: {\n path: focusTextBlock.path,\n // Example: \"foo **bar*|\" (10) + \"*\".length = 11\n offset: selectionStartOffset.offset + event.text.length,\n },\n }\n\n // If the prefix is more than one character, then we need to check if\n // there is an inline object inside it\n if (prefixOffsets.focus.offset - prefixOffsets.anchor.offset > 1) {\n const prefixSelection = utils.blockOffsetsToSelection({\n context: snapshot.context,\n offsets: prefixOffsets,\n })\n const inlineObjectBeforePrefixFocus = selectors.getPreviousInlineObject(\n {\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: prefixSelection\n ? {\n anchor: prefixSelection.focus,\n focus: prefixSelection.focus,\n }\n : null,\n },\n },\n )\n const inlineObjectBeforePrefixFocusOffset =\n inlineObjectBeforePrefixFocus\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: inlineObjectBeforePrefixFocus.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n inlineObjectBeforePrefixFocusOffset &&\n inlineObjectBeforePrefixFocusOffset.offset >\n prefixOffsets.anchor.offset &&\n inlineObjectBeforePrefixFocusOffset.offset <\n prefixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n // If the suffix is more than one character, then we need to check if\n // there is an inline object inside it\n if (suffixOffsets.focus.offset - suffixOffsets.anchor.offset > 1) {\n const previousInlineObject = selectors.getPreviousInlineObject(snapshot)\n const previousInlineObjectOffset = previousInlineObject\n ? utils.childSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: {\n path: previousInlineObject.path,\n offset: 0,\n },\n })\n : undefined\n\n if (\n previousInlineObjectOffset &&\n previousInlineObjectOffset.offset > suffixOffsets.anchor.offset &&\n previousInlineObjectOffset.offset < suffixOffsets.focus.offset\n ) {\n return false\n }\n }\n\n return {\n prefixOffsets,\n suffixOffsets,\n decorator,\n }\n },\n actions: [\n // Insert the text as usual in its own undo step\n ({event}) => [execute(event)],\n (_, {prefixOffsets, suffixOffsets, decorator}) => [\n // Decorate the text between the prefix and suffix\n execute({\n type: 'decorator.add',\n decorator,\n at: {\n anchor: prefixOffsets.focus,\n focus: suffixOffsets.anchor,\n },\n }),\n // Delete the suffix\n execute({\n type: 'delete.text',\n at: suffixOffsets,\n }),\n // Delete the prefix\n execute({\n type: 'delete.text',\n at: prefixOffsets,\n }),\n // Toggle the decorator off so the next inserted text isn't emphasized\n execute({\n type: 'decorator.remove',\n decorator,\n }),\n effect(() => {\n config.onDecorate({\n ...suffixOffsets.anchor,\n offset:\n suffixOffsets.anchor.offset -\n (prefixOffsets.focus.offset - prefixOffsets.anchor.offset),\n })\n }),\n ],\n ],\n })\n}\n","import type {BlockOffset, Editor, EditorSchema} from '@portabletext/editor'\nimport {useEditor} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n execute,\n forward,\n} from '@portabletext/editor/behaviors'\nimport * as utils from '@portabletext/editor/utils'\nimport {useActorRef} from '@xstate/react'\nimport {isDeepEqual} from 'remeda'\nimport {\n assign,\n fromCallback,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport {createCharacterPairDecoratorBehavior} from './behavior.character-pair-decorator'\n\n/**\n * @beta\n */\nexport function CharacterPairDecoratorPlugin(config: {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n pair: {char: string; amount: number}\n}) {\n const editor = useEditor()\n\n useActorRef(decoratorPairMachine, {\n input: {\n editor,\n decorator: config.decorator,\n pair: config.pair,\n },\n })\n\n return null\n}\n\ntype DecoratorPairEvent =\n | {\n type: 'decorator.add'\n blockOffset: BlockOffset\n }\n | {\n type: 'selection'\n blockOffsets?: {\n anchor: BlockOffset\n focus: BlockOffset\n }\n }\n | {\n type: 'delete.backward'\n }\n\nconst decorateListener: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n }\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: createCharacterPairDecoratorBehavior({\n decorator: input.decorator,\n pair: input.pair,\n onDecorate: (offset) => {\n sendBack({type: 'decorator.add', blockOffset: offset})\n },\n }),\n })\n\n return unregister\n}\n\nconst selectionListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'select',\n guard: ({snapshot, event}) => {\n if (!event.at) {\n return {blockOffsets: undefined}\n }\n\n const anchor = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.anchor,\n })\n const focus = utils.spanSelectionPointToBlockOffset({\n context: snapshot.context,\n selectionPoint: event.at.focus,\n })\n\n if (!anchor || !focus) {\n return {blockOffsets: undefined}\n }\n\n return {\n blockOffsets: {\n anchor,\n focus,\n },\n }\n },\n actions: [\n ({event}, {blockOffsets}) => [\n {\n type: 'effect',\n effect: () => {\n sendBack({type: 'selection', blockOffsets})\n },\n },\n forward(event),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst deleteBackwardListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n DecoratorPairEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'delete.backward',\n actions: [\n () => [\n execute({\n type: 'history.undo',\n }),\n effect(() => {\n sendBack({type: 'delete.backward'})\n }),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst decoratorPairMachine = setup({\n types: {\n context: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n offsetAfterDecorator?: BlockOffset\n pair: {char: string; amount: number}\n },\n input: {} as {\n decorator: ({schema}: {schema: EditorSchema}) => string | undefined\n editor: Editor\n pair: {char: string; amount: number}\n },\n events: {} as DecoratorPairEvent,\n },\n actors: {\n 'decorate listener': fromCallback(decorateListener),\n 'delete.backward listener': fromCallback(deleteBackwardListenerCallback),\n 'selection listener': fromCallback(selectionListenerCallback),\n },\n}).createMachine({\n id: 'decorator pair',\n context: ({input}) => ({\n decorator: input.decorator,\n editor: input.editor,\n pair: input.pair,\n }),\n initial: 'idle',\n states: {\n 'idle': {\n invoke: [\n {\n src: 'decorate listener',\n input: ({context}) => ({\n decorator: context.decorator,\n editor: context.editor,\n pair: context.pair,\n }),\n },\n ],\n on: {\n 'decorator.add': {\n target: 'decorator added',\n actions: assign({\n offsetAfterDecorator: ({event}) => event.blockOffset,\n }),\n },\n },\n },\n 'decorator added': {\n exit: [\n assign({\n offsetAfterDecorator: undefined,\n }),\n ],\n invoke: [\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'delete.backward listener',\n input: ({context}) => ({editor: context.editor}),\n },\n ],\n on: {\n 'selection': {\n target: 'idle',\n guard: ({context, event}) => {\n const selectionChanged = !isDeepEqual(\n {\n anchor: context.offsetAfterDecorator,\n focus: context.offsetAfterDecorator,\n },\n event.blockOffsets,\n )\n\n return selectionChanged\n },\n },\n 'delete.backward': {\n target: 'idle',\n },\n },\n },\n },\n})\n"],"names":["createCharacterPairRegex","char","amount","prePrefix","prefix","repeat","Math","max","postPrefix","content","preSuffix","suffix","postSuffix","createCharacterPairDecoratorBehavior","config","pair","console","warn","pairRegex","regEx","RegExp","defineBehavior","on","guard","snapshot","event","decorator","schema","context","undefined","focusTextBlock","selectors","getFocusTextBlock","selectionStartPoint","getSelectionStartPoint","selectionStartOffset","utils","spanSelectionPointToBlockOffset","selectionPoint","newText","getBlockTextBefore","text","textToDecorate","match","at","prefixOffsets","anchor","path","offset","length","focus","suffixOffsets","prefixSelection","blockOffsetsToSelection","offsets","inlineObjectBeforePrefixFocus","getPreviousInlineObject","selection","inlineObjectBeforePrefixFocusOffset","childSelectionPointToBlockOffset","previousInlineObject","previousInlineObjectOffset","actions","execute","_","type","effect","onDecorate","CharacterPairDecoratorPlugin","$","_c","editor","useEditor","t0","input","useActorRef","decoratorPairMachine","decorateListener","sendBack","registerBehavior","behavior","blockOffset","selectionListenerCallback","blockOffsets","forward","deleteBackwardListenerCallback","setup","types","events","actors","fromCallback","createMachine","id","initial","states","invoke","src","target","assign","offsetAfterDecorator","exit","isDeepEqual"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portabletext/plugin-character-pair-decorator",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Automatically match a pair of characters and decorate the text in between",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"portabletext",
|
|
@@ -41,11 +41,12 @@
|
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@portabletext/editor": "^2.4.1",
|
|
43
43
|
"@types/react": "^19.1.2",
|
|
44
|
+
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
|
44
45
|
"react": "^19.1.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
48
|
"@portabletext/editor": "^2.4.1",
|
|
48
|
-
"react": "^19
|
|
49
|
+
"react": "^19"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
51
52
|
"@xstate/react": "^6.0.0",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"scripts": {
|
|
56
57
|
"build": "pkg-utils build --strict --check --clean",
|
|
57
58
|
"check:lint": "biome lint .",
|
|
58
|
-
"check:react-compiler": "eslint
|
|
59
|
+
"check:react-compiler": "eslint .",
|
|
59
60
|
"check:types": "tsc",
|
|
60
61
|
"check:types:watch": "tsc --watch",
|
|
61
62
|
"clean": "del .turbo && del dist && del node_modules",
|