@lexical/code 0.7.7 → 0.7.9
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/LexicalCode.dev.js +59 -234
- package/package.json +3 -3
package/LexicalCode.dev.js
CHANGED
|
@@ -29,60 +29,50 @@ var lexical = require('lexical');
|
|
|
29
29
|
* LICENSE file in the root directory of this source tree.
|
|
30
30
|
*
|
|
31
31
|
*/
|
|
32
|
-
|
|
33
32
|
const mapToPrismLanguage = language => {
|
|
34
33
|
// eslint-disable-next-line no-prototype-builtins
|
|
35
34
|
return language != null && Prism.languages.hasOwnProperty(language) ? language : undefined;
|
|
36
35
|
};
|
|
37
|
-
|
|
38
36
|
function hasChildDOMNodeTag(node, tagName) {
|
|
39
37
|
for (const child of node.childNodes) {
|
|
40
38
|
if (child instanceof HTMLElement && child.tagName === tagName) {
|
|
41
39
|
return true;
|
|
42
40
|
}
|
|
43
|
-
|
|
44
41
|
hasChildDOMNodeTag(child, tagName);
|
|
45
42
|
}
|
|
46
|
-
|
|
47
43
|
return false;
|
|
48
44
|
}
|
|
49
|
-
|
|
50
45
|
const LANGUAGE_DATA_ATTRIBUTE = 'data-highlight-language';
|
|
51
|
-
/** @noInheritDoc */
|
|
52
46
|
|
|
47
|
+
/** @noInheritDoc */
|
|
53
48
|
class CodeNode extends lexical.ElementNode {
|
|
54
49
|
/** @internal */
|
|
50
|
+
|
|
55
51
|
static getType() {
|
|
56
52
|
return 'code';
|
|
57
53
|
}
|
|
58
|
-
|
|
59
54
|
static clone(node) {
|
|
60
55
|
return new CodeNode(node.__language, node.__key);
|
|
61
56
|
}
|
|
62
|
-
|
|
63
57
|
constructor(language, key) {
|
|
64
58
|
super(key);
|
|
65
59
|
this.__language = mapToPrismLanguage(language);
|
|
66
|
-
}
|
|
67
|
-
|
|
60
|
+
}
|
|
68
61
|
|
|
62
|
+
// View
|
|
69
63
|
createDOM(config) {
|
|
70
64
|
const element = document.createElement('code');
|
|
71
65
|
utils.addClassNamesToElement(element, config.theme.code);
|
|
72
66
|
element.setAttribute('spellcheck', 'false');
|
|
73
67
|
const language = this.getLanguage();
|
|
74
|
-
|
|
75
68
|
if (language) {
|
|
76
69
|
element.setAttribute(LANGUAGE_DATA_ATTRIBUTE, language);
|
|
77
70
|
}
|
|
78
|
-
|
|
79
71
|
return element;
|
|
80
72
|
}
|
|
81
|
-
|
|
82
73
|
updateDOM(prevNode, dom, config) {
|
|
83
74
|
const language = this.__language;
|
|
84
75
|
const prevLanguage = prevNode.__language;
|
|
85
|
-
|
|
86
76
|
if (language) {
|
|
87
77
|
if (language !== prevLanguage) {
|
|
88
78
|
dom.setAttribute(LANGUAGE_DATA_ATTRIBUTE, language);
|
|
@@ -90,10 +80,8 @@ class CodeNode extends lexical.ElementNode {
|
|
|
90
80
|
} else if (prevLanguage) {
|
|
91
81
|
dom.removeAttribute(LANGUAGE_DATA_ATTRIBUTE);
|
|
92
82
|
}
|
|
93
|
-
|
|
94
83
|
return false;
|
|
95
84
|
}
|
|
96
|
-
|
|
97
85
|
static importDOM() {
|
|
98
86
|
return {
|
|
99
87
|
// Typically <pre> is used for code blocks, and <code> for inline code styles
|
|
@@ -115,29 +103,26 @@ class CodeNode extends lexical.ElementNode {
|
|
|
115
103
|
priority: 0
|
|
116
104
|
}),
|
|
117
105
|
table: node => {
|
|
118
|
-
const table = node;
|
|
119
|
-
|
|
106
|
+
const table = node;
|
|
107
|
+
// domNode is a <table> since we matched it by nodeName
|
|
120
108
|
if (isGitHubCodeTable(table)) {
|
|
121
109
|
return {
|
|
122
110
|
conversion: convertTableElement,
|
|
123
111
|
priority: 3
|
|
124
112
|
};
|
|
125
113
|
}
|
|
126
|
-
|
|
127
114
|
return null;
|
|
128
115
|
},
|
|
129
116
|
td: node => {
|
|
130
117
|
// element is a <td> since we matched it by nodeName
|
|
131
118
|
const td = node;
|
|
132
119
|
const table = td.closest('table');
|
|
133
|
-
|
|
134
120
|
if (isGitHubCodeCell(td)) {
|
|
135
121
|
return {
|
|
136
122
|
conversion: convertTableCellElement,
|
|
137
123
|
priority: 3
|
|
138
124
|
};
|
|
139
125
|
}
|
|
140
|
-
|
|
141
126
|
if (table && isGitHubCodeTable(table)) {
|
|
142
127
|
// Return a no-op if it's a table cell in a code table, but not a code line.
|
|
143
128
|
// Otherwise it'll fall back to the T
|
|
@@ -146,26 +131,22 @@ class CodeNode extends lexical.ElementNode {
|
|
|
146
131
|
priority: 3
|
|
147
132
|
};
|
|
148
133
|
}
|
|
149
|
-
|
|
150
134
|
return null;
|
|
151
135
|
},
|
|
152
136
|
tr: node => {
|
|
153
137
|
// element is a <tr> since we matched it by nodeName
|
|
154
138
|
const tr = node;
|
|
155
139
|
const table = tr.closest('table');
|
|
156
|
-
|
|
157
140
|
if (table && isGitHubCodeTable(table)) {
|
|
158
141
|
return {
|
|
159
142
|
conversion: convertCodeNoop,
|
|
160
143
|
priority: 3
|
|
161
144
|
};
|
|
162
145
|
}
|
|
163
|
-
|
|
164
146
|
return null;
|
|
165
147
|
}
|
|
166
148
|
};
|
|
167
149
|
}
|
|
168
|
-
|
|
169
150
|
static importJSON(serializedNode) {
|
|
170
151
|
const node = $createCodeNode(serializedNode.language);
|
|
171
152
|
node.setFormat(serializedNode.format);
|
|
@@ -173,42 +154,38 @@ class CodeNode extends lexical.ElementNode {
|
|
|
173
154
|
node.setDirection(serializedNode.direction);
|
|
174
155
|
return node;
|
|
175
156
|
}
|
|
176
|
-
|
|
177
157
|
exportJSON() {
|
|
178
|
-
return {
|
|
158
|
+
return {
|
|
159
|
+
...super.exportJSON(),
|
|
179
160
|
language: this.getLanguage(),
|
|
180
161
|
type: 'code',
|
|
181
162
|
version: 1
|
|
182
163
|
};
|
|
183
|
-
}
|
|
184
|
-
|
|
164
|
+
}
|
|
185
165
|
|
|
166
|
+
// Mutation
|
|
186
167
|
insertNewAfter(selection, restoreSelection = true) {
|
|
187
168
|
const children = this.getChildren();
|
|
188
169
|
const childrenLength = children.length;
|
|
189
|
-
|
|
190
170
|
if (childrenLength >= 2 && children[childrenLength - 1].getTextContent() === '\n' && children[childrenLength - 2].getTextContent() === '\n' && selection.isCollapsed() && selection.anchor.key === this.__key && selection.anchor.offset === childrenLength) {
|
|
191
171
|
children[childrenLength - 1].remove();
|
|
192
172
|
children[childrenLength - 2].remove();
|
|
193
173
|
const newElement = lexical.$createParagraphNode();
|
|
194
174
|
this.insertAfter(newElement, restoreSelection);
|
|
195
175
|
return newElement;
|
|
196
|
-
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// If the selection is within the codeblock, find all leading tabs and
|
|
197
179
|
// spaces of the current line. Create a new line that has all those
|
|
198
180
|
// tabs and spaces, such that leading indentation is preserved.
|
|
199
|
-
|
|
200
|
-
|
|
201
181
|
const anchor = selection.anchor.getNode();
|
|
202
182
|
const firstNode = getFirstCodeHighlightNodeOfLine(anchor);
|
|
203
|
-
|
|
204
183
|
if (firstNode != null) {
|
|
205
184
|
let leadingWhitespace = 0;
|
|
206
185
|
const firstNodeText = firstNode.getTextContent();
|
|
207
|
-
|
|
208
186
|
while (leadingWhitespace < firstNodeText.length && /[\t ]/.test(firstNodeText[leadingWhitespace])) {
|
|
209
187
|
leadingWhitespace += 1;
|
|
210
188
|
}
|
|
211
|
-
|
|
212
189
|
if (leadingWhitespace > 0) {
|
|
213
190
|
const whitespace = firstNodeText.substring(0, leadingWhitespace);
|
|
214
191
|
const indentedChild = $createCodeHighlightNode(whitespace);
|
|
@@ -218,24 +195,18 @@ class CodeNode extends lexical.ElementNode {
|
|
|
218
195
|
return indentedChild;
|
|
219
196
|
}
|
|
220
197
|
}
|
|
221
|
-
|
|
222
198
|
return null;
|
|
223
199
|
}
|
|
224
|
-
|
|
225
200
|
canInsertTab() {
|
|
226
201
|
const selection = lexical.$getSelection();
|
|
227
|
-
|
|
228
202
|
if (!lexical.$isRangeSelection(selection) || !selection.isCollapsed()) {
|
|
229
203
|
return false;
|
|
230
204
|
}
|
|
231
|
-
|
|
232
205
|
return true;
|
|
233
206
|
}
|
|
234
|
-
|
|
235
207
|
canIndent() {
|
|
236
208
|
return false;
|
|
237
209
|
}
|
|
238
|
-
|
|
239
210
|
collapseAtStart() {
|
|
240
211
|
const paragraph = lexical.$createParagraphNode();
|
|
241
212
|
const children = this.getChildren();
|
|
@@ -243,16 +214,13 @@ class CodeNode extends lexical.ElementNode {
|
|
|
243
214
|
this.replace(paragraph);
|
|
244
215
|
return true;
|
|
245
216
|
}
|
|
246
|
-
|
|
247
217
|
setLanguage(language) {
|
|
248
218
|
const writable = this.getWritable();
|
|
249
219
|
writable.__language = mapToPrismLanguage(language);
|
|
250
220
|
}
|
|
251
|
-
|
|
252
221
|
getLanguage() {
|
|
253
222
|
return this.getLatest().__language;
|
|
254
223
|
}
|
|
255
|
-
|
|
256
224
|
}
|
|
257
225
|
function $createCodeNode(language) {
|
|
258
226
|
return lexical.$applyNodeReplacement(new CodeNode(language));
|
|
@@ -260,53 +228,44 @@ function $createCodeNode(language) {
|
|
|
260
228
|
function $isCodeNode(node) {
|
|
261
229
|
return node instanceof CodeNode;
|
|
262
230
|
}
|
|
263
|
-
|
|
264
231
|
function convertPreElement(domNode) {
|
|
265
232
|
return {
|
|
266
233
|
node: $createCodeNode(),
|
|
267
234
|
preformatted: true
|
|
268
235
|
};
|
|
269
236
|
}
|
|
270
|
-
|
|
271
237
|
function convertDivElement(domNode) {
|
|
272
238
|
// domNode is a <div> since we matched it by nodeName
|
|
273
239
|
const div = domNode;
|
|
274
240
|
const isCode = isCodeElement(div);
|
|
275
|
-
|
|
276
241
|
if (!isCode && !isCodeChildElement(div)) {
|
|
277
242
|
return {
|
|
278
243
|
node: null
|
|
279
244
|
};
|
|
280
245
|
}
|
|
281
|
-
|
|
282
246
|
return {
|
|
283
247
|
after: childLexicalNodes => {
|
|
284
248
|
const domParent = domNode.parentNode;
|
|
285
|
-
|
|
286
249
|
if (domParent != null && domNode !== domParent.lastChild) {
|
|
287
250
|
childLexicalNodes.push(lexical.$createLineBreakNode());
|
|
288
251
|
}
|
|
289
|
-
|
|
290
252
|
return childLexicalNodes;
|
|
291
253
|
},
|
|
292
254
|
node: isCode ? $createCodeNode() : null,
|
|
293
255
|
preformatted: isCode
|
|
294
256
|
};
|
|
295
257
|
}
|
|
296
|
-
|
|
297
258
|
function convertTableElement() {
|
|
298
259
|
return {
|
|
299
260
|
node: $createCodeNode(),
|
|
300
261
|
preformatted: true
|
|
301
262
|
};
|
|
302
263
|
}
|
|
303
|
-
|
|
304
264
|
function convertCodeNoop() {
|
|
305
265
|
return {
|
|
306
266
|
node: null
|
|
307
267
|
};
|
|
308
268
|
}
|
|
309
|
-
|
|
310
269
|
function convertTableCellElement(domNode) {
|
|
311
270
|
// domNode is a <td> since we matched it by nodeName
|
|
312
271
|
const cell = domNode;
|
|
@@ -316,35 +275,27 @@ function convertTableCellElement(domNode) {
|
|
|
316
275
|
// Append newline between code lines
|
|
317
276
|
childLexicalNodes.push(lexical.$createLineBreakNode());
|
|
318
277
|
}
|
|
319
|
-
|
|
320
278
|
return childLexicalNodes;
|
|
321
279
|
},
|
|
322
280
|
node: null
|
|
323
281
|
};
|
|
324
282
|
}
|
|
325
|
-
|
|
326
283
|
function isCodeElement(div) {
|
|
327
284
|
return div.style.fontFamily.match('monospace') !== null;
|
|
328
285
|
}
|
|
329
|
-
|
|
330
286
|
function isCodeChildElement(node) {
|
|
331
287
|
let parent = node.parentElement;
|
|
332
|
-
|
|
333
288
|
while (parent !== null) {
|
|
334
289
|
if (isCodeElement(parent)) {
|
|
335
290
|
return true;
|
|
336
291
|
}
|
|
337
|
-
|
|
338
292
|
parent = parent.parentElement;
|
|
339
293
|
}
|
|
340
|
-
|
|
341
294
|
return false;
|
|
342
295
|
}
|
|
343
|
-
|
|
344
296
|
function isGitHubCodeCell(cell) {
|
|
345
297
|
return cell.classList.contains('js-file-line');
|
|
346
298
|
}
|
|
347
|
-
|
|
348
299
|
function isGitHubCodeTable(table) {
|
|
349
300
|
return table.classList.contains('js-file-line-container');
|
|
350
301
|
}
|
|
@@ -386,60 +337,52 @@ function normalizeCodeLang(lang) {
|
|
|
386
337
|
}
|
|
387
338
|
function getLanguageFriendlyName(lang) {
|
|
388
339
|
const _lang = normalizeCodeLang(lang);
|
|
389
|
-
|
|
390
340
|
return CODE_LANGUAGE_FRIENDLY_NAME_MAP[_lang] || _lang;
|
|
391
341
|
}
|
|
392
342
|
const getDefaultCodeLanguage = () => DEFAULT_CODE_LANGUAGE;
|
|
393
|
-
const getCodeLanguages = () => Object.keys(Prism.languages).filter(
|
|
343
|
+
const getCodeLanguages = () => Object.keys(Prism.languages).filter(
|
|
344
|
+
// Prism has several language helpers mixed into languages object
|
|
394
345
|
// so filtering them out here to get langs list
|
|
395
346
|
language => typeof Prism.languages[language] !== 'function').sort();
|
|
396
|
-
/** @noInheritDoc */
|
|
397
347
|
|
|
348
|
+
/** @noInheritDoc */
|
|
398
349
|
class CodeHighlightNode extends lexical.TextNode {
|
|
399
350
|
/** @internal */
|
|
351
|
+
|
|
400
352
|
constructor(text, highlightType, key) {
|
|
401
353
|
super(text, key);
|
|
402
354
|
this.__highlightType = highlightType;
|
|
403
355
|
}
|
|
404
|
-
|
|
405
356
|
static getType() {
|
|
406
357
|
return 'code-highlight';
|
|
407
358
|
}
|
|
408
|
-
|
|
409
359
|
static clone(node) {
|
|
410
360
|
return new CodeHighlightNode(node.__text, node.__highlightType || undefined, node.__key);
|
|
411
361
|
}
|
|
412
|
-
|
|
413
362
|
getHighlightType() {
|
|
414
363
|
const self = this.getLatest();
|
|
415
364
|
return self.__highlightType;
|
|
416
365
|
}
|
|
417
|
-
|
|
418
366
|
createDOM(config) {
|
|
419
367
|
const element = super.createDOM(config);
|
|
420
368
|
const className = getHighlightThemeClass(config.theme, this.__highlightType);
|
|
421
369
|
utils.addClassNamesToElement(element, className);
|
|
422
370
|
return element;
|
|
423
371
|
}
|
|
424
|
-
|
|
425
372
|
updateDOM(prevNode, dom, config) {
|
|
426
373
|
const update = super.updateDOM(prevNode, dom, config);
|
|
427
374
|
const prevClassName = getHighlightThemeClass(config.theme, prevNode.__highlightType);
|
|
428
375
|
const nextClassName = getHighlightThemeClass(config.theme, this.__highlightType);
|
|
429
|
-
|
|
430
376
|
if (prevClassName !== nextClassName) {
|
|
431
377
|
if (prevClassName) {
|
|
432
378
|
utils.removeClassNamesFromElement(dom, prevClassName);
|
|
433
379
|
}
|
|
434
|
-
|
|
435
380
|
if (nextClassName) {
|
|
436
381
|
utils.addClassNamesToElement(dom, nextClassName);
|
|
437
382
|
}
|
|
438
383
|
}
|
|
439
|
-
|
|
440
384
|
return update;
|
|
441
385
|
}
|
|
442
|
-
|
|
443
386
|
static importJSON(serializedNode) {
|
|
444
387
|
const node = $createCodeHighlightNode(serializedNode.text, serializedNode.highlightType);
|
|
445
388
|
node.setFormat(serializedNode.format);
|
|
@@ -448,34 +391,29 @@ class CodeHighlightNode extends lexical.TextNode {
|
|
|
448
391
|
node.setStyle(serializedNode.style);
|
|
449
392
|
return node;
|
|
450
393
|
}
|
|
451
|
-
|
|
452
394
|
exportJSON() {
|
|
453
|
-
return {
|
|
395
|
+
return {
|
|
396
|
+
...super.exportJSON(),
|
|
454
397
|
highlightType: this.getHighlightType(),
|
|
455
398
|
type: 'code-highlight',
|
|
456
399
|
version: 1
|
|
457
400
|
};
|
|
458
|
-
}
|
|
459
|
-
|
|
401
|
+
}
|
|
460
402
|
|
|
403
|
+
// Prevent formatting (bold, underline, etc)
|
|
461
404
|
setFormat(format) {
|
|
462
405
|
return this;
|
|
463
406
|
}
|
|
464
|
-
|
|
465
407
|
isParentRequired() {
|
|
466
408
|
return true;
|
|
467
409
|
}
|
|
468
|
-
|
|
469
410
|
createParentElementNode() {
|
|
470
411
|
return $createCodeNode();
|
|
471
412
|
}
|
|
472
|
-
|
|
473
413
|
}
|
|
474
|
-
|
|
475
414
|
function getHighlightThemeClass(theme, highlightType) {
|
|
476
415
|
return highlightType && theme && theme.codeHighlight && theme.codeHighlight[highlightType];
|
|
477
416
|
}
|
|
478
|
-
|
|
479
417
|
function $createCodeHighlightNode(text, highlightType) {
|
|
480
418
|
return lexical.$applyNodeReplacement(new CodeHighlightNode(text, highlightType));
|
|
481
419
|
}
|
|
@@ -486,38 +424,30 @@ function getFirstCodeHighlightNodeOfLine(anchor) {
|
|
|
486
424
|
let currentNode = null;
|
|
487
425
|
const previousSiblings = anchor.getPreviousSiblings();
|
|
488
426
|
previousSiblings.push(anchor);
|
|
489
|
-
|
|
490
427
|
while (previousSiblings.length > 0) {
|
|
491
428
|
const node = previousSiblings.pop();
|
|
492
|
-
|
|
493
429
|
if ($isCodeHighlightNode(node)) {
|
|
494
430
|
currentNode = node;
|
|
495
431
|
}
|
|
496
|
-
|
|
497
432
|
if (lexical.$isLineBreakNode(node)) {
|
|
498
433
|
break;
|
|
499
434
|
}
|
|
500
435
|
}
|
|
501
|
-
|
|
502
436
|
return currentNode;
|
|
503
437
|
}
|
|
504
438
|
function getLastCodeHighlightNodeOfLine(anchor) {
|
|
505
439
|
let currentNode = null;
|
|
506
440
|
const nextSiblings = anchor.getNextSiblings();
|
|
507
441
|
nextSiblings.unshift(anchor);
|
|
508
|
-
|
|
509
442
|
while (nextSiblings.length > 0) {
|
|
510
443
|
const node = nextSiblings.shift();
|
|
511
|
-
|
|
512
444
|
if ($isCodeHighlightNode(node)) {
|
|
513
445
|
currentNode = node;
|
|
514
446
|
}
|
|
515
|
-
|
|
516
447
|
if (lexical.$isLineBreakNode(node)) {
|
|
517
448
|
break;
|
|
518
449
|
}
|
|
519
450
|
}
|
|
520
|
-
|
|
521
451
|
return currentNode;
|
|
522
452
|
}
|
|
523
453
|
|
|
@@ -530,25 +460,19 @@ function getLastCodeHighlightNodeOfLine(anchor) {
|
|
|
530
460
|
*/
|
|
531
461
|
const PrismTokenizer = {
|
|
532
462
|
defaultLanguage: DEFAULT_CODE_LANGUAGE,
|
|
533
|
-
|
|
534
463
|
tokenize(code, language) {
|
|
535
464
|
return Prism.tokenize(code, Prism.languages[language || ''] || Prism.languages[this.defaultLanguage]);
|
|
536
465
|
}
|
|
537
|
-
|
|
538
466
|
};
|
|
539
|
-
|
|
540
467
|
function isSpaceOrTabChar(char) {
|
|
541
468
|
return char === ' ' || char === '\t';
|
|
542
469
|
}
|
|
543
|
-
|
|
544
470
|
function findFirstNotSpaceOrTabCharAtText(text, isForward) {
|
|
545
471
|
const length = text.length;
|
|
546
472
|
let offset = -1;
|
|
547
|
-
|
|
548
473
|
if (isForward) {
|
|
549
474
|
for (let i = 0; i < length; i++) {
|
|
550
475
|
const char = text[i];
|
|
551
|
-
|
|
552
476
|
if (!isSpaceOrTabChar(char)) {
|
|
553
477
|
offset = i;
|
|
554
478
|
break;
|
|
@@ -557,64 +481,51 @@ function findFirstNotSpaceOrTabCharAtText(text, isForward) {
|
|
|
557
481
|
} else {
|
|
558
482
|
for (let i = length - 1; i > -1; i--) {
|
|
559
483
|
const char = text[i];
|
|
560
|
-
|
|
561
484
|
if (!isSpaceOrTabChar(char)) {
|
|
562
485
|
offset = i;
|
|
563
486
|
break;
|
|
564
487
|
}
|
|
565
488
|
}
|
|
566
489
|
}
|
|
567
|
-
|
|
568
490
|
return offset;
|
|
569
491
|
}
|
|
570
|
-
|
|
571
492
|
function getStartOfCodeInLine(anchor) {
|
|
572
493
|
let currentNode = null;
|
|
573
494
|
let currentNodeOffset = -1;
|
|
574
495
|
const previousSiblings = anchor.getPreviousSiblings();
|
|
575
496
|
previousSiblings.push(anchor);
|
|
576
|
-
|
|
577
497
|
while (previousSiblings.length > 0) {
|
|
578
498
|
const node = previousSiblings.pop();
|
|
579
|
-
|
|
580
499
|
if ($isCodeHighlightNode(node)) {
|
|
581
500
|
const text = node.getTextContent();
|
|
582
501
|
const offset = findFirstNotSpaceOrTabCharAtText(text, true);
|
|
583
|
-
|
|
584
502
|
if (offset !== -1) {
|
|
585
503
|
currentNode = node;
|
|
586
504
|
currentNodeOffset = offset;
|
|
587
505
|
}
|
|
588
506
|
}
|
|
589
|
-
|
|
590
507
|
if (lexical.$isLineBreakNode(node)) {
|
|
591
508
|
break;
|
|
592
509
|
}
|
|
593
510
|
}
|
|
594
|
-
|
|
595
511
|
if (currentNode === null) {
|
|
596
512
|
const nextSiblings = anchor.getNextSiblings();
|
|
597
|
-
|
|
598
513
|
while (nextSiblings.length > 0) {
|
|
599
514
|
const node = nextSiblings.shift();
|
|
600
|
-
|
|
601
515
|
if ($isCodeHighlightNode(node)) {
|
|
602
516
|
const text = node.getTextContent();
|
|
603
517
|
const offset = findFirstNotSpaceOrTabCharAtText(text, true);
|
|
604
|
-
|
|
605
518
|
if (offset !== -1) {
|
|
606
519
|
currentNode = node;
|
|
607
520
|
currentNodeOffset = offset;
|
|
608
521
|
break;
|
|
609
522
|
}
|
|
610
523
|
}
|
|
611
|
-
|
|
612
524
|
if (lexical.$isLineBreakNode(node)) {
|
|
613
525
|
break;
|
|
614
526
|
}
|
|
615
527
|
}
|
|
616
528
|
}
|
|
617
|
-
|
|
618
529
|
return {
|
|
619
530
|
node: currentNode,
|
|
620
531
|
offset: currentNodeOffset
|
|
@@ -625,59 +536,47 @@ function getEndOfCodeInLine(anchor) {
|
|
|
625
536
|
let currentNodeOffset = -1;
|
|
626
537
|
const nextSiblings = anchor.getNextSiblings();
|
|
627
538
|
nextSiblings.unshift(anchor);
|
|
628
|
-
|
|
629
539
|
while (nextSiblings.length > 0) {
|
|
630
540
|
const node = nextSiblings.shift();
|
|
631
|
-
|
|
632
541
|
if ($isCodeHighlightNode(node)) {
|
|
633
542
|
const text = node.getTextContent();
|
|
634
543
|
const offset = findFirstNotSpaceOrTabCharAtText(text, false);
|
|
635
|
-
|
|
636
544
|
if (offset !== -1) {
|
|
637
545
|
currentNode = node;
|
|
638
546
|
currentNodeOffset = offset + 1;
|
|
639
547
|
}
|
|
640
548
|
}
|
|
641
|
-
|
|
642
549
|
if (lexical.$isLineBreakNode(node)) {
|
|
643
550
|
break;
|
|
644
551
|
}
|
|
645
552
|
}
|
|
646
|
-
|
|
647
553
|
if (currentNode === null) {
|
|
648
554
|
const previousSiblings = anchor.getPreviousSiblings();
|
|
649
|
-
|
|
650
555
|
while (previousSiblings.length > 0) {
|
|
651
556
|
const node = previousSiblings.pop();
|
|
652
|
-
|
|
653
557
|
if ($isCodeHighlightNode(node)) {
|
|
654
558
|
const text = node.getTextContent();
|
|
655
559
|
const offset = findFirstNotSpaceOrTabCharAtText(text, false);
|
|
656
|
-
|
|
657
560
|
if (offset !== -1) {
|
|
658
561
|
currentNode = node;
|
|
659
562
|
currentNodeOffset = offset + 1;
|
|
660
563
|
break;
|
|
661
564
|
}
|
|
662
565
|
}
|
|
663
|
-
|
|
664
566
|
if (lexical.$isLineBreakNode(node)) {
|
|
665
567
|
break;
|
|
666
568
|
}
|
|
667
569
|
}
|
|
668
570
|
}
|
|
669
|
-
|
|
670
571
|
return {
|
|
671
572
|
node: currentNode,
|
|
672
573
|
offset: currentNodeOffset
|
|
673
574
|
};
|
|
674
575
|
}
|
|
675
|
-
|
|
676
576
|
function textNodeTransform(node, editor, tokenizer) {
|
|
677
577
|
// Since CodeNode has flat children structure we only need to check
|
|
678
578
|
// if node's parent is a code node and run highlighting if so
|
|
679
579
|
const parentNode = node.getParent();
|
|
680
|
-
|
|
681
580
|
if ($isCodeNode(parentNode)) {
|
|
682
581
|
codeNodeTransform(parentNode, editor, tokenizer);
|
|
683
582
|
} else if ($isCodeHighlightNode(node)) {
|
|
@@ -686,35 +585,31 @@ function textNodeTransform(node, editor, tokenizer) {
|
|
|
686
585
|
node.replace(lexical.$createTextNode(node.__text));
|
|
687
586
|
}
|
|
688
587
|
}
|
|
689
|
-
|
|
690
588
|
function updateCodeGutter(node, editor) {
|
|
691
589
|
const codeElement = editor.getElementByKey(node.getKey());
|
|
692
|
-
|
|
693
590
|
if (codeElement === null) {
|
|
694
591
|
return;
|
|
695
592
|
}
|
|
696
|
-
|
|
697
593
|
const children = node.getChildren();
|
|
698
|
-
const childrenLength = children.length;
|
|
699
|
-
|
|
594
|
+
const childrenLength = children.length;
|
|
595
|
+
// @ts-ignore: internal field
|
|
700
596
|
if (childrenLength === codeElement.__cachedChildrenLength) {
|
|
701
597
|
// Avoid updating the attribute if the children length hasn't changed.
|
|
702
598
|
return;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
|
|
599
|
+
}
|
|
600
|
+
// @ts-ignore:: internal field
|
|
706
601
|
codeElement.__cachedChildrenLength = childrenLength;
|
|
707
602
|
let gutter = '1';
|
|
708
603
|
let count = 1;
|
|
709
|
-
|
|
710
604
|
for (let i = 0; i < childrenLength; i++) {
|
|
711
605
|
if (lexical.$isLineBreakNode(children[i])) {
|
|
712
606
|
gutter += '\n' + ++count;
|
|
713
607
|
}
|
|
714
608
|
}
|
|
715
|
-
|
|
716
609
|
codeElement.setAttribute('data-gutter', gutter);
|
|
717
|
-
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Using `skipTransforms` to prevent extra transforms since reformatting the code
|
|
718
613
|
// will not affect code block content itself.
|
|
719
614
|
//
|
|
720
615
|
// Using extra cache (`nodesCurrentlyHighlighting`) since both CodeNode and CodeHighlightNode
|
|
@@ -722,33 +617,28 @@ function updateCodeGutter(node, editor) {
|
|
|
722
617
|
// in both cases we'll rerun whole reformatting over CodeNode, which is redundant.
|
|
723
618
|
// Especially when pasting code into CodeBlock.
|
|
724
619
|
|
|
725
|
-
|
|
726
620
|
const nodesCurrentlyHighlighting = new Set();
|
|
727
|
-
|
|
728
621
|
function codeNodeTransform(node, editor, tokenizer) {
|
|
729
622
|
const nodeKey = node.getKey();
|
|
730
|
-
|
|
731
623
|
if (nodesCurrentlyHighlighting.has(nodeKey)) {
|
|
732
624
|
return;
|
|
733
625
|
}
|
|
626
|
+
nodesCurrentlyHighlighting.add(nodeKey);
|
|
734
627
|
|
|
735
|
-
|
|
736
|
-
|
|
628
|
+
// When new code block inserted it might not have language selected
|
|
737
629
|
if (node.getLanguage() === undefined) {
|
|
738
630
|
node.setLanguage(tokenizer.defaultLanguage);
|
|
739
|
-
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Using nested update call to pass `skipTransforms` since we don't want
|
|
740
634
|
// each individual codehighlight node to be transformed again as it's already
|
|
741
635
|
// in its final state
|
|
742
|
-
|
|
743
|
-
|
|
744
636
|
editor.update(() => {
|
|
745
637
|
updateAndRetainSelection(nodeKey, () => {
|
|
746
638
|
const currentNode = lexical.$getNodeByKey(nodeKey);
|
|
747
|
-
|
|
748
639
|
if (!$isCodeNode(currentNode) || !currentNode.isAttached()) {
|
|
749
640
|
return false;
|
|
750
641
|
}
|
|
751
|
-
|
|
752
642
|
const code = currentNode.getTextContent();
|
|
753
643
|
const tokens = tokenizer.tokenize(code, currentNode.getLanguage() || tokenizer.defaultLanguage);
|
|
754
644
|
const highlightNodes = getHighlightNodes(tokens);
|
|
@@ -758,12 +648,10 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
758
648
|
to,
|
|
759
649
|
nodesForReplacement
|
|
760
650
|
} = diffRange;
|
|
761
|
-
|
|
762
651
|
if (from !== to || nodesForReplacement.length) {
|
|
763
652
|
node.splice(from, to - from, nodesForReplacement);
|
|
764
653
|
return true;
|
|
765
654
|
}
|
|
766
|
-
|
|
767
655
|
return false;
|
|
768
656
|
});
|
|
769
657
|
}, {
|
|
@@ -773,20 +661,16 @@ function codeNodeTransform(node, editor, tokenizer) {
|
|
|
773
661
|
skipTransforms: true
|
|
774
662
|
});
|
|
775
663
|
}
|
|
776
|
-
|
|
777
664
|
function getHighlightNodes(tokens) {
|
|
778
665
|
const nodes = [];
|
|
779
666
|
tokens.forEach(token => {
|
|
780
667
|
if (typeof token === 'string') {
|
|
781
668
|
const partials = token.split('\n');
|
|
782
|
-
|
|
783
669
|
for (let i = 0; i < partials.length; i++) {
|
|
784
670
|
const text = partials[i];
|
|
785
|
-
|
|
786
671
|
if (text.length) {
|
|
787
672
|
nodes.push($createCodeHighlightNode(text));
|
|
788
673
|
}
|
|
789
|
-
|
|
790
674
|
if (i < partials.length - 1) {
|
|
791
675
|
nodes.push(lexical.$createLineBreakNode());
|
|
792
676
|
}
|
|
@@ -795,7 +679,6 @@ function getHighlightNodes(tokens) {
|
|
|
795
679
|
const {
|
|
796
680
|
content
|
|
797
681
|
} = token;
|
|
798
|
-
|
|
799
682
|
if (typeof content === 'string') {
|
|
800
683
|
nodes.push($createCodeHighlightNode(content, token.type));
|
|
801
684
|
} else if (Array.isArray(content) && content.length === 1 && typeof content[0] === 'string') {
|
|
@@ -806,98 +689,83 @@ function getHighlightNodes(tokens) {
|
|
|
806
689
|
}
|
|
807
690
|
});
|
|
808
691
|
return nodes;
|
|
809
|
-
}
|
|
810
|
-
// position as before.
|
|
811
|
-
|
|
692
|
+
}
|
|
812
693
|
|
|
694
|
+
// Wrapping update function into selection retainer, that tries to keep cursor at the same
|
|
695
|
+
// position as before.
|
|
813
696
|
function updateAndRetainSelection(nodeKey, updateFn) {
|
|
814
697
|
const node = lexical.$getNodeByKey(nodeKey);
|
|
815
|
-
|
|
816
698
|
if (!$isCodeNode(node) || !node.isAttached()) {
|
|
817
699
|
return;
|
|
818
700
|
}
|
|
819
|
-
|
|
820
|
-
|
|
701
|
+
const selection = lexical.$getSelection();
|
|
702
|
+
// If it's not range selection (or null selection) there's no need to change it,
|
|
821
703
|
// but we can still run highlighting logic
|
|
822
|
-
|
|
823
704
|
if (!lexical.$isRangeSelection(selection)) {
|
|
824
705
|
updateFn();
|
|
825
706
|
return;
|
|
826
707
|
}
|
|
827
|
-
|
|
828
708
|
const anchor = selection.anchor;
|
|
829
709
|
const anchorOffset = anchor.offset;
|
|
830
710
|
const isNewLineAnchor = anchor.type === 'element' && lexical.$isLineBreakNode(node.getChildAtIndex(anchor.offset - 1));
|
|
831
|
-
let textOffset = 0;
|
|
711
|
+
let textOffset = 0;
|
|
832
712
|
|
|
713
|
+
// Calculating previous text offset (all text node prior to anchor + anchor own text offset)
|
|
833
714
|
if (!isNewLineAnchor) {
|
|
834
715
|
const anchorNode = anchor.getNode();
|
|
835
716
|
textOffset = anchorOffset + anchorNode.getPreviousSiblings().reduce((offset, _node) => {
|
|
836
717
|
return offset + _node.getTextContentSize();
|
|
837
718
|
}, 0);
|
|
838
719
|
}
|
|
839
|
-
|
|
840
720
|
const hasChanges = updateFn();
|
|
841
|
-
|
|
842
721
|
if (!hasChanges) {
|
|
843
722
|
return;
|
|
844
|
-
}
|
|
845
|
-
// selection will be within text node (code highlight node)
|
|
846
|
-
|
|
723
|
+
}
|
|
847
724
|
|
|
725
|
+
// Non-text anchors only happen for line breaks, otherwise
|
|
726
|
+
// selection will be within text node (code highlight node)
|
|
848
727
|
if (isNewLineAnchor) {
|
|
849
728
|
anchor.getNode().select(anchorOffset, anchorOffset);
|
|
850
729
|
return;
|
|
851
|
-
}
|
|
852
|
-
// and looking for a position of original text offset
|
|
853
|
-
|
|
730
|
+
}
|
|
854
731
|
|
|
732
|
+
// If it was non-element anchor then we walk through child nodes
|
|
733
|
+
// and looking for a position of original text offset
|
|
855
734
|
node.getChildren().some(_node => {
|
|
856
735
|
const isText = lexical.$isTextNode(_node);
|
|
857
|
-
|
|
858
736
|
if (isText || lexical.$isLineBreakNode(_node)) {
|
|
859
737
|
const textContentSize = _node.getTextContentSize();
|
|
860
|
-
|
|
861
738
|
if (isText && textContentSize >= textOffset) {
|
|
862
739
|
_node.select(textOffset, textOffset);
|
|
863
|
-
|
|
864
740
|
return true;
|
|
865
741
|
}
|
|
866
|
-
|
|
867
742
|
textOffset -= textContentSize;
|
|
868
743
|
}
|
|
869
|
-
|
|
870
744
|
return false;
|
|
871
745
|
});
|
|
872
|
-
}
|
|
873
|
-
// that needs to be replaced with `nodes` (subset of nextNodes) to make prevNodes equal to nextNodes.
|
|
874
|
-
|
|
746
|
+
}
|
|
875
747
|
|
|
748
|
+
// Finds minimal diff range between two nodes lists. It returns from/to range boundaries of prevNodes
|
|
749
|
+
// that needs to be replaced with `nodes` (subset of nextNodes) to make prevNodes equal to nextNodes.
|
|
876
750
|
function getDiffRange(prevNodes, nextNodes) {
|
|
877
751
|
let leadingMatch = 0;
|
|
878
|
-
|
|
879
752
|
while (leadingMatch < prevNodes.length) {
|
|
880
753
|
if (!isEqual(prevNodes[leadingMatch], nextNodes[leadingMatch])) {
|
|
881
754
|
break;
|
|
882
755
|
}
|
|
883
|
-
|
|
884
756
|
leadingMatch++;
|
|
885
757
|
}
|
|
886
|
-
|
|
887
758
|
const prevNodesLength = prevNodes.length;
|
|
888
759
|
const nextNodesLength = nextNodes.length;
|
|
889
760
|
const maxTrailingMatch = Math.min(prevNodesLength, nextNodesLength) - leadingMatch;
|
|
890
761
|
let trailingMatch = 0;
|
|
891
|
-
|
|
892
762
|
while (trailingMatch < maxTrailingMatch) {
|
|
893
763
|
trailingMatch++;
|
|
894
|
-
|
|
895
764
|
if (!isEqual(prevNodes[prevNodesLength - trailingMatch], nextNodes[nextNodesLength - trailingMatch])) {
|
|
896
765
|
trailingMatch--;
|
|
897
766
|
break;
|
|
898
767
|
}
|
|
899
768
|
}
|
|
900
|
-
|
|
901
769
|
const from = leadingMatch;
|
|
902
770
|
const to = prevNodesLength - trailingMatch;
|
|
903
771
|
const nodesForReplacement = nextNodes.slice(leadingMatch, nextNodesLength - trailingMatch);
|
|
@@ -907,59 +775,45 @@ function getDiffRange(prevNodes, nextNodes) {
|
|
|
907
775
|
to
|
|
908
776
|
};
|
|
909
777
|
}
|
|
910
|
-
|
|
911
778
|
function isEqual(nodeA, nodeB) {
|
|
912
779
|
// Only checking for code higlight nodes and linebreaks. If it's regular text node
|
|
913
780
|
// returning false so that it's transformed into code highlight node
|
|
914
781
|
if ($isCodeHighlightNode(nodeA) && $isCodeHighlightNode(nodeB)) {
|
|
915
782
|
return nodeA.__text === nodeB.__text && nodeA.__highlightType === nodeB.__highlightType;
|
|
916
783
|
}
|
|
917
|
-
|
|
918
784
|
if (lexical.$isLineBreakNode(nodeA) && lexical.$isLineBreakNode(nodeB)) {
|
|
919
785
|
return true;
|
|
920
786
|
}
|
|
921
|
-
|
|
922
787
|
return false;
|
|
923
788
|
}
|
|
924
|
-
|
|
925
789
|
function handleMultilineIndent(type) {
|
|
926
790
|
const selection = lexical.$getSelection();
|
|
927
|
-
|
|
928
791
|
if (!lexical.$isRangeSelection(selection) || selection.isCollapsed()) {
|
|
929
792
|
return false;
|
|
930
|
-
}
|
|
931
|
-
|
|
793
|
+
}
|
|
932
794
|
|
|
795
|
+
// Only run multiline indent logic on selections exclusively composed of code highlights and linebreaks
|
|
933
796
|
const nodes = selection.getNodes();
|
|
934
|
-
|
|
935
797
|
for (let i = 0; i < nodes.length; i++) {
|
|
936
798
|
const node = nodes[i];
|
|
937
|
-
|
|
938
799
|
if (!$isCodeHighlightNode(node) && !lexical.$isLineBreakNode(node)) {
|
|
939
800
|
return false;
|
|
940
801
|
}
|
|
941
802
|
}
|
|
942
|
-
|
|
943
803
|
const startOfLine = getFirstCodeHighlightNodeOfLine(nodes[0]);
|
|
944
|
-
|
|
945
804
|
if (startOfLine != null) {
|
|
946
805
|
doIndent(startOfLine, type);
|
|
947
806
|
}
|
|
948
|
-
|
|
949
807
|
for (let i = 1; i < nodes.length; i++) {
|
|
950
808
|
const node = nodes[i];
|
|
951
|
-
|
|
952
809
|
if (lexical.$isLineBreakNode(nodes[i - 1]) && $isCodeHighlightNode(node)) {
|
|
953
810
|
doIndent(node, type);
|
|
954
811
|
}
|
|
955
812
|
}
|
|
956
|
-
|
|
957
813
|
return true;
|
|
958
814
|
}
|
|
959
|
-
|
|
960
815
|
function doIndent(node, type) {
|
|
961
816
|
const text = node.getTextContent();
|
|
962
|
-
|
|
963
817
|
if (type === lexical.INDENT_CONTENT_COMMAND) {
|
|
964
818
|
// If the codeblock node doesn't start with whitespace, we don't want to
|
|
965
819
|
// naively prepend a '\t'; Prism will then mangle all of our nodes when
|
|
@@ -984,17 +838,15 @@ function doIndent(node, type) {
|
|
|
984
838
|
}
|
|
985
839
|
}
|
|
986
840
|
}
|
|
987
|
-
|
|
988
841
|
function handleShiftLines(type, event) {
|
|
989
842
|
// We only care about the alt+arrow keys
|
|
990
843
|
const selection = lexical.$getSelection();
|
|
991
|
-
|
|
992
844
|
if (!lexical.$isRangeSelection(selection)) {
|
|
993
845
|
return false;
|
|
994
|
-
}
|
|
995
|
-
// So first, get the anchor and the focus, then get their nodes
|
|
996
|
-
|
|
846
|
+
}
|
|
997
847
|
|
|
848
|
+
// I'm not quite sure why, but it seems like calling anchor.getNode() collapses the selection here
|
|
849
|
+
// So first, get the anchor and the focus, then get their nodes
|
|
998
850
|
const {
|
|
999
851
|
anchor,
|
|
1000
852
|
focus
|
|
@@ -1003,21 +855,19 @@ function handleShiftLines(type, event) {
|
|
|
1003
855
|
const focusOffset = focus.offset;
|
|
1004
856
|
const anchorNode = anchor.getNode();
|
|
1005
857
|
const focusNode = focus.getNode();
|
|
1006
|
-
const arrowIsUp = type === lexical.KEY_ARROW_UP_COMMAND;
|
|
858
|
+
const arrowIsUp = type === lexical.KEY_ARROW_UP_COMMAND;
|
|
1007
859
|
|
|
860
|
+
// Ensure the selection is within the codeblock
|
|
1008
861
|
if (!$isCodeHighlightNode(anchorNode) || !$isCodeHighlightNode(focusNode)) {
|
|
1009
862
|
return false;
|
|
1010
863
|
}
|
|
1011
|
-
|
|
1012
864
|
if (!event.altKey) {
|
|
1013
865
|
// Handle moving selection out of the code block, given there are no
|
|
1014
866
|
// sibling thats can natively take the selection.
|
|
1015
867
|
if (selection.isCollapsed()) {
|
|
1016
868
|
const codeNode = anchorNode.getParentOrThrow();
|
|
1017
|
-
|
|
1018
869
|
if (arrowIsUp && anchorOffset === 0 && anchorNode.getPreviousSibling() === null) {
|
|
1019
870
|
const codeNodeSibling = codeNode.getPreviousSibling();
|
|
1020
|
-
|
|
1021
871
|
if (codeNodeSibling === null) {
|
|
1022
872
|
codeNode.selectPrevious();
|
|
1023
873
|
event.preventDefault();
|
|
@@ -1025,7 +875,6 @@ function handleShiftLines(type, event) {
|
|
|
1025
875
|
}
|
|
1026
876
|
} else if (!arrowIsUp && anchorOffset === anchorNode.getTextContentSize() && anchorNode.getNextSibling() === null) {
|
|
1027
877
|
const codeNodeSibling = codeNode.getNextSibling();
|
|
1028
|
-
|
|
1029
878
|
if (codeNodeSibling === null) {
|
|
1030
879
|
codeNode.selectNext();
|
|
1031
880
|
event.preventDefault();
|
|
@@ -1033,50 +882,39 @@ function handleShiftLines(type, event) {
|
|
|
1033
882
|
}
|
|
1034
883
|
}
|
|
1035
884
|
}
|
|
1036
|
-
|
|
1037
885
|
return false;
|
|
1038
886
|
}
|
|
1039
|
-
|
|
1040
887
|
const start = getFirstCodeHighlightNodeOfLine(anchorNode);
|
|
1041
888
|
const end = getLastCodeHighlightNodeOfLine(focusNode);
|
|
1042
|
-
|
|
1043
889
|
if (start == null || end == null) {
|
|
1044
890
|
return false;
|
|
1045
891
|
}
|
|
1046
|
-
|
|
1047
892
|
const range = start.getNodesBetween(end);
|
|
1048
|
-
|
|
1049
893
|
for (let i = 0; i < range.length; i++) {
|
|
1050
894
|
const node = range[i];
|
|
1051
|
-
|
|
1052
895
|
if (!$isCodeHighlightNode(node) && !lexical.$isLineBreakNode(node)) {
|
|
1053
896
|
return false;
|
|
1054
897
|
}
|
|
1055
|
-
}
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// After this point, we know the selection is within the codeblock. We may not be able to
|
|
1056
901
|
// actually move the lines around, but we want to return true either way to prevent
|
|
1057
902
|
// the event's default behavior
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
903
|
event.preventDefault();
|
|
1061
904
|
event.stopPropagation(); // required to stop cursor movement under Firefox
|
|
1062
905
|
|
|
1063
906
|
const linebreak = arrowIsUp ? start.getPreviousSibling() : end.getNextSibling();
|
|
1064
|
-
|
|
1065
907
|
if (!lexical.$isLineBreakNode(linebreak)) {
|
|
1066
908
|
return true;
|
|
1067
909
|
}
|
|
1068
|
-
|
|
1069
910
|
const sibling = arrowIsUp ? linebreak.getPreviousSibling() : linebreak.getNextSibling();
|
|
1070
|
-
|
|
1071
911
|
if (sibling == null) {
|
|
1072
912
|
return true;
|
|
1073
913
|
}
|
|
1074
|
-
|
|
1075
914
|
const maybeInsertionPoint = arrowIsUp ? getFirstCodeHighlightNodeOfLine(sibling) : getLastCodeHighlightNodeOfLine(sibling);
|
|
1076
915
|
let insertionPoint = maybeInsertionPoint != null ? maybeInsertionPoint : sibling;
|
|
1077
916
|
linebreak.remove();
|
|
1078
917
|
range.forEach(node => node.remove());
|
|
1079
|
-
|
|
1080
918
|
if (type === lexical.KEY_ARROW_UP_COMMAND) {
|
|
1081
919
|
range.forEach(node => insertionPoint.insertBefore(node));
|
|
1082
920
|
insertionPoint.insertBefore(linebreak);
|
|
@@ -1088,18 +926,14 @@ function handleShiftLines(type, event) {
|
|
|
1088
926
|
insertionPoint = node;
|
|
1089
927
|
});
|
|
1090
928
|
}
|
|
1091
|
-
|
|
1092
929
|
selection.setTextNodeRange(anchorNode, anchorOffset, focusNode, focusOffset);
|
|
1093
930
|
return true;
|
|
1094
931
|
}
|
|
1095
|
-
|
|
1096
932
|
function handleMoveTo(type, event) {
|
|
1097
933
|
const selection = lexical.$getSelection();
|
|
1098
|
-
|
|
1099
934
|
if (!lexical.$isRangeSelection(selection)) {
|
|
1100
935
|
return false;
|
|
1101
936
|
}
|
|
1102
|
-
|
|
1103
937
|
const {
|
|
1104
938
|
anchor,
|
|
1105
939
|
focus
|
|
@@ -1107,14 +941,11 @@ function handleMoveTo(type, event) {
|
|
|
1107
941
|
const anchorNode = anchor.getNode();
|
|
1108
942
|
const focusNode = focus.getNode();
|
|
1109
943
|
const isMoveToStart = type === lexical.MOVE_TO_START;
|
|
1110
|
-
|
|
1111
944
|
if (!$isCodeHighlightNode(anchorNode) || !$isCodeHighlightNode(focusNode)) {
|
|
1112
945
|
return false;
|
|
1113
946
|
}
|
|
1114
|
-
|
|
1115
947
|
let node;
|
|
1116
948
|
let offset;
|
|
1117
|
-
|
|
1118
949
|
if (isMoveToStart) {
|
|
1119
950
|
({
|
|
1120
951
|
node,
|
|
@@ -1126,31 +957,25 @@ function handleMoveTo(type, event) {
|
|
|
1126
957
|
offset
|
|
1127
958
|
} = getEndOfCodeInLine(focusNode));
|
|
1128
959
|
}
|
|
1129
|
-
|
|
1130
960
|
if (node !== null && offset !== -1) {
|
|
1131
961
|
selection.setTextNodeRange(node, offset, node, offset);
|
|
1132
962
|
}
|
|
1133
|
-
|
|
1134
963
|
event.preventDefault();
|
|
1135
964
|
event.stopPropagation();
|
|
1136
965
|
return true;
|
|
1137
966
|
}
|
|
1138
|
-
|
|
1139
967
|
function registerCodeHighlighting(editor, tokenizer) {
|
|
1140
968
|
if (!editor.hasNodes([CodeNode, CodeHighlightNode])) {
|
|
1141
969
|
throw new Error('CodeHighlightPlugin: CodeNode or CodeHighlightNode not registered on editor');
|
|
1142
970
|
}
|
|
1143
|
-
|
|
1144
971
|
if (tokenizer == null) {
|
|
1145
972
|
tokenizer = PrismTokenizer;
|
|
1146
973
|
}
|
|
1147
|
-
|
|
1148
974
|
return utils.mergeRegister(editor.registerMutationListener(CodeNode, mutations => {
|
|
1149
975
|
editor.update(() => {
|
|
1150
976
|
for (const [key, type] of mutations) {
|
|
1151
977
|
if (type !== 'destroyed') {
|
|
1152
978
|
const node = lexical.$getNodeByKey(key);
|
|
1153
|
-
|
|
1154
979
|
if (node !== null) {
|
|
1155
980
|
updateCodeGutter(node, editor);
|
|
1156
981
|
}
|
package/package.json
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"code"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.7.
|
|
11
|
+
"version": "0.7.9",
|
|
12
12
|
"main": "LexicalCode.js",
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"lexical": "0.7.
|
|
14
|
+
"lexical": "0.7.9"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@lexical/utils": "0.7.
|
|
17
|
+
"@lexical/utils": "0.7.9",
|
|
18
18
|
"prismjs": "^1.27.0"
|
|
19
19
|
},
|
|
20
20
|
"repository": {
|