@portabletext/plugin-input-rule 0.4.4 → 0.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@portabletext/plugin-input-rule",
3
- "version": "0.4.4",
3
+ "version": "0.5.1",
4
4
  "description": "Easily configure input rules in the Portable Text Editor",
5
5
  "keywords": [
6
6
  "portabletext",
@@ -23,14 +23,11 @@
23
23
  "exports": {
24
24
  ".": {
25
25
  "source": "./src/index.ts",
26
- "import": "./dist/index.js",
27
- "require": "./dist/index.cjs",
28
26
  "default": "./dist/index.js"
29
27
  },
30
28
  "./package.json": "./package.json"
31
29
  },
32
- "main": "./dist/index.cjs",
33
- "module": "./dist/index.js",
30
+ "main": "./dist/index.js",
34
31
  "types": "./dist/index.d.ts",
35
32
  "files": [
36
33
  "dist",
@@ -42,11 +39,11 @@
42
39
  "xstate": "^5.23.0"
43
40
  },
44
41
  "devDependencies": {
45
- "@sanity/pkg-utils": "^8.1.4",
46
- "@types/react": "^19.2.0",
42
+ "@sanity/pkg-utils": "^9.0.1",
43
+ "@types/react": "^19.2.2",
47
44
  "@vitejs/plugin-react": "^5.0.4",
48
- "@vitest/browser": "^4.0.5",
49
- "@vitest/browser-playwright": "^4.0.5",
45
+ "@vitest/browser": "^4.0.6",
46
+ "@vitest/browser-playwright": "^4.0.6",
50
47
  "babel-plugin-react-compiler": "1.0.0",
51
48
  "eslint": "^9.38.0",
52
49
  "eslint-formatter-gha": "^1.6.0",
@@ -54,15 +51,18 @@
54
51
  "react": "^19.2.0",
55
52
  "typescript": "5.9.3",
56
53
  "typescript-eslint": "^8.46.1",
57
- "vitest": "^4.0.5",
58
- "@portabletext/editor": "2.17.2",
59
- "@portabletext/schema": "1.2.0",
60
- "racejar": "1.3.2"
54
+ "vitest": "^4.0.6",
55
+ "@portabletext/editor": "2.18.1",
56
+ "@portabletext/schema": "2.0.0",
57
+ "racejar": "2.0.0"
61
58
  },
62
59
  "peerDependencies": {
63
- "@portabletext/editor": "^2.17.2",
60
+ "@portabletext/editor": "^2.18.1",
64
61
  "react": "^19.1.1"
65
62
  },
63
+ "engines": {
64
+ "node": ">=20.19 <22 || >=22.12"
65
+ },
66
66
  "publishConfig": {
67
67
  "access": "public"
68
68
  },
package/dist/index.cjs DELETED
@@ -1,391 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var compilerRuntime = require("react/compiler-runtime"), editor = require("@portabletext/editor"), behaviors = require("@portabletext/editor/behaviors"), selectors = require("@portabletext/editor/selectors"), utils = require("@portabletext/editor/utils"), react = require("@xstate/react"), xstate = require("xstate");
4
- function defineInputRule(config) {
5
- return config;
6
- }
7
- function getInputRuleMatchLocation({
8
- match,
9
- adjustIndexBy,
10
- snapshot,
11
- focusTextBlock,
12
- originalTextBefore
13
- }) {
14
- const [text, start, end] = match, adjustedIndex = start + adjustIndexBy, targetOffsets = {
15
- anchor: {
16
- path: focusTextBlock.path,
17
- offset: adjustedIndex
18
- },
19
- focus: {
20
- path: focusTextBlock.path,
21
- offset: adjustedIndex + end - start
22
- },
23
- backward: !1
24
- }, normalizedOffsets = {
25
- anchor: {
26
- path: focusTextBlock.path,
27
- offset: Math.min(targetOffsets.anchor.offset, originalTextBefore.length)
28
- },
29
- focus: {
30
- path: focusTextBlock.path,
31
- offset: Math.min(targetOffsets.focus.offset, originalTextBefore.length)
32
- }
33
- }, anchorBackwards = utils.blockOffsetToSpanSelectionPoint({
34
- context: snapshot.context,
35
- blockOffset: normalizedOffsets.anchor,
36
- direction: "backward"
37
- }), focusForwards = utils.blockOffsetToSpanSelectionPoint({
38
- context: snapshot.context,
39
- blockOffset: normalizedOffsets.focus,
40
- direction: "forward"
41
- });
42
- if (!anchorBackwards || !focusForwards)
43
- return;
44
- const selection = {
45
- anchor: anchorBackwards,
46
- focus: focusForwards
47
- }, inlineObjectsAfterMatch = selectors.getNextInlineObjects({
48
- ...snapshot,
49
- context: {
50
- ...snapshot.context,
51
- selection: {
52
- anchor: selection.anchor,
53
- focus: selection.anchor
54
- }
55
- }
56
- }), inlineObjectsBefore = selectors.getPreviousInlineObjects(snapshot);
57
- if (!inlineObjectsAfterMatch.some((inlineObjectAfter) => inlineObjectsBefore.some((inlineObjectBefore) => inlineObjectAfter.node._key === inlineObjectBefore.node._key)))
58
- return {
59
- text,
60
- selection,
61
- targetOffsets
62
- };
63
- }
64
- function defineInputRuleBehavior(config) {
65
- return behaviors.defineBehavior({
66
- on: "insert.text",
67
- guard: ({
68
- snapshot,
69
- event,
70
- dom
71
- }) => {
72
- if (!snapshot.context.selection || !utils.isSelectionCollapsed(snapshot.context.selection))
73
- return !1;
74
- const focusTextBlock = selectors.getFocusTextBlock(snapshot);
75
- if (!focusTextBlock)
76
- return !1;
77
- const originalTextBefore = selectors.getBlockTextBefore(snapshot);
78
- let textBefore = originalTextBefore;
79
- const originalNewText = textBefore + event.text;
80
- let newText = originalNewText;
81
- const foundMatches = [], foundActions = [];
82
- for (const rule of config.rules) {
83
- const matcher = new RegExp(rule.on.source, "gd");
84
- for (; ; ) {
85
- const ruleMatches = [...newText.matchAll(matcher)].flatMap((regExpMatch) => {
86
- if (regExpMatch.indices === void 0)
87
- return [];
88
- const match = regExpMatch.indices.at(0);
89
- if (!match)
90
- return [];
91
- const matchLocation = getInputRuleMatchLocation({
92
- match: [regExpMatch.at(0) ?? "", ...match],
93
- adjustIndexBy: originalNewText.length - newText.length,
94
- snapshot,
95
- focusTextBlock,
96
- originalTextBefore
97
- });
98
- if (!matchLocation)
99
- return [];
100
- if (matchLocation.targetOffsets.focus.offset <= originalTextBefore.length)
101
- return [];
102
- if (foundMatches.some((foundMatch) => foundMatch.targetOffsets.anchor.offset === matchLocation.targetOffsets.anchor.offset))
103
- return [];
104
- const groupMatches = regExpMatch.indices.length > 1 ? regExpMatch.indices.slice(1).filter((indices) => indices !== void 0) : [];
105
- return [{
106
- text: matchLocation.text,
107
- selection: matchLocation.selection,
108
- targetOffsets: matchLocation.targetOffsets,
109
- groupMatches: groupMatches.flatMap((match2, index) => {
110
- const text = regExpMatch.at(index + 1) ?? "";
111
- return getInputRuleMatchLocation({
112
- match: [text, ...match2],
113
- adjustIndexBy: originalNewText.length - newText.length,
114
- snapshot,
115
- focusTextBlock,
116
- originalTextBefore
117
- }) || [];
118
- })
119
- }];
120
- });
121
- if (ruleMatches.length > 0) {
122
- const guardResult = rule.guard?.({
123
- snapshot,
124
- event: {
125
- type: "custom.input rule",
126
- matches: ruleMatches,
127
- focusTextBlock,
128
- textBefore: originalTextBefore,
129
- textInserted: event.text
130
- },
131
- dom
132
- }) ?? !0;
133
- if (!guardResult)
134
- break;
135
- const actionSets = rule.actions.map((action) => action({
136
- snapshot,
137
- event: {
138
- type: "custom.input rule",
139
- matches: ruleMatches,
140
- focusTextBlock,
141
- textBefore: originalTextBefore,
142
- textInserted: event.text
143
- },
144
- dom
145
- }, guardResult));
146
- for (const actionSet of actionSets)
147
- for (const action of actionSet)
148
- foundActions.push(action);
149
- const matches = ruleMatches.flatMap((match) => match.groupMatches.length === 0 ? [match] : match.groupMatches);
150
- for (const match of matches)
151
- foundMatches.push(match), textBefore = newText.slice(0, match.targetOffsets.focus.offset ?? 0), newText = originalNewText.slice(match.targetOffsets.focus.offset ?? 0);
152
- } else
153
- break;
154
- }
155
- }
156
- return foundActions.length === 0 ? !1 : {
157
- actions: foundActions
158
- };
159
- },
160
- actions: [({
161
- event
162
- }) => [behaviors.forward(event)], (_, {
163
- actions
164
- }) => actions, ({
165
- snapshot
166
- }) => [behaviors.effect(() => {
167
- const blockOffsets = selectors.getBlockOffsets(snapshot);
168
- config.onApply?.({
169
- endOffsets: blockOffsets
170
- });
171
- })]]
172
- });
173
- }
174
- function InputRulePlugin(props) {
175
- const $ = compilerRuntime.c(3), editor$1 = editor.useEditor();
176
- let t0;
177
- return $[0] !== editor$1 || $[1] !== props.rules ? (t0 = {
178
- input: {
179
- editor: editor$1,
180
- rules: props.rules
181
- }
182
- }, $[0] = editor$1, $[1] = props.rules, $[2] = t0) : t0 = $[2], react.useActorRef(inputRuleMachine, t0), null;
183
- }
184
- const inputRuleListenerCallback = ({
185
- input,
186
- sendBack
187
- }) => {
188
- const unregister = input.editor.registerBehavior({
189
- behavior: defineInputRuleBehavior({
190
- rules: input.rules,
191
- onApply: ({
192
- endOffsets
193
- }) => {
194
- sendBack({
195
- type: "input rule raised",
196
- endOffsets
197
- });
198
- }
199
- })
200
- });
201
- return () => {
202
- unregister();
203
- };
204
- }, deleteBackwardListenerCallback = ({
205
- input,
206
- sendBack
207
- }) => input.editor.registerBehavior({
208
- behavior: behaviors.defineBehavior({
209
- on: "delete.backward",
210
- actions: [() => [behaviors.raise({
211
- type: "history.undo"
212
- }), behaviors.effect(() => {
213
- sendBack({
214
- type: "history.undo raised"
215
- });
216
- })]]
217
- })
218
- }), selectionListenerCallback = ({
219
- sendBack,
220
- input
221
- }) => input.editor.registerBehavior({
222
- behavior: behaviors.defineBehavior({
223
- on: "select",
224
- guard: ({
225
- snapshot,
226
- event
227
- }) => ({
228
- blockOffsets: selectors.getBlockOffsets({
229
- ...snapshot,
230
- context: {
231
- ...snapshot.context,
232
- selection: event.at
233
- }
234
- })
235
- }),
236
- actions: [({
237
- event
238
- }, {
239
- blockOffsets
240
- }) => [behaviors.effect(() => {
241
- sendBack({
242
- type: "selection changed",
243
- blockOffsets
244
- });
245
- }), behaviors.forward(event)]]
246
- })
247
- }), inputRuleSetup = xstate.setup({
248
- types: {
249
- context: {},
250
- input: {},
251
- events: {}
252
- },
253
- actors: {
254
- "delete.backward listener": xstate.fromCallback(deleteBackwardListenerCallback),
255
- "input rule listener": xstate.fromCallback(inputRuleListenerCallback),
256
- "selection listener": xstate.fromCallback(selectionListenerCallback)
257
- },
258
- guards: {
259
- "block offset changed": ({
260
- context,
261
- event
262
- }) => {
263
- if (event.type !== "selection changed")
264
- return !1;
265
- if (!event.blockOffsets || !context.endOffsets)
266
- return !0;
267
- const startChanged = context.endOffsets.start.path[0]._key !== event.blockOffsets.start.path[0]._key || context.endOffsets.start.offset !== event.blockOffsets.start.offset, endChanged = context.endOffsets.end.path[0]._key !== event.blockOffsets.end.path[0]._key || context.endOffsets.end.offset !== event.blockOffsets.end.offset;
268
- return startChanged || endChanged;
269
- }
270
- }
271
- }), assignEndOffsets = inputRuleSetup.assign({
272
- endOffsets: ({
273
- context,
274
- event
275
- }) => event.type === "input rule raised" ? event.endOffsets : context.endOffsets
276
- }), inputRuleMachine = inputRuleSetup.createMachine({
277
- id: "input rule",
278
- context: ({
279
- input
280
- }) => ({
281
- editor: input.editor,
282
- rules: input.rules,
283
- endOffsets: void 0
284
- }),
285
- initial: "idle",
286
- invoke: {
287
- src: "input rule listener",
288
- input: ({
289
- context
290
- }) => ({
291
- editor: context.editor,
292
- rules: context.rules
293
- })
294
- },
295
- on: {
296
- "input rule raised": {
297
- target: ".input rule applied",
298
- actions: assignEndOffsets
299
- }
300
- },
301
- states: {
302
- idle: {},
303
- "input rule applied": {
304
- invoke: [{
305
- src: "delete.backward listener",
306
- input: ({
307
- context
308
- }) => ({
309
- editor: context.editor
310
- })
311
- }, {
312
- src: "selection listener",
313
- input: ({
314
- context
315
- }) => ({
316
- editor: context.editor
317
- })
318
- }],
319
- on: {
320
- "selection changed": {
321
- target: "idle",
322
- guard: "block offset changed"
323
- },
324
- "history.undo raised": {
325
- target: "idle"
326
- }
327
- }
328
- }
329
- }
330
- });
331
- function defineTextTransformRule(config) {
332
- return {
333
- on: config.on,
334
- guard: config.guard ?? (() => !0),
335
- actions: [({
336
- snapshot,
337
- event
338
- }, guardResponse) => {
339
- const locations = event.matches.flatMap((match) => match.groupMatches.length === 0 ? [match] : match.groupMatches), newText = event.textBefore + event.textInserted;
340
- let textLengthDelta = 0;
341
- const actions = [];
342
- for (const location of locations.reverse()) {
343
- const text = config.transform({
344
- location
345
- }, guardResponse);
346
- textLengthDelta = textLengthDelta - (text.length - (location.targetOffsets.focus.offset - location.targetOffsets.anchor.offset)), actions.push(behaviors.raise({
347
- type: "select",
348
- at: location.targetOffsets
349
- })), actions.push(behaviors.raise({
350
- type: "delete",
351
- at: location.targetOffsets
352
- })), actions.push(behaviors.raise({
353
- type: "insert.child",
354
- child: {
355
- _type: snapshot.context.schema.span.name,
356
- text,
357
- marks: selectors.getMarkState({
358
- ...snapshot,
359
- context: {
360
- ...snapshot.context,
361
- selection: {
362
- anchor: location.selection.anchor,
363
- focus: {
364
- path: location.selection.focus.path,
365
- offset: Math.min(location.selection.focus.offset, event.textBefore.length)
366
- }
367
- }
368
- }
369
- })?.marks ?? []
370
- }
371
- }));
372
- }
373
- const endCaretPosition = {
374
- path: event.focusTextBlock.path,
375
- offset: newText.length - textLengthDelta
376
- };
377
- return [...actions, behaviors.raise({
378
- type: "select",
379
- at: {
380
- anchor: endCaretPosition,
381
- focus: endCaretPosition
382
- }
383
- })];
384
- }]
385
- };
386
- }
387
- exports.InputRulePlugin = InputRulePlugin;
388
- exports.defineInputRule = defineInputRule;
389
- exports.defineInputRuleBehavior = defineInputRuleBehavior;
390
- exports.defineTextTransformRule = defineTextTransformRule;
391
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/input-rule.ts","../src/input-rule-match-location.ts","../src/plugin.input-rule.tsx","../src/text-transform-rule.ts"],"sourcesContent":["import type {BlockPath, PortableTextTextBlock} from '@portabletext/editor'\nimport type {\n BehaviorActionSet,\n BehaviorGuard,\n} from '@portabletext/editor/behaviors'\nimport type {InputRuleMatchLocation} from './input-rule-match-location'\n\n/**\n * Match found in the text after the insertion\n * @alpha\n */\nexport type InputRuleMatch = InputRuleMatchLocation & {\n groupMatches: Array<InputRuleMatchLocation>\n}\n\n/**\n * @alpha\n */\nexport type InputRuleEvent = {\n type: 'custom.input rule'\n /**\n * Matches found by the input rule\n */\n matches: Array<InputRuleMatch>\n /**\n * The text before the insertion\n */\n textBefore: string\n /**\n * The text is destined to be inserted\n */\n textInserted: string\n /**\n * The text block where the insertion takes place\n */\n focusTextBlock: {\n path: BlockPath\n node: PortableTextTextBlock\n }\n}\n\n/**\n * @alpha\n */\nexport type InputRuleGuard<TGuardResponse = true> = BehaviorGuard<\n InputRuleEvent,\n TGuardResponse\n>\n\n/**\n * @alpha\n */\nexport type InputRule<TGuardResponse = true> = {\n on: RegExp\n guard?: InputRuleGuard<TGuardResponse>\n actions: Array<BehaviorActionSet<InputRuleEvent, TGuardResponse>>\n}\n\n/**\n * @alpha\n */\nexport function defineInputRule<TGuardResponse = true>(\n config: InputRule<TGuardResponse>,\n): InputRule<TGuardResponse> {\n return config\n}\n","import type {\n BlockOffset,\n BlockPath,\n EditorSelection,\n EditorSnapshot,\n} from '@portabletext/editor'\nimport {\n getNextInlineObjects,\n getPreviousInlineObjects,\n} from '@portabletext/editor/selectors'\nimport {blockOffsetToSpanSelectionPoint} from '@portabletext/editor/utils'\n\nexport type InputRuleMatchLocation = {\n /**\n * The matched text\n */\n text: string\n /**\n * Estimated selection of where in the original text the match is located.\n * The selection is estimated since the match is found in the text after\n * insertion.\n */\n selection: NonNullable<EditorSelection>\n /**\n * Block offsets of the match in the text after the insertion\n */\n targetOffsets: {\n anchor: BlockOffset\n focus: BlockOffset\n backward: boolean\n }\n}\n\nexport function getInputRuleMatchLocation({\n match,\n adjustIndexBy,\n snapshot,\n focusTextBlock,\n originalTextBefore,\n}: {\n match: [string, number, number]\n adjustIndexBy: number\n snapshot: EditorSnapshot\n focusTextBlock: {\n path: BlockPath\n }\n originalTextBefore: string\n}): InputRuleMatchLocation | undefined {\n const [text, start, end] = match\n const adjustedIndex = start + adjustIndexBy\n\n const targetOffsets = {\n anchor: {\n path: focusTextBlock.path,\n offset: adjustedIndex,\n },\n focus: {\n path: focusTextBlock.path,\n offset: adjustedIndex + end - start,\n },\n backward: false,\n }\n const normalizedOffsets = {\n anchor: {\n path: focusTextBlock.path,\n offset: Math.min(targetOffsets.anchor.offset, originalTextBefore.length),\n },\n focus: {\n path: focusTextBlock.path,\n offset: Math.min(targetOffsets.focus.offset, originalTextBefore.length),\n },\n backward: false,\n }\n\n const anchorBackwards = blockOffsetToSpanSelectionPoint({\n context: snapshot.context,\n blockOffset: normalizedOffsets.anchor,\n direction: 'backward',\n })\n const focusForwards = blockOffsetToSpanSelectionPoint({\n context: snapshot.context,\n blockOffset: normalizedOffsets.focus,\n direction: 'forward',\n })\n\n if (!anchorBackwards || !focusForwards) {\n return undefined\n }\n\n const selection = {\n anchor: anchorBackwards,\n focus: focusForwards,\n }\n\n const inlineObjectsAfterMatch = getNextInlineObjects({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: selection.anchor,\n focus: selection.anchor,\n },\n },\n })\n const inlineObjectsBefore = getPreviousInlineObjects(snapshot)\n\n if (\n inlineObjectsAfterMatch.some((inlineObjectAfter) =>\n inlineObjectsBefore.some(\n (inlineObjectBefore) =>\n inlineObjectAfter.node._key === inlineObjectBefore.node._key,\n ),\n )\n ) {\n return undefined\n }\n\n return {\n text,\n selection,\n targetOffsets,\n }\n}\n","import {useEditor, type BlockOffset, type Editor} from '@portabletext/editor'\nimport {\n defineBehavior,\n effect,\n forward,\n raise,\n type BehaviorAction,\n} from '@portabletext/editor/behaviors'\nimport {\n getBlockOffsets,\n getBlockTextBefore,\n getFocusTextBlock,\n} from '@portabletext/editor/selectors'\nimport {isSelectionCollapsed} from '@portabletext/editor/utils'\nimport {useActorRef} from '@xstate/react'\nimport {\n fromCallback,\n setup,\n type AnyEventObject,\n type CallbackLogicFunction,\n} from 'xstate'\nimport type {InputRule, InputRuleMatch} from './input-rule'\nimport {getInputRuleMatchLocation} from './input-rule-match-location'\n\n/**\n * @alpha\n */\nexport function defineInputRuleBehavior(config: {\n rules: Array<InputRule<any>>\n onApply?: ({\n endOffsets,\n }: {\n endOffsets: {start: BlockOffset; end: BlockOffset} | undefined\n }) => void\n}) {\n return defineBehavior({\n on: 'insert.text',\n guard: ({snapshot, event, dom}) => {\n if (\n !snapshot.context.selection ||\n !isSelectionCollapsed(snapshot.context.selection)\n ) {\n return false\n }\n\n const focusTextBlock = getFocusTextBlock(snapshot)\n\n if (!focusTextBlock) {\n return false\n }\n\n const originalTextBefore = getBlockTextBefore(snapshot)\n let textBefore = originalTextBefore\n const originalNewText = textBefore + event.text\n let newText = originalNewText\n\n const foundMatches: Array<InputRuleMatch['groupMatches'][number]> = []\n const foundActions: Array<BehaviorAction> = []\n\n for (const rule of config.rules) {\n const matcher = new RegExp(rule.on.source, 'gd')\n\n while (true) {\n // Find matches in the text after the insertion\n const ruleMatches = [...newText.matchAll(matcher)].flatMap(\n (regExpMatch) => {\n if (regExpMatch.indices === undefined) {\n return []\n }\n\n const match = regExpMatch.indices.at(0)\n\n if (!match) {\n return []\n }\n\n const matchLocation = getInputRuleMatchLocation({\n match: [regExpMatch.at(0) ?? '', ...match],\n adjustIndexBy: originalNewText.length - newText.length,\n snapshot,\n focusTextBlock,\n originalTextBefore,\n })\n\n if (!matchLocation) {\n return []\n }\n\n const existsInTextBefore =\n matchLocation.targetOffsets.focus.offset <=\n originalTextBefore.length\n\n // Ignore if this match occurs in the text before the insertion\n if (existsInTextBefore) {\n return []\n }\n\n const alreadyFound = foundMatches.some(\n (foundMatch) =>\n foundMatch.targetOffsets.anchor.offset ===\n matchLocation.targetOffsets.anchor.offset,\n )\n\n // Ignore if this match has already been found\n if (alreadyFound) {\n return []\n }\n\n const groupMatches =\n regExpMatch.indices.length > 1\n ? regExpMatch.indices\n .slice(1)\n .filter((indices) => indices !== undefined)\n : []\n\n const ruleMatch = {\n text: matchLocation.text,\n selection: matchLocation.selection,\n targetOffsets: matchLocation.targetOffsets,\n groupMatches: groupMatches.flatMap((match, index) => {\n const text = regExpMatch.at(index + 1) ?? ''\n const groupMatchLocation = getInputRuleMatchLocation({\n match: [text, ...match],\n adjustIndexBy: originalNewText.length - newText.length,\n snapshot,\n focusTextBlock,\n originalTextBefore,\n })\n\n if (!groupMatchLocation) {\n return []\n }\n\n return groupMatchLocation\n }),\n }\n\n return [ruleMatch]\n },\n )\n\n if (ruleMatches.length > 0) {\n const guardResult =\n rule.guard?.({\n snapshot,\n event: {\n type: 'custom.input rule',\n matches: ruleMatches,\n focusTextBlock,\n textBefore: originalTextBefore,\n textInserted: event.text,\n },\n dom,\n }) ?? true\n\n if (!guardResult) {\n break\n }\n\n const actionSets = rule.actions.map((action) =>\n action(\n {\n snapshot,\n event: {\n type: 'custom.input rule',\n matches: ruleMatches,\n focusTextBlock,\n textBefore: originalTextBefore,\n textInserted: event.text,\n },\n dom,\n },\n guardResult,\n ),\n )\n\n for (const actionSet of actionSets) {\n for (const action of actionSet) {\n foundActions.push(action)\n }\n }\n\n const matches = ruleMatches.flatMap((match) =>\n match.groupMatches.length === 0 ? [match] : match.groupMatches,\n )\n\n for (const match of matches) {\n // Remember each match and adjust `textBefore` and `newText` so\n // no subsequent matches can overlap with this one\n foundMatches.push(match)\n textBefore = newText.slice(\n 0,\n match.targetOffsets.focus.offset ?? 0,\n )\n newText = originalNewText.slice(\n match.targetOffsets.focus.offset ?? 0,\n )\n }\n } else {\n // If no match was found, break out of the loop to try the next\n // rule\n break\n }\n }\n }\n\n if (foundActions.length === 0) {\n return false\n }\n\n return {actions: foundActions}\n },\n actions: [\n ({event}) => [forward(event)],\n (_, {actions}) => actions,\n ({snapshot}) => [\n effect(() => {\n const blockOffsets = getBlockOffsets(snapshot)\n\n config.onApply?.({endOffsets: blockOffsets})\n }),\n ],\n ],\n })\n}\n\ntype InputRulePluginProps = {\n rules: Array<InputRule<any>>\n}\n\n/**\n * Turn an array of `InputRule`s into a Behavior that can be used to apply the\n * rules to the editor.\n *\n * The plugin handles undo/redo out of the box including smart undo with\n * Backspace.\n *\n * @example\n * ```tsx\n * <InputRulePlugin rules={smartQuotesRules} />\n * ```\n *\n * @alpha\n */\nexport function InputRulePlugin(props: InputRulePluginProps) {\n const editor = useEditor()\n\n useActorRef(inputRuleMachine, {\n input: {editor, rules: props.rules},\n })\n\n return null\n}\n\ntype InputRuleMachineEvent =\n | {\n type: 'input rule raised'\n endOffsets: {start: BlockOffset; end: BlockOffset} | undefined\n }\n | {type: 'history.undo raised'}\n | {\n type: 'selection changed'\n blockOffsets: {start: BlockOffset; end: BlockOffset} | undefined\n }\n\nconst inputRuleListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n InputRuleMachineEvent,\n {\n editor: Editor\n rules: Array<InputRule>\n }\n> = ({input, sendBack}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineInputRuleBehavior({\n rules: input.rules,\n onApply: ({endOffsets}) => {\n sendBack({type: 'input rule raised', endOffsets})\n },\n }),\n })\n\n return () => {\n unregister()\n }\n}\n\nconst deleteBackwardListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n InputRuleMachineEvent,\n {editor: Editor}\n> = ({input, sendBack}) => {\n return input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'delete.backward',\n actions: [\n () => [\n raise({type: 'history.undo'}),\n effect(() => {\n sendBack({type: 'history.undo raised'})\n }),\n ],\n ],\n }),\n })\n}\n\nconst selectionListenerCallback: CallbackLogicFunction<\n AnyEventObject,\n InputRuleMachineEvent,\n {editor: Editor}\n> = ({sendBack, input}) => {\n const unregister = input.editor.registerBehavior({\n behavior: defineBehavior({\n on: 'select',\n guard: ({snapshot, event}) => {\n const blockOffsets = getBlockOffsets({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: event.at,\n },\n })\n\n return {blockOffsets}\n },\n actions: [\n ({event}, {blockOffsets}) => [\n effect(() => {\n sendBack({type: 'selection changed', blockOffsets})\n }),\n forward(event),\n ],\n ],\n }),\n })\n\n return unregister\n}\n\nconst inputRuleSetup = setup({\n types: {\n context: {} as {\n editor: Editor\n rules: Array<InputRule>\n endOffsets: {start: BlockOffset; end: BlockOffset} | undefined\n },\n input: {} as {\n editor: Editor\n rules: Array<InputRule>\n },\n events: {} as InputRuleMachineEvent,\n },\n actors: {\n 'delete.backward listener': fromCallback(deleteBackwardListenerCallback),\n 'input rule listener': fromCallback(inputRuleListenerCallback),\n 'selection listener': fromCallback(selectionListenerCallback),\n },\n guards: {\n 'block offset changed': ({context, event}) => {\n if (event.type !== 'selection changed') {\n return false\n }\n\n if (!event.blockOffsets || !context.endOffsets) {\n return true\n }\n\n const startChanged =\n context.endOffsets.start.path[0]._key !==\n event.blockOffsets.start.path[0]._key ||\n context.endOffsets.start.offset !== event.blockOffsets.start.offset\n const endChanged =\n context.endOffsets.end.path[0]._key !==\n event.blockOffsets.end.path[0]._key ||\n context.endOffsets.end.offset !== event.blockOffsets.end.offset\n\n return startChanged || endChanged\n },\n },\n})\n\nconst assignEndOffsets = inputRuleSetup.assign({\n endOffsets: ({context, event}) =>\n event.type === 'input rule raised' ? event.endOffsets : context.endOffsets,\n})\n\nconst inputRuleMachine = inputRuleSetup.createMachine({\n id: 'input rule',\n context: ({input}) => ({\n editor: input.editor,\n rules: input.rules,\n endOffsets: undefined,\n }),\n initial: 'idle',\n invoke: {\n src: 'input rule listener',\n input: ({context}) => ({\n editor: context.editor,\n rules: context.rules,\n }),\n },\n on: {\n 'input rule raised': {\n target: '.input rule applied',\n actions: assignEndOffsets,\n },\n },\n states: {\n 'idle': {},\n 'input rule applied': {\n invoke: [\n {\n src: 'delete.backward listener',\n input: ({context}) => ({editor: context.editor}),\n },\n {\n src: 'selection listener',\n input: ({context}) => ({editor: context.editor}),\n },\n ],\n on: {\n 'selection changed': {\n target: 'idle',\n guard: 'block offset changed',\n },\n 'history.undo raised': {\n target: 'idle',\n },\n },\n },\n },\n})\n","import {raise, type BehaviorAction} from '@portabletext/editor/behaviors'\nimport {getMarkState} from '@portabletext/editor/selectors'\nimport type {InputRule, InputRuleGuard} from './input-rule'\nimport type {InputRuleMatchLocation} from './input-rule-match-location'\n\n/**\n * @alpha\n */\nexport type TextTransformRule<TGuardResponse = true> = {\n on: RegExp\n guard?: InputRuleGuard<TGuardResponse>\n transform: (\n {location}: {location: InputRuleMatchLocation},\n guardResponse: TGuardResponse,\n ) => string\n}\n\n/**\n * Define an `InputRule` specifically designed to transform matched text into\n * some other text.\n *\n * @example\n * ```tsx\n * const transformRule = defineTextTransformRule({\n * on: /--/,\n * transform: () => '—',\n * })\n * ```\n *\n * @alpha\n */\nexport function defineTextTransformRule<TGuardResponse = true>(\n config: TextTransformRule<TGuardResponse>,\n): InputRule<TGuardResponse> {\n return {\n on: config.on,\n guard: config.guard ?? (() => true as TGuardResponse),\n actions: [\n ({snapshot, event}, guardResponse) => {\n const locations = event.matches.flatMap((match) =>\n match.groupMatches.length === 0 ? [match] : match.groupMatches,\n )\n const newText = event.textBefore + event.textInserted\n\n let textLengthDelta = 0\n const actions: Array<BehaviorAction> = []\n\n for (const location of locations.reverse()) {\n const text = config.transform({location}, guardResponse)\n\n textLengthDelta =\n textLengthDelta -\n (text.length -\n (location.targetOffsets.focus.offset -\n location.targetOffsets.anchor.offset))\n\n actions.push(raise({type: 'select', at: location.targetOffsets}))\n actions.push(raise({type: 'delete', at: location.targetOffsets}))\n actions.push(\n raise({\n type: 'insert.child',\n child: {\n _type: snapshot.context.schema.span.name,\n text,\n marks:\n getMarkState({\n ...snapshot,\n context: {\n ...snapshot.context,\n selection: {\n anchor: location.selection.anchor,\n focus: {\n path: location.selection.focus.path,\n offset: Math.min(\n location.selection.focus.offset,\n event.textBefore.length,\n ),\n },\n },\n },\n })?.marks ?? [],\n },\n }),\n )\n }\n\n const endCaretPosition = {\n path: event.focusTextBlock.path,\n offset: newText.length - textLengthDelta,\n }\n\n return [\n ...actions,\n raise({\n type: 'select',\n at: {\n anchor: endCaretPosition,\n focus: endCaretPosition,\n },\n }),\n ]\n },\n ],\n }\n}\n"],"names":["defineInputRule","config","getInputRuleMatchLocation","match","adjustIndexBy","snapshot","focusTextBlock","originalTextBefore","text","start","end","adjustedIndex","targetOffsets","anchor","path","offset","focus","backward","normalizedOffsets","Math","min","length","anchorBackwards","blockOffsetToSpanSelectionPoint","context","blockOffset","direction","focusForwards","selection","inlineObjectsAfterMatch","getNextInlineObjects","inlineObjectsBefore","getPreviousInlineObjects","some","inlineObjectAfter","inlineObjectBefore","node","_key","defineInputRuleBehavior","defineBehavior","on","guard","event","dom","isSelectionCollapsed","getFocusTextBlock","getBlockTextBefore","textBefore","originalNewText","newText","foundMatches","foundActions","rule","rules","matcher","RegExp","source","ruleMatches","matchAll","flatMap","regExpMatch","indices","undefined","at","matchLocation","foundMatch","groupMatches","slice","filter","index","guardResult","type","matches","textInserted","actionSets","actions","map","action","actionSet","push","forward","_","effect","blockOffsets","getBlockOffsets","onApply","endOffsets","InputRulePlugin","props","$","_c","editor","useEditor","t0","input","useActorRef","inputRuleMachine","inputRuleListenerCallback","sendBack","unregister","registerBehavior","behavior","deleteBackwardListenerCallback","raise","selectionListenerCallback","inputRuleSetup","setup","types","events","actors","fromCallback","guards","block offset changed","startChanged","endChanged","assignEndOffsets","assign","createMachine","id","initial","invoke","src","target","states","defineTextTransformRule","guardResponse","locations","textLengthDelta","location","reverse","transform","child","_type","schema","span","name","marks","getMarkState","endCaretPosition"],"mappings":"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"}
package/dist/index.d.cts DELETED
@@ -1,253 +0,0 @@
1
- import {BlockOffset} from '@portabletext/editor'
2
- import type {
3
- BlockPath,
4
- EditorSelection,
5
- PortableTextTextBlock,
6
- } from '@portabletext/editor'
7
- import {Behavior, BehaviorEvent} from '@portabletext/editor/behaviors'
8
- import type {
9
- BehaviorActionSet,
10
- BehaviorGuard,
11
- } from '@portabletext/editor/behaviors'
12
-
13
- /**
14
- * @alpha
15
- */
16
- export declare function defineInputRule<TGuardResponse = true>(
17
- config: InputRule<TGuardResponse>,
18
- ): InputRule<TGuardResponse>
19
-
20
- /**
21
- * @alpha
22
- */
23
- export declare function defineInputRuleBehavior(config: {
24
- rules: Array<InputRule<any>>
25
- onApply?: ({
26
- endOffsets,
27
- }: {
28
- endOffsets:
29
- | {
30
- start: BlockOffset
31
- end: BlockOffset
32
- }
33
- | undefined
34
- }) => void
35
- }): Behavior<
36
- | '*'
37
- | 'insert.text'
38
- | 'annotation.add'
39
- | 'annotation.remove'
40
- | 'block.set'
41
- | 'block.unset'
42
- | 'child.set'
43
- | 'child.unset'
44
- | 'decorator.add'
45
- | 'decorator.remove'
46
- | 'delete'
47
- | 'history.redo'
48
- | 'history.undo'
49
- | 'insert.block'
50
- | 'insert.child'
51
- | 'move.backward'
52
- | 'move.block'
53
- | 'move.forward'
54
- | 'select'
55
- | 'annotation.set'
56
- | 'annotation.toggle'
57
- | 'decorator.toggle'
58
- | 'delete.backward'
59
- | 'delete.block'
60
- | 'delete.child'
61
- | 'delete.forward'
62
- | 'delete.text'
63
- | 'deserialize'
64
- | 'deserialize.data'
65
- | 'deserialization.success'
66
- | 'deserialization.failure'
67
- | 'insert.blocks'
68
- | 'insert.break'
69
- | 'insert.inline object'
70
- | 'insert.soft break'
71
- | 'insert.span'
72
- | 'list item.add'
73
- | 'list item.remove'
74
- | 'list item.toggle'
75
- | 'move.block down'
76
- | 'move.block up'
77
- | 'select.block'
78
- | 'select.previous block'
79
- | 'select.next block'
80
- | 'serialize'
81
- | 'serialize.data'
82
- | 'serialization.success'
83
- | 'serialization.failure'
84
- | 'split'
85
- | 'style.add'
86
- | 'style.remove'
87
- | 'style.toggle'
88
- | 'clipboard.copy'
89
- | 'clipboard.cut'
90
- | 'clipboard.paste'
91
- | 'drag.dragstart'
92
- | 'drag.drag'
93
- | 'drag.dragend'
94
- | 'drag.dragenter'
95
- | 'drag.dragover'
96
- | 'drag.dragleave'
97
- | 'drag.drop'
98
- | 'input.*'
99
- | 'keyboard.keydown'
100
- | 'keyboard.keyup'
101
- | 'mouse.click'
102
- | 'delete.*'
103
- | 'select.*'
104
- | 'deserialize.*'
105
- | 'serialize.*'
106
- | 'split.*'
107
- | 'insert.*'
108
- | 'annotation.*'
109
- | 'block.*'
110
- | 'child.*'
111
- | 'decorator.*'
112
- | 'history.*'
113
- | 'move.*'
114
- | 'deserialization.*'
115
- | 'list item.*'
116
- | 'serialization.*'
117
- | 'style.*'
118
- | 'clipboard.*'
119
- | 'drag.*'
120
- | 'keyboard.*'
121
- | 'mouse.*'
122
- | `custom.${string}`,
123
- true,
124
- BehaviorEvent
125
- >
126
-
127
- /**
128
- * Define an `InputRule` specifically designed to transform matched text into
129
- * some other text.
130
- *
131
- * @example
132
- * ```tsx
133
- * const transformRule = defineTextTransformRule({
134
- * on: /--/,
135
- * transform: () => '—',
136
- * })
137
- * ```
138
- *
139
- * @alpha
140
- */
141
- export declare function defineTextTransformRule<TGuardResponse = true>(
142
- config: TextTransformRule<TGuardResponse>,
143
- ): InputRule<TGuardResponse>
144
-
145
- /**
146
- * @alpha
147
- */
148
- export declare type InputRule<TGuardResponse = true> = {
149
- on: RegExp
150
- guard?: InputRuleGuard<TGuardResponse>
151
- actions: Array<BehaviorActionSet<InputRuleEvent, TGuardResponse>>
152
- }
153
-
154
- /**
155
- * @alpha
156
- */
157
- export declare type InputRuleEvent = {
158
- type: 'custom.input rule'
159
- /**
160
- * Matches found by the input rule
161
- */
162
- matches: Array<InputRuleMatch>
163
- /**
164
- * The text before the insertion
165
- */
166
- textBefore: string
167
- /**
168
- * The text is destined to be inserted
169
- */
170
- textInserted: string
171
- /**
172
- * The text block where the insertion takes place
173
- */
174
- focusTextBlock: {
175
- path: BlockPath
176
- node: PortableTextTextBlock
177
- }
178
- }
179
-
180
- /**
181
- * @alpha
182
- */
183
- export declare type InputRuleGuard<TGuardResponse = true> = BehaviorGuard<
184
- InputRuleEvent,
185
- TGuardResponse
186
- >
187
-
188
- /**
189
- * Match found in the text after the insertion
190
- * @alpha
191
- */
192
- export declare type InputRuleMatch = InputRuleMatchLocation & {
193
- groupMatches: Array<InputRuleMatchLocation>
194
- }
195
-
196
- declare type InputRuleMatchLocation = {
197
- /**
198
- * The matched text
199
- */
200
- text: string
201
- /**
202
- * Estimated selection of where in the original text the match is located.
203
- * The selection is estimated since the match is found in the text after
204
- * insertion.
205
- */
206
- selection: NonNullable<EditorSelection>
207
- /**
208
- * Block offsets of the match in the text after the insertion
209
- */
210
- targetOffsets: {
211
- anchor: BlockOffset
212
- focus: BlockOffset
213
- backward: boolean
214
- }
215
- }
216
-
217
- /**
218
- * Turn an array of `InputRule`s into a Behavior that can be used to apply the
219
- * rules to the editor.
220
- *
221
- * The plugin handles undo/redo out of the box including smart undo with
222
- * Backspace.
223
- *
224
- * @example
225
- * ```tsx
226
- * <InputRulePlugin rules={smartQuotesRules} />
227
- * ```
228
- *
229
- * @alpha
230
- */
231
- export declare function InputRulePlugin(props: InputRulePluginProps): null
232
-
233
- declare type InputRulePluginProps = {
234
- rules: Array<InputRule<any>>
235
- }
236
-
237
- /**
238
- * @alpha
239
- */
240
- export declare type TextTransformRule<TGuardResponse = true> = {
241
- on: RegExp
242
- guard?: InputRuleGuard<TGuardResponse>
243
- transform: (
244
- {
245
- location,
246
- }: {
247
- location: InputRuleMatchLocation
248
- },
249
- guardResponse: TGuardResponse,
250
- ) => string
251
- }
252
-
253
- export {}