@lexical/react 0.1.14 → 0.1.15
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/DEPRECATED_useLexicalAutoFormatter.dev.js +283 -295
- package/DEPRECATED_useLexicalAutoFormatter.prod.js +19 -21
- package/DEPRECATED_useLexicalCanShowPlaceholder.dev.js +3 -72
- package/DEPRECATED_useLexicalCanShowPlaceholder.prod.js +1 -2
- package/DEPRECATED_useLexicalCharacterLimit.dev.js +11 -63
- package/DEPRECATED_useLexicalCharacterLimit.prod.js +6 -7
- package/DEPRECATED_useLexicalPlainText.dev.js +16 -41
- package/DEPRECATED_useLexicalPlainText.prod.js +13 -14
- package/DEPRECATED_useLexicalRichText.dev.js +24 -49
- package/DEPRECATED_useLexicalRichText.prod.js +15 -15
- package/LexicalAutoFormatterPlugin.dev.js +283 -295
- package/LexicalAutoFormatterPlugin.prod.js +19 -21
- package/LexicalAutoLinkPlugin.dev.js +2 -2
- package/LexicalAutoLinkPlugin.prod.js +2 -2
- package/LexicalCharacterLimitPlugin.dev.js +11 -63
- package/LexicalCharacterLimitPlugin.prod.js +8 -9
- package/LexicalCollaborationPlugin.d.ts +3 -1
- package/LexicalCollaborationPlugin.dev.js +40 -6
- package/LexicalCollaborationPlugin.js.flow +4 -1
- package/LexicalCollaborationPlugin.prod.js +8 -7
- package/LexicalHashtagPlugin.dev.js +16 -13
- package/LexicalHashtagPlugin.prod.js +7 -7
- package/LexicalOnChangePlugin.dev.js +15 -2
- package/LexicalOnChangePlugin.prod.js +2 -1
- package/LexicalPlainTextPlugin.dev.js +20 -113
- package/LexicalPlainTextPlugin.prod.js +11 -12
- package/LexicalRichTextPlugin.dev.js +28 -121
- package/LexicalRichTextPlugin.prod.js +12 -13
- package/LexicalTablePlugin.dev.js +9 -5
- package/LexicalTablePlugin.prod.js +2 -2
- package/package.json +9 -7
- package/useLexicalIsTextContentEmpty.dev.js +3 -32
- package/useLexicalIsTextContentEmpty.prod.js +1 -2
|
@@ -12,6 +12,7 @@ var lexical = require('lexical');
|
|
|
12
12
|
var CodeNode = require('lexical/CodeNode');
|
|
13
13
|
var react = require('react');
|
|
14
14
|
var LexicalHorizontalRuleNode = require('@lexical/react/LexicalHorizontalRuleNode');
|
|
15
|
+
var text = require('@lexical/text');
|
|
15
16
|
var HeadingNode = require('lexical/HeadingNode');
|
|
16
17
|
var QuoteNode = require('lexical/QuoteNode');
|
|
17
18
|
|
|
@@ -23,108 +24,27 @@ var QuoteNode = require('lexical/QuoteNode');
|
|
|
23
24
|
*
|
|
24
25
|
*
|
|
25
26
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const child = children[i];
|
|
37
|
-
|
|
38
|
-
if (lexical.$isTextNode(child)) {
|
|
39
|
-
const childTextContent = child.getTextContent();
|
|
40
|
-
|
|
41
|
-
if (child.is(stopAt.node)) {
|
|
42
|
-
if (stopAt.offset > childTextContent.length) {
|
|
43
|
-
{
|
|
44
|
-
throw Error(`Node ${child.__key} and selection point do not match.`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
textContent += child.getTextContent().substr(0, stopAt.offset);
|
|
49
|
-
break;
|
|
50
|
-
} else {
|
|
51
|
-
textContent += childTextContent;
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
textContent += separator;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return textContent;
|
|
59
|
-
} // This function converts the offsetInJoinedText to
|
|
60
|
-
// a node and offset result or null if not found.
|
|
61
|
-
// This function is to be used in conjunction with joinTextNodesInElementNode above.
|
|
62
|
-
// The joinedTextContent should be return value from joinTextNodesInElementNode.
|
|
63
|
-
//
|
|
64
|
-
// The offsetInJoinedText is relative to the entire string which
|
|
65
|
-
// itself is relevant to the parent ElementNode.
|
|
66
|
-
//
|
|
67
|
-
// Example:
|
|
68
|
-
// Given a Paragraph with 2 TextNodes. The first is Hello, the second is World.
|
|
69
|
-
// The joinedTextContent would be "HelloWorld"
|
|
70
|
-
// The offsetInJoinedText might be for the letter "e" = 1 or "r" = 7.
|
|
71
|
-
// The return values would be {TextNode1, 1} or {TextNode2,2}, respectively.
|
|
72
|
-
|
|
73
|
-
function $findNodeWithOffsetFromJoinedText(elementNode, joinedTextLength, offsetInJoinedText, separatorLength) {
|
|
74
|
-
const children = elementNode.getChildren();
|
|
75
|
-
const childrenLength = children.length;
|
|
76
|
-
let runningLength = 0;
|
|
77
|
-
let isPriorNodeTextNode = false;
|
|
78
|
-
|
|
79
|
-
for (let i = 0; i < childrenLength; ++i) {
|
|
80
|
-
// We must examine the offsetInJoinedText that is located
|
|
81
|
-
// at the length of the string.
|
|
82
|
-
// For example, given "hello", the length is 5, yet
|
|
83
|
-
// the caller still wants the node + offset at the
|
|
84
|
-
// right edge of the "o".
|
|
85
|
-
if (runningLength > joinedTextLength) {
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const child = children[i];
|
|
90
|
-
const isChildNodeTestNode = lexical.$isTextNode(child);
|
|
91
|
-
const childContentLength = isChildNodeTestNode ? child.getTextContent().length : separatorLength;
|
|
92
|
-
const newRunningLength = runningLength + childContentLength;
|
|
93
|
-
const isJoinedOffsetWithinNode = isPriorNodeTextNode === false && runningLength === offsetInJoinedText || runningLength === 0 && runningLength === offsetInJoinedText || runningLength < offsetInJoinedText && offsetInJoinedText <= newRunningLength;
|
|
94
|
-
|
|
95
|
-
if (isJoinedOffsetWithinNode && lexical.$isTextNode(child)) {
|
|
96
|
-
// Check isTextNode again for flow.
|
|
97
|
-
return {
|
|
98
|
-
node: child,
|
|
99
|
-
offset: offsetInJoinedText - runningLength
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
runningLength = newRunningLength;
|
|
104
|
-
isPriorNodeTextNode = isChildNodeTestNode;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
112
|
-
*
|
|
113
|
-
* This source code is licensed under the MIT license found in the
|
|
114
|
-
* LICENSE file in the root directory of this source tree.
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*/
|
|
27
|
+
/*
|
|
28
|
+
How to add a new syntax to capture and transform.
|
|
29
|
+
1. Create a new enumeration by adding to AutoFormatKind.
|
|
30
|
+
2. Add a new criteria with a regEx pattern. See markdownStrikethrough as an example.
|
|
31
|
+
3. Add your block criteria (e.g. '# ') to allAutoFormatCriteria or
|
|
32
|
+
your text criteria (e.g. *MyItalic*) to allAutoFormatCriteriaForTextNodes.
|
|
33
|
+
4. Add your Lexical block specific transforming code here: transformTextNodeForText.
|
|
34
|
+
Add your Lexical text specific transforming code here: transformTextNodeForText.
|
|
35
|
+
*/
|
|
36
|
+
// The trigger state helps to capture EditorState information
|
|
118
37
|
// from the prior and current EditorState.
|
|
119
38
|
// This is then used to determined if an auto format has been triggered.
|
|
120
39
|
|
|
121
40
|
const TRIGGER_STRING = '\u0020'; // The space key triggers markdown.
|
|
122
41
|
|
|
123
|
-
const TRIGGER_STRING_LENGTH = TRIGGER_STRING.length;
|
|
124
42
|
const SEPARATOR_BETWEEN_TEXT_AND_NON_TEXT_NODES = '\u0004'; // Select an unused unicode character to separate text and non-text nodes.
|
|
125
43
|
|
|
44
|
+
const SEPARATOR_LENGTH = SEPARATOR_BETWEEN_TEXT_AND_NON_TEXT_NODES.length; // Todo: speed up performance by having non-capture group variations of the regex.
|
|
45
|
+
|
|
126
46
|
const autoFormatBase = {
|
|
127
|
-
|
|
47
|
+
autoFormatKind: null,
|
|
128
48
|
regEx: /(?:)/,
|
|
129
49
|
requiresParagraphStart: false
|
|
130
50
|
};
|
|
@@ -132,72 +52,76 @@ const paragraphStartBase = { ...autoFormatBase,
|
|
|
132
52
|
requiresParagraphStart: true
|
|
133
53
|
};
|
|
134
54
|
const markdownHeader1 = { ...paragraphStartBase,
|
|
135
|
-
|
|
55
|
+
autoFormatKind: 'paragraphH1',
|
|
136
56
|
regEx: /^(?:# )/
|
|
137
57
|
};
|
|
138
58
|
const markdownHeader2 = { ...paragraphStartBase,
|
|
139
|
-
|
|
59
|
+
autoFormatKind: 'paragraphH2',
|
|
140
60
|
regEx: /^(?:## )/
|
|
141
61
|
};
|
|
142
62
|
const markdownHeader3 = { ...paragraphStartBase,
|
|
143
|
-
|
|
63
|
+
autoFormatKind: 'paragraphH2',
|
|
144
64
|
regEx: /^(?:### )/
|
|
145
65
|
};
|
|
146
66
|
const markdownBlockQuote = { ...paragraphStartBase,
|
|
147
|
-
|
|
67
|
+
autoFormatKind: 'paragraphBlockQuote',
|
|
148
68
|
regEx: /^(?:> )/
|
|
149
69
|
};
|
|
150
70
|
const markdownUnorderedListDash = { ...paragraphStartBase,
|
|
151
|
-
|
|
71
|
+
autoFormatKind: 'paragraphUnorderedList',
|
|
152
72
|
regEx: /^(?:- )/
|
|
153
73
|
};
|
|
154
74
|
const markdownUnorderedListAsterisk = { ...paragraphStartBase,
|
|
155
|
-
|
|
75
|
+
autoFormatKind: 'paragraphUnorderedList',
|
|
156
76
|
regEx: /^(?:\* )/
|
|
157
77
|
};
|
|
158
78
|
const markdownCodeBlock = { ...paragraphStartBase,
|
|
159
|
-
|
|
79
|
+
autoFormatKind: 'paragraphCodeBlock',
|
|
160
80
|
regEx: /^(```)([a-z]*)( )/
|
|
161
81
|
};
|
|
162
82
|
const markdownOrderedList = { ...paragraphStartBase,
|
|
163
|
-
|
|
83
|
+
autoFormatKind: 'paragraphOrderedList',
|
|
164
84
|
regEx: /^(\d+)\.\s/
|
|
165
85
|
};
|
|
166
86
|
const markdownHorizontalRule = { ...paragraphStartBase,
|
|
167
|
-
|
|
87
|
+
autoFormatKind: 'horizontalRule',
|
|
168
88
|
regEx: /^(?:\*\*\* )/
|
|
169
89
|
};
|
|
170
90
|
const markdownHorizontalRuleUsingDashes = { ...paragraphStartBase,
|
|
171
|
-
|
|
91
|
+
autoFormatKind: 'horizontalRule',
|
|
172
92
|
regEx: /^(?:--- )/
|
|
173
93
|
};
|
|
174
94
|
const markdownItalic = { ...autoFormatBase,
|
|
175
|
-
|
|
176
|
-
regEx: /(\*)(\s*\b)([^\*]*)(\b\s*)(
|
|
95
|
+
autoFormatKind: 'italic',
|
|
96
|
+
regEx: /(\*)(\s*\b)([^\*]*)(\b\s*)(\*)(\s)$/
|
|
177
97
|
};
|
|
178
98
|
const markdownBold = { ...autoFormatBase,
|
|
179
|
-
|
|
180
|
-
regEx: /(\*\*)(\s*\b)([^\*\*]*)(\b\s*)(
|
|
99
|
+
autoFormatKind: 'bold',
|
|
100
|
+
regEx: /(\*\*)(\s*\b)([^\*\*]*)(\b\s*)(\*\*)(\s)$/
|
|
181
101
|
};
|
|
182
102
|
const markdownBoldWithUnderlines = { ...autoFormatBase,
|
|
183
|
-
|
|
184
|
-
regEx: /(__)(\s*)([^__]*)(\s*)(__\s)$/
|
|
103
|
+
autoFormatKind: 'bold',
|
|
104
|
+
regEx: /(__)(\s*)([^__]*)(\s*)(__)(\s)$/
|
|
185
105
|
};
|
|
186
106
|
const markdownBoldItalic = { ...autoFormatBase,
|
|
187
|
-
|
|
188
|
-
regEx: /(\*\*\*)(\s*\b)([^\*\*\*]*)(\b\s*)(
|
|
107
|
+
autoFormatKind: 'bold_italic',
|
|
108
|
+
regEx: /(\*\*\*)(\s*\b)([^\*\*\*]*)(\b\s*)(\*\*\*)(\s)$/
|
|
189
109
|
}; // Markdown does not support underline, but we can allow folks to use
|
|
190
110
|
// the HTML tags for underline.
|
|
191
111
|
|
|
192
112
|
const fakeMarkdownUnderline = { ...autoFormatBase,
|
|
193
|
-
|
|
194
|
-
regEx: /(\<u\>)(\s*\b)([^\<]*)(\b\s*)(\<\/u
|
|
113
|
+
autoFormatKind: 'underline',
|
|
114
|
+
regEx: /(\<u\>)(\s*\b)([^\<]*)(\b\s*)(\<\/u\>)(\s)$/
|
|
195
115
|
};
|
|
196
116
|
const markdownStrikethrough = { ...autoFormatBase,
|
|
197
|
-
|
|
198
|
-
regEx: /(~~)(\s*\b)([^~~]*)(\b\s*)(
|
|
117
|
+
autoFormatKind: 'strikethrough',
|
|
118
|
+
regEx: /(~~)(\s*\b)([^~~]*)(\b\s*)(~~)(\s)$/
|
|
199
119
|
};
|
|
200
|
-
const
|
|
120
|
+
const markdownLink = { ...autoFormatBase,
|
|
121
|
+
autoFormatKind: 'link',
|
|
122
|
+
regEx: /(\[)(.+)(\]\()([^ ]+)(?: \"(?:.+)\")?(\))(\s)$/
|
|
123
|
+
};
|
|
124
|
+
const allAutoFormatCriteriaForTextNodes = [markdownBoldItalic, markdownItalic, markdownBold, markdownBoldWithUnderlines, fakeMarkdownUnderline, markdownStrikethrough, markdownLink];
|
|
201
125
|
const allAutoFormatCriteria = [markdownHeader1, markdownHeader2, markdownHeader3, markdownBlockQuote, markdownUnorderedListDash, markdownUnorderedListAsterisk, markdownOrderedList, markdownCodeBlock, markdownHorizontalRule, markdownHorizontalRuleUsingDashes, ...allAutoFormatCriteriaForTextNodes];
|
|
202
126
|
function getAllAutoFormatCriteriaForTextNodes() {
|
|
203
127
|
return allAutoFormatCriteriaForTextNodes;
|
|
@@ -205,17 +129,17 @@ function getAllAutoFormatCriteriaForTextNodes() {
|
|
|
205
129
|
function getAllAutoFormatCriteria() {
|
|
206
130
|
return allAutoFormatCriteria;
|
|
207
131
|
}
|
|
208
|
-
function getInitialScanningContext(textNodeWithOffset, triggerState) {
|
|
132
|
+
function getInitialScanningContext(editor, textNodeWithOffset, triggerState) {
|
|
209
133
|
return {
|
|
210
134
|
autoFormatCriteria: {
|
|
211
|
-
|
|
135
|
+
autoFormatKind: 'noTransformation',
|
|
212
136
|
regEx: /(?:)/,
|
|
213
137
|
// Empty reg ex will do until the precise criteria is discovered.
|
|
214
138
|
requiresParagraphStart: null
|
|
215
139
|
},
|
|
140
|
+
editor,
|
|
216
141
|
joinedText: null,
|
|
217
|
-
|
|
218
|
-
offsetInJoinedTextForCollapsedSelection: 0,
|
|
142
|
+
patternMatchResults: {
|
|
219
143
|
regExCaptureGroups: []
|
|
220
144
|
},
|
|
221
145
|
textNodeWithOffset,
|
|
@@ -223,26 +147,21 @@ function getInitialScanningContext(textNodeWithOffset, triggerState) {
|
|
|
223
147
|
};
|
|
224
148
|
}
|
|
225
149
|
|
|
226
|
-
function
|
|
227
|
-
const
|
|
228
|
-
offsetInJoinedTextForCollapsedSelection: 0,
|
|
150
|
+
function getPatternMatchResultsWithRegEx(textToSearch, matchMustAppearAtStartOfString, matchMustAppearAtEndOfString, regEx) {
|
|
151
|
+
const patternMatchResults = {
|
|
229
152
|
regExCaptureGroups: []
|
|
230
153
|
};
|
|
231
154
|
const regExMatches = textToSearch.match(regEx);
|
|
232
155
|
|
|
233
156
|
if (regExMatches !== null && regExMatches.length > 0 && (matchMustAppearAtStartOfString === false || regExMatches.index === 0) && (matchMustAppearAtEndOfString === false || regExMatches.index + regExMatches[0].length === textToSearch.length)) {
|
|
234
|
-
matchResultContext.offsetInJoinedTextForCollapsedSelection = textToSearch.length;
|
|
235
157
|
const captureGroupsCount = regExMatches.length;
|
|
236
158
|
let runningLength = regExMatches.index;
|
|
237
159
|
|
|
238
160
|
for (let captureGroupIndex = 0; captureGroupIndex < captureGroupsCount; captureGroupIndex++) {
|
|
239
161
|
const textContent = regExMatches[captureGroupIndex];
|
|
240
|
-
|
|
241
|
-
anchorTextNodeWithOffset: null,
|
|
242
|
-
focusTextNodeWithOffset: null,
|
|
162
|
+
patternMatchResults.regExCaptureGroups.push({
|
|
243
163
|
offsetInParent: runningLength,
|
|
244
|
-
text: textContent
|
|
245
|
-
textLength: textContent.length - (captureGroupIndex + 1 === captureGroupsCount ? TRIGGER_STRING_LENGTH : 0)
|
|
164
|
+
text: textContent
|
|
246
165
|
}); // The 0th capture group is special in that it's text contents is
|
|
247
166
|
// a join of all subsequent capture groups. So, skip this group
|
|
248
167
|
// when calculating the runningLength.
|
|
@@ -252,31 +171,31 @@ function getMatchResultContextWithRegEx(textToSearch, matchMustAppearAtStartOfSt
|
|
|
252
171
|
}
|
|
253
172
|
}
|
|
254
173
|
|
|
255
|
-
return
|
|
174
|
+
return patternMatchResults;
|
|
256
175
|
}
|
|
257
176
|
|
|
258
177
|
return null;
|
|
259
178
|
}
|
|
260
179
|
|
|
261
|
-
function
|
|
180
|
+
function getPatternMatchResultsForParagraphs(autoFormatCriteria, scanningContext) {
|
|
262
181
|
const textNodeWithOffset = scanningContext.textNodeWithOffset; // At start of paragraph.
|
|
263
182
|
|
|
264
183
|
if (textNodeWithOffset.node.getPreviousSibling() === null) {
|
|
265
184
|
const textToSearch = scanningContext.textNodeWithOffset.node.getTextContent();
|
|
266
|
-
return
|
|
185
|
+
return getPatternMatchResultsWithRegEx(textToSearch, true, false, autoFormatCriteria.regEx);
|
|
267
186
|
}
|
|
268
187
|
|
|
269
188
|
return null;
|
|
270
189
|
}
|
|
271
190
|
|
|
272
|
-
function
|
|
191
|
+
function getPatternMatchResultsForText(autoFormatCriteria, scanningContext) {
|
|
273
192
|
if (scanningContext.joinedText == null) {
|
|
274
|
-
const parentNode = scanningContext
|
|
193
|
+
const parentNode = getParent(scanningContext);
|
|
275
194
|
|
|
276
195
|
if (lexical.$isElementNode(parentNode)) {
|
|
277
196
|
if (scanningContext.joinedText == null) {
|
|
278
197
|
// Lazy calculate the text to search.
|
|
279
|
-
scanningContext.joinedText =
|
|
198
|
+
scanningContext.joinedText = text.$joinTextNodesInElementNode(parentNode, SEPARATOR_BETWEEN_TEXT_AND_NON_TEXT_NODES, scanningContext.textNodeWithOffset);
|
|
280
199
|
}
|
|
281
200
|
} else {
|
|
282
201
|
{
|
|
@@ -285,25 +204,25 @@ function getMatchResultContextForText(autoFormatCriteria, scanningContext) {
|
|
|
285
204
|
}
|
|
286
205
|
}
|
|
287
206
|
|
|
288
|
-
return
|
|
207
|
+
return getPatternMatchResultsWithRegEx(scanningContext.joinedText, false, true, autoFormatCriteria.regEx);
|
|
289
208
|
}
|
|
290
209
|
|
|
291
|
-
function
|
|
210
|
+
function getPatternMatchResultsForCriteria(autoFormatCriteria, scanningContext) {
|
|
292
211
|
if (autoFormatCriteria.requiresParagraphStart !== null && autoFormatCriteria.requiresParagraphStart === true) {
|
|
293
|
-
return
|
|
212
|
+
return getPatternMatchResultsForParagraphs(autoFormatCriteria, scanningContext);
|
|
294
213
|
}
|
|
295
214
|
|
|
296
|
-
return
|
|
215
|
+
return getPatternMatchResultsForText(autoFormatCriteria, scanningContext);
|
|
297
216
|
}
|
|
298
217
|
|
|
299
218
|
function getNewNodeForCriteria(scanningContext, element) {
|
|
300
219
|
let newNode = null;
|
|
301
220
|
const children = element.getChildren();
|
|
302
221
|
const autoFormatCriteria = scanningContext.autoFormatCriteria;
|
|
303
|
-
const
|
|
222
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
304
223
|
|
|
305
|
-
if (autoFormatCriteria.
|
|
306
|
-
switch (autoFormatCriteria.
|
|
224
|
+
if (autoFormatCriteria.autoFormatKind != null) {
|
|
225
|
+
switch (autoFormatCriteria.autoFormatKind) {
|
|
307
226
|
case 'paragraphH1':
|
|
308
227
|
{
|
|
309
228
|
newNode = HeadingNode.$createHeadingNode('h1');
|
|
@@ -343,7 +262,7 @@ function getNewNodeForCriteria(scanningContext, element) {
|
|
|
343
262
|
|
|
344
263
|
case 'paragraphOrderedList':
|
|
345
264
|
{
|
|
346
|
-
const startAsString =
|
|
265
|
+
const startAsString = patternMatchResults.regExCaptureGroups.length > 1 ? patternMatchResults.regExCaptureGroups[patternMatchResults.regExCaptureGroups.length - 1].text : '1';
|
|
347
266
|
const start = parseInt(startAsString, 10);
|
|
348
267
|
newNode = list.$createListNode('ol', start);
|
|
349
268
|
const listItem = list.$createListItemNode();
|
|
@@ -359,7 +278,7 @@ function getNewNodeForCriteria(scanningContext, element) {
|
|
|
359
278
|
newNode = lexical.$createParagraphNode();
|
|
360
279
|
} else {
|
|
361
280
|
newNode = CodeNode.$createCodeNode();
|
|
362
|
-
const codingLanguage =
|
|
281
|
+
const codingLanguage = patternMatchResults.regExCaptureGroups.length >= 3 ? patternMatchResults.regExCaptureGroups[2].text : null;
|
|
363
282
|
|
|
364
283
|
if (codingLanguage != null && codingLanguage.length > 0) {
|
|
365
284
|
newNode.setLanguage(codingLanguage);
|
|
@@ -383,15 +302,6 @@ function getNewNodeForCriteria(scanningContext, element) {
|
|
|
383
302
|
return newNode;
|
|
384
303
|
}
|
|
385
304
|
|
|
386
|
-
function updateTextNode(node, count) {
|
|
387
|
-
const textNode = node.spliceText(0, count, '', true);
|
|
388
|
-
|
|
389
|
-
if (textNode.getTextContent() === '') {
|
|
390
|
-
textNode.selectPrevious();
|
|
391
|
-
textNode.remove();
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
|
|
395
305
|
function transformTextNodeForAutoFormatCriteria(scanningContext) {
|
|
396
306
|
if (scanningContext.autoFormatCriteria.requiresParagraphStart) {
|
|
397
307
|
transformTextNodeForParagraphs(scanningContext);
|
|
@@ -403,8 +313,16 @@ function transformTextNodeForAutoFormatCriteria(scanningContext) {
|
|
|
403
313
|
function transformTextNodeForParagraphs(scanningContext) {
|
|
404
314
|
const textNodeWithOffset = scanningContext.textNodeWithOffset;
|
|
405
315
|
const element = textNodeWithOffset.node.getParentOrThrow();
|
|
406
|
-
const text = scanningContext.
|
|
407
|
-
|
|
316
|
+
const text = scanningContext.patternMatchResults.regExCaptureGroups[0].text; // Remove the text which we matched.
|
|
317
|
+
|
|
318
|
+
const textNode = textNodeWithOffset.node.spliceText(0, text.length, '', true);
|
|
319
|
+
|
|
320
|
+
if (textNode.getTextContent() === '') {
|
|
321
|
+
textNode.selectPrevious();
|
|
322
|
+
textNode.remove();
|
|
323
|
+
} // Transform the current element kind to the new element kind.
|
|
324
|
+
|
|
325
|
+
|
|
408
326
|
const elementNode = getNewNodeForCriteria(scanningContext, element);
|
|
409
327
|
|
|
410
328
|
if (elementNode !== null) {
|
|
@@ -412,155 +330,223 @@ function transformTextNodeForParagraphs(scanningContext) {
|
|
|
412
330
|
}
|
|
413
331
|
}
|
|
414
332
|
|
|
415
|
-
function
|
|
416
|
-
|
|
417
|
-
case 'italic':
|
|
418
|
-
case 'bold':
|
|
419
|
-
case 'underline':
|
|
420
|
-
case 'strikethrough':
|
|
421
|
-
return [nodeTransformationKind];
|
|
333
|
+
function transformTextNodeForText(scanningContext) {
|
|
334
|
+
const autoFormatCriteria = scanningContext.autoFormatCriteria;
|
|
422
335
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
336
|
+
if (autoFormatCriteria.autoFormatKind != null) {
|
|
337
|
+
const formatting = getTextFormatType(autoFormatCriteria.autoFormatKind);
|
|
338
|
+
|
|
339
|
+
if (formatting != null) {
|
|
340
|
+
transformTextNodeWithFormatting(formatting, scanningContext);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (autoFormatCriteria.autoFormatKind === 'link') {
|
|
345
|
+
transformTextNodeWithLink(scanningContext);
|
|
346
|
+
}
|
|
427
347
|
}
|
|
348
|
+
}
|
|
428
349
|
|
|
429
|
-
|
|
350
|
+
function transformTextNodeWithFormatting(formatting, scanningContext) {
|
|
351
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
352
|
+
const groupCount = patternMatchResults.regExCaptureGroups.length;
|
|
353
|
+
|
|
354
|
+
if (groupCount !== 7) {
|
|
355
|
+
// For BIUS and similar formats which have a pattern + text + pattern:
|
|
356
|
+
// given '*italic* ' below are the capture groups by index:
|
|
357
|
+
// 0. '*italic* '
|
|
358
|
+
// 1. '*'
|
|
359
|
+
// 2. whitespace // typically this is "".
|
|
360
|
+
// 3. 'italic'
|
|
361
|
+
// 4. whitespace // typicallly this is "".
|
|
362
|
+
// 5. '*'
|
|
363
|
+
// 6. ' '
|
|
364
|
+
return;
|
|
365
|
+
} // Remove unwanted text in reg ex pattern.
|
|
366
|
+
// Remove group 5.
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
removeTextByCaptureGroups(5, 5, scanningContext); // Remove group 1.
|
|
370
|
+
|
|
371
|
+
removeTextByCaptureGroups(1, 1, scanningContext); // Apply the formatting.
|
|
372
|
+
|
|
373
|
+
formatTextInCaptureGroupIndex(formatting, 3, scanningContext); // Place caret at end of final capture group.
|
|
374
|
+
|
|
375
|
+
selectAfterFinalCaptureGroup(scanningContext);
|
|
430
376
|
}
|
|
431
377
|
|
|
432
|
-
function
|
|
433
|
-
const
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
378
|
+
function transformTextNodeWithLink(scanningContext) {
|
|
379
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
380
|
+
const regExCaptureGroups = patternMatchResults.regExCaptureGroups;
|
|
381
|
+
const groupCount = regExCaptureGroups.length;
|
|
382
|
+
|
|
383
|
+
if (groupCount !== 7) {
|
|
384
|
+
// For links and similar formats which have: pattern + text + pattern + pattern2 text2 + pattern2:
|
|
385
|
+
// Given '[title](url) ', below are the capture groups by index:
|
|
386
|
+
// 0. '[title](url) '
|
|
387
|
+
// 1. '['
|
|
388
|
+
// 2. 'title'
|
|
389
|
+
// 3. ']('
|
|
390
|
+
// 4. 'url'
|
|
391
|
+
// 5. ')'
|
|
392
|
+
// 6. ' '
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
444
395
|
|
|
445
|
-
|
|
396
|
+
const title = regExCaptureGroups[2].text;
|
|
397
|
+
const url = regExCaptureGroups[4].text;
|
|
446
398
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
matchResultContext.regExCaptureGroups = getCaptureGroupsByResolvingAllDetails(scanningContext);
|
|
399
|
+
if (title.length === 0 || url.length === 0) {
|
|
400
|
+
return;
|
|
401
|
+
} // Remove the initial pattern through to the final pattern.
|
|
451
402
|
|
|
452
|
-
if (captureGroupsToDelete.length > 0) {
|
|
453
|
-
// Remove unwanted text in reg ex pattern.
|
|
454
|
-
removeTextInCaptureGroups(captureGroupsToDelete, matchResultContext);
|
|
455
|
-
}
|
|
456
403
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
404
|
+
removeTextByCaptureGroups(1, 5, scanningContext);
|
|
405
|
+
insertTextPriorToCaptureGroup(1, // Insert at the beginning of the meaningful capture groups, namely index 1. Index 0 refers to the whole matched string.
|
|
406
|
+
title, scanningContext);
|
|
407
|
+
const newSelectionForLink = createSelectionWithCaptureGroups(1, 1, false, true, scanningContext);
|
|
408
|
+
|
|
409
|
+
if (newSelectionForLink == null) {
|
|
410
|
+
return;
|
|
460
411
|
}
|
|
461
|
-
} // Some Capture Group Details were left lazily unresolved as their calculation
|
|
462
|
-
// was not necessary during the scanning phase. Now that the nodeTransformationKind is
|
|
463
|
-
// known, the details may be fully resolved without incurring unwasted performance cost.
|
|
464
412
|
|
|
413
|
+
lexical.$setSelection(newSelectionForLink);
|
|
414
|
+
scanningContext.editor.execCommand('toggleLink', url); // Place caret at end of final capture group.
|
|
465
415
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const matchResultContext = scanningContext.matchResultContext;
|
|
469
|
-
const textNodeWithOffset = scanningContext.textNodeWithOffset;
|
|
470
|
-
const regExCaptureGroups = matchResultContext.regExCaptureGroups;
|
|
471
|
-
const captureGroupsCount = regExCaptureGroups.length;
|
|
472
|
-
const parentElementNode = textNodeWithOffset.node.getParentOrThrow();
|
|
416
|
+
selectAfterFinalCaptureGroup(scanningContext);
|
|
417
|
+
} // Below are lower level helper functions.
|
|
473
418
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
419
|
+
|
|
420
|
+
function getParent(scanningContext) {
|
|
421
|
+
return scanningContext.textNodeWithOffset.node.getParentOrThrow();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function getJoinedTextLength(patternMatchResults) {
|
|
425
|
+
const groupCount = patternMatchResults.regExCaptureGroups.length;
|
|
426
|
+
|
|
427
|
+
if (groupCount < 2) {
|
|
428
|
+
// Ignore capture group 0, as regEx defaults the 0th one to the entire matched string.
|
|
429
|
+
return 0;
|
|
478
430
|
}
|
|
479
431
|
|
|
480
|
-
const
|
|
432
|
+
const lastGroupIndex = groupCount - 1;
|
|
433
|
+
return patternMatchResults.regExCaptureGroups[lastGroupIndex].offsetInParent + patternMatchResults.regExCaptureGroups[lastGroupIndex].text.length;
|
|
434
|
+
}
|
|
481
435
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
436
|
+
function getTextFormatType(autoFormatKind) {
|
|
437
|
+
switch (autoFormatKind) {
|
|
438
|
+
case 'italic':
|
|
439
|
+
case 'bold':
|
|
440
|
+
case 'underline':
|
|
441
|
+
case 'strikethrough':
|
|
442
|
+
return [autoFormatKind];
|
|
486
443
|
|
|
487
|
-
|
|
444
|
+
case 'bold_italic':
|
|
488
445
|
{
|
|
489
|
-
|
|
446
|
+
return ['bold', 'italic'];
|
|
490
447
|
}
|
|
491
|
-
}
|
|
492
448
|
}
|
|
493
449
|
|
|
494
|
-
return
|
|
450
|
+
return null;
|
|
495
451
|
}
|
|
496
452
|
|
|
497
|
-
function
|
|
498
|
-
const
|
|
453
|
+
function createSelectionWithCaptureGroups(anchorCaptureGroupIndex, focusCaptureGroupIndex, startAtEndOfAnchor, finishAtEndOfFocus, scanningContext) {
|
|
454
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
455
|
+
const regExCaptureGroups = patternMatchResults.regExCaptureGroups;
|
|
499
456
|
const regExCaptureGroupsCount = regExCaptureGroups.length;
|
|
500
457
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const captureGroupDetail = regExCaptureGroups[captureGroupIndex];
|
|
505
|
-
const anchorTextNodeWithOffset = captureGroupDetail.anchorTextNodeWithOffset;
|
|
506
|
-
const focusTextNodeWithOffset = captureGroupDetail.focusTextNodeWithOffset;
|
|
458
|
+
if (anchorCaptureGroupIndex >= regExCaptureGroupsCount || focusCaptureGroupIndex >= regExCaptureGroupsCount) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
507
461
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
462
|
+
const parentElementNode = getParent(scanningContext);
|
|
463
|
+
const joinedTextLength = getJoinedTextLength(patternMatchResults);
|
|
464
|
+
const anchorCaptureGroupDetail = regExCaptureGroups[anchorCaptureGroupIndex];
|
|
465
|
+
const focusCaptureGroupDetail = regExCaptureGroups[focusCaptureGroupIndex];
|
|
466
|
+
const anchorLocation = startAtEndOfAnchor ? anchorCaptureGroupDetail.offsetInParent + anchorCaptureGroupDetail.text.length : anchorCaptureGroupDetail.offsetInParent;
|
|
467
|
+
const focusLocation = finishAtEndOfFocus ? focusCaptureGroupDetail.offsetInParent + focusCaptureGroupDetail.text.length : focusCaptureGroupDetail.offsetInParent;
|
|
468
|
+
const anchorTextNodeWithOffset = text.$findNodeWithOffsetFromJoinedText(anchorLocation, joinedTextLength, SEPARATOR_LENGTH, parentElementNode);
|
|
469
|
+
const focusTextNodeWithOffset = text.$findNodeWithOffsetFromJoinedText(focusLocation, joinedTextLength, SEPARATOR_LENGTH, parentElementNode);
|
|
514
470
|
|
|
515
|
-
|
|
516
|
-
|
|
471
|
+
if (anchorTextNodeWithOffset == null || focusTextNodeWithOffset == null) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
517
474
|
|
|
518
|
-
|
|
519
|
-
|
|
475
|
+
const selection = lexical.$createRangeSelection();
|
|
476
|
+
selection.anchor.set(anchorTextNodeWithOffset.node.getKey(), anchorTextNodeWithOffset.offset, 'text');
|
|
477
|
+
selection.focus.set(focusTextNodeWithOffset.node.getKey(), focusTextNodeWithOffset.offset, 'text');
|
|
478
|
+
return selection;
|
|
479
|
+
}
|
|
520
480
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
481
|
+
function removeTextByCaptureGroups(anchorCaptureGroupIndex, focusCaptureGroupIndex, scanningContext) {
|
|
482
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
483
|
+
const regExCaptureGroups = patternMatchResults.regExCaptureGroups;
|
|
484
|
+
const newSelection = createSelectionWithCaptureGroups(anchorCaptureGroupIndex, focusCaptureGroupIndex, false, true, scanningContext);
|
|
524
485
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
486
|
+
if (newSelection != null) {
|
|
487
|
+
lexical.$setSelection(newSelection);
|
|
488
|
+
const currentSelection = lexical.$getSelection();
|
|
528
489
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
490
|
+
if (currentSelection != null && lexical.$isRangeSelection(currentSelection) && currentSelection.isCollapsed() === false) {
|
|
491
|
+
currentSelection.removeText(); // Shift all group offsets and clear out group text.
|
|
492
|
+
|
|
493
|
+
let runningLength = 0;
|
|
494
|
+
const groupCount = regExCaptureGroups.length;
|
|
495
|
+
|
|
496
|
+
for (let i = anchorCaptureGroupIndex; i < groupCount; i++) {
|
|
497
|
+
const captureGroupDetail = regExCaptureGroups[i];
|
|
498
|
+
|
|
499
|
+
if (i > anchorCaptureGroupIndex) {
|
|
500
|
+
captureGroupDetail.offsetInParent -= runningLength;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
if (i <= focusCaptureGroupIndex) {
|
|
504
|
+
runningLength += captureGroupDetail.text.length;
|
|
505
|
+
captureGroupDetail.text = '';
|
|
533
506
|
}
|
|
534
507
|
}
|
|
535
508
|
}
|
|
536
509
|
}
|
|
537
510
|
}
|
|
538
511
|
|
|
539
|
-
function
|
|
540
|
-
|
|
512
|
+
function insertTextPriorToCaptureGroup(captureGroupIndex, text, scanningContext) {
|
|
513
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
514
|
+
const regExCaptureGroups = patternMatchResults.regExCaptureGroups;
|
|
515
|
+
const regExCaptureGroupsCount = regExCaptureGroups.length;
|
|
541
516
|
|
|
542
|
-
if (
|
|
543
|
-
|
|
517
|
+
if (captureGroupIndex >= regExCaptureGroupsCount) {
|
|
518
|
+
return;
|
|
544
519
|
}
|
|
545
520
|
|
|
546
|
-
const
|
|
547
|
-
const
|
|
521
|
+
const captureGroupDetail = regExCaptureGroups[captureGroupIndex];
|
|
522
|
+
const newCaptureGroupDetail = {
|
|
523
|
+
offsetInParent: captureGroupDetail.offsetInParent,
|
|
524
|
+
text
|
|
525
|
+
};
|
|
526
|
+
const newSelection = createSelectionWithCaptureGroups(captureGroupIndex, captureGroupIndex, false, false, scanningContext);
|
|
548
527
|
|
|
549
|
-
|
|
550
|
-
|
|
528
|
+
if (newSelection != null) {
|
|
529
|
+
lexical.$setSelection(newSelection);
|
|
530
|
+
const currentSelection = lexical.$getSelection();
|
|
551
531
|
|
|
552
|
-
if (
|
|
553
|
-
|
|
554
|
-
}
|
|
532
|
+
if (currentSelection != null && lexical.$isRangeSelection(currentSelection) && currentSelection.isCollapsed()) {
|
|
533
|
+
currentSelection.insertText(newCaptureGroupDetail.text); // Update the capture groups.
|
|
555
534
|
|
|
556
|
-
|
|
557
|
-
|
|
535
|
+
regExCaptureGroups.splice(captureGroupIndex, 0, newCaptureGroupDetail);
|
|
536
|
+
const textLength = newCaptureGroupDetail.text.length;
|
|
537
|
+
const newGroupCount = regExCaptureGroups.length;
|
|
538
|
+
|
|
539
|
+
for (let i = captureGroupIndex + 1; i < newGroupCount; i++) {
|
|
540
|
+
const currentCaptureGroupDetail = regExCaptureGroups[i];
|
|
541
|
+
currentCaptureGroupDetail.offsetInParent += textLength;
|
|
542
|
+
}
|
|
558
543
|
}
|
|
559
544
|
}
|
|
560
545
|
}
|
|
561
546
|
|
|
562
|
-
function formatTextInCaptureGroupIndex(formatTypes, captureGroupIndex,
|
|
563
|
-
const
|
|
547
|
+
function formatTextInCaptureGroupIndex(formatTypes, captureGroupIndex, scanningContext) {
|
|
548
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
549
|
+
const regExCaptureGroups = patternMatchResults.regExCaptureGroups;
|
|
564
550
|
const regExCaptureGroupsCount = regExCaptureGroups.length;
|
|
565
551
|
|
|
566
552
|
if (!(captureGroupIndex < regExCaptureGroupsCount)) {
|
|
@@ -568,13 +554,14 @@ function formatTextInCaptureGroupIndex(formatTypes, captureGroupIndex, matchResu
|
|
|
568
554
|
}
|
|
569
555
|
|
|
570
556
|
const captureGroupDetail = regExCaptureGroups[captureGroupIndex];
|
|
571
|
-
const anchorTextNodeWithOffset = captureGroupDetail.anchorTextNodeWithOffset;
|
|
572
|
-
const focusTextNodeWithOffset = captureGroupDetail.focusTextNodeWithOffset;
|
|
573
557
|
|
|
574
|
-
if (
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
558
|
+
if (captureGroupDetail.text.length === 0) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
const newSelection = createSelectionWithCaptureGroups(captureGroupIndex, captureGroupIndex, false, true, scanningContext);
|
|
563
|
+
|
|
564
|
+
if (newSelection != null) {
|
|
578
565
|
lexical.$setSelection(newSelection);
|
|
579
566
|
const currentSelection = lexical.$getSelection();
|
|
580
567
|
|
|
@@ -582,22 +569,24 @@ function formatTextInCaptureGroupIndex(formatTypes, captureGroupIndex, matchResu
|
|
|
582
569
|
for (let i = 0; i < formatTypes.length; i++) {
|
|
583
570
|
currentSelection.formatText(formatTypes[i]);
|
|
584
571
|
}
|
|
585
|
-
|
|
586
|
-
const finalSelection = lexical.$createRangeSelection();
|
|
587
|
-
finalSelection.anchor.set(focusTextNodeWithOffset.node.getKey(), focusTextNodeWithOffset.offset + 1, 'text');
|
|
588
|
-
finalSelection.focus.set(focusTextNodeWithOffset.node.getKey(), focusTextNodeWithOffset.offset + 1, 'text');
|
|
589
|
-
lexical.$setSelection(finalSelection);
|
|
590
572
|
}
|
|
591
573
|
}
|
|
592
|
-
}
|
|
574
|
+
} // Place caret at end of final capture group.
|
|
575
|
+
|
|
593
576
|
|
|
594
|
-
function
|
|
595
|
-
const
|
|
577
|
+
function selectAfterFinalCaptureGroup(scanningContext) {
|
|
578
|
+
const patternMatchResults = scanningContext.patternMatchResults;
|
|
579
|
+
const groupCount = patternMatchResults.regExCaptureGroups.length;
|
|
596
580
|
|
|
597
|
-
if (
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
581
|
+
if (groupCount < 2) {
|
|
582
|
+
// Ignore capture group 0, as regEx defaults the 0th one to the entire matched string.
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const lastGroupIndex = groupCount - 1;
|
|
587
|
+
const newSelection = createSelectionWithCaptureGroups(lastGroupIndex, lastGroupIndex, true, true, scanningContext);
|
|
588
|
+
|
|
589
|
+
if (newSelection != null) {
|
|
601
590
|
lexical.$setSelection(newSelection);
|
|
602
591
|
}
|
|
603
592
|
}
|
|
@@ -611,20 +600,20 @@ function makeCollapsedSelectionAtOffsetInJoinedText(offsetInJoinedText, joinedTe
|
|
|
611
600
|
*
|
|
612
601
|
*/
|
|
613
602
|
|
|
614
|
-
function
|
|
603
|
+
function getCriteriaWithPatternMatchResults(autoFormatCriteriaArray, scanningContext) {
|
|
615
604
|
const currentTriggerState = scanningContext.triggerState;
|
|
616
605
|
const count = autoFormatCriteriaArray.length;
|
|
617
606
|
|
|
618
607
|
for (let i = 0; i < count; i++) {
|
|
619
|
-
const autoFormatCriteria = autoFormatCriteriaArray[i]; // Skip code block nodes, unless the
|
|
608
|
+
const autoFormatCriteria = autoFormatCriteriaArray[i]; // Skip code block nodes, unless the autoFormatKind calls for toggling the code block.
|
|
620
609
|
|
|
621
|
-
if (currentTriggerState != null && currentTriggerState.isCodeBlock === false || autoFormatCriteria.
|
|
622
|
-
const
|
|
610
|
+
if (currentTriggerState != null && currentTriggerState.isCodeBlock === false || autoFormatCriteria.autoFormatKind === 'paragraphCodeBlock') {
|
|
611
|
+
const patternMatchResults = getPatternMatchResultsForCriteria(autoFormatCriteria, scanningContext);
|
|
623
612
|
|
|
624
|
-
if (
|
|
613
|
+
if (patternMatchResults != null) {
|
|
625
614
|
return {
|
|
626
615
|
autoFormatCriteria: autoFormatCriteria,
|
|
627
|
-
|
|
616
|
+
patternMatchResults
|
|
628
617
|
};
|
|
629
618
|
}
|
|
630
619
|
}
|
|
@@ -632,7 +621,7 @@ function getCriteriaWithMatchResultContext(autoFormatCriteriaArray, scanningCont
|
|
|
632
621
|
|
|
633
622
|
return {
|
|
634
623
|
autoFormatCriteria: null,
|
|
635
|
-
|
|
624
|
+
patternMatchResults: null
|
|
636
625
|
};
|
|
637
626
|
}
|
|
638
627
|
|
|
@@ -661,9 +650,9 @@ function updateAutoFormatting(editor, scanningContext) {
|
|
|
661
650
|
});
|
|
662
651
|
}
|
|
663
652
|
|
|
664
|
-
function findScanningContextWithValidMatch(
|
|
653
|
+
function findScanningContextWithValidMatch(editor, currentTriggerState) {
|
|
665
654
|
let scanningContext = null;
|
|
666
|
-
|
|
655
|
+
editor.getEditorState().read(() => {
|
|
667
656
|
const textNodeWithOffset = getTextNodeForAutoFormatting(lexical.$getSelection());
|
|
668
657
|
|
|
669
658
|
if (textNodeWithOffset === null) {
|
|
@@ -671,23 +660,23 @@ function findScanningContextWithValidMatch(editorState, currentTriggerState) {
|
|
|
671
660
|
} // Please see the declaration of ScanningContext for a detailed explanation.
|
|
672
661
|
|
|
673
662
|
|
|
674
|
-
const initialScanningContext = getInitialScanningContext(textNodeWithOffset, currentTriggerState);
|
|
675
|
-
const
|
|
663
|
+
const initialScanningContext = getInitialScanningContext(editor, textNodeWithOffset, currentTriggerState);
|
|
664
|
+
const criteriaWithPatternMatchResults = getCriteriaWithPatternMatchResults( // Do not apply paragraph node changes like blockQuote or H1 to listNodes. Also, do not attempt to transform a list into a list using * or -.
|
|
676
665
|
currentTriggerState.isParentAListItemNode === false ? getAllAutoFormatCriteria() : getAllAutoFormatCriteriaForTextNodes(), initialScanningContext);
|
|
677
666
|
|
|
678
|
-
if (
|
|
667
|
+
if (criteriaWithPatternMatchResults.autoFormatCriteria === null || criteriaWithPatternMatchResults.patternMatchResults === null) {
|
|
679
668
|
return;
|
|
680
669
|
}
|
|
681
670
|
|
|
682
671
|
scanningContext = initialScanningContext; // Lazy fill-in the particular format criteria and any matching result information.
|
|
683
672
|
|
|
684
|
-
scanningContext.autoFormatCriteria =
|
|
685
|
-
scanningContext.
|
|
673
|
+
scanningContext.autoFormatCriteria = criteriaWithPatternMatchResults.autoFormatCriteria;
|
|
674
|
+
scanningContext.patternMatchResults = criteriaWithPatternMatchResults.patternMatchResults;
|
|
686
675
|
});
|
|
687
676
|
return scanningContext;
|
|
688
677
|
}
|
|
689
678
|
|
|
690
|
-
function findScanningContext(
|
|
679
|
+
function findScanningContext(editor, currentTriggerState, priorTriggerState) {
|
|
691
680
|
if (currentTriggerState == null || priorTriggerState == null) {
|
|
692
681
|
return null;
|
|
693
682
|
} // The below checks needs to execute relativey quickly, so perform the light-weight ones first.
|
|
@@ -703,7 +692,7 @@ function findScanningContext(editorState, currentTriggerState, priorTriggerState
|
|
|
703
692
|
return null;
|
|
704
693
|
}
|
|
705
694
|
|
|
706
|
-
return findScanningContextWithValidMatch(
|
|
695
|
+
return findScanningContextWithValidMatch(editor, currentTriggerState);
|
|
707
696
|
}
|
|
708
697
|
|
|
709
698
|
function getTriggerState(editorState) {
|
|
@@ -745,9 +734,8 @@ function useAutoFormatter(editor) {
|
|
|
745
734
|
}) => {
|
|
746
735
|
// Examine historic so that we are not running autoformatting within markdown.
|
|
747
736
|
if (tags.has('historic') === false) {
|
|
748
|
-
const
|
|
749
|
-
const
|
|
750
|
-
const scanningContext = currentTriggerState == null ? null : findScanningContext(editorState, currentTriggerState, priorTriggerState);
|
|
737
|
+
const currentTriggerState = getTriggerState(editor.getEditorState());
|
|
738
|
+
const scanningContext = currentTriggerState == null ? null : findScanningContext(editor, currentTriggerState, priorTriggerState);
|
|
751
739
|
|
|
752
740
|
if (scanningContext != null) {
|
|
753
741
|
updateAutoFormatting(editor, scanningContext);
|