Skip to content

Commit 213a86e

Browse files
authored
Merge pull request #5415 from BookStackApp/more_lexical_fixes
Further Lexical Fixes
2 parents 5c15f4a + 2b74642 commit 213a86e

35 files changed

+569
-237
lines changed

lang/en/editor.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
'cancel' => 'Cancel',
1414
'save' => 'Save',
1515
'close' => 'Close',
16+
'apply' => 'Apply',
1617
'undo' => 'Undo',
1718
'redo' => 'Redo',
1819
'left' => 'Left',
@@ -147,6 +148,7 @@
147148
'url' => 'URL',
148149
'text_to_display' => 'Text to display',
149150
'title' => 'Title',
151+
'browse_links' => 'Browse links',
150152
'open_link' => 'Open link',
151153
'open_link_in' => 'Open link in...',
152154
'open_link_current' => 'Current window',
Lines changed: 10 additions & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading

resources/js/wysiwyg/lexical/core/LexicalCommands.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import type {
1010
BaseSelection,
11-
ElementFormatType,
1211
LexicalCommand,
1312
LexicalNode,
1413
TextFormatType,
@@ -91,8 +90,6 @@ export const OUTDENT_CONTENT_COMMAND: LexicalCommand<void> = createCommand(
9190
);
9291
export const DROP_COMMAND: LexicalCommand<DragEvent> =
9392
createCommand('DROP_COMMAND');
94-
export const FORMAT_ELEMENT_COMMAND: LexicalCommand<ElementFormatType> =
95-
createCommand('FORMAT_ELEMENT_COMMAND');
9693
export const DRAGSTART_COMMAND: LexicalCommand<DragEvent> =
9794
createCommand('DRAGSTART_COMMAND');
9895
export const DRAGOVER_COMMAND: LexicalCommand<DragEvent> =

resources/js/wysiwyg/lexical/core/LexicalConstants.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
*
77
*/
88

9-
import type {ElementFormatType} from './nodes/LexicalElementNode';
109
import type {
1110
TextDetailType,
1211
TextFormatType,
@@ -111,27 +110,6 @@ export const DETAIL_TYPE_TO_DETAIL: Record<TextDetailType | string, number> = {
111110
unmergeable: IS_UNMERGEABLE,
112111
};
113112

114-
export const ELEMENT_TYPE_TO_FORMAT: Record<
115-
Exclude<ElementFormatType, ''>,
116-
number
117-
> = {
118-
center: IS_ALIGN_CENTER,
119-
end: IS_ALIGN_END,
120-
justify: IS_ALIGN_JUSTIFY,
121-
left: IS_ALIGN_LEFT,
122-
right: IS_ALIGN_RIGHT,
123-
start: IS_ALIGN_START,
124-
};
125-
126-
export const ELEMENT_FORMAT_TO_TYPE: Record<number, ElementFormatType> = {
127-
[IS_ALIGN_CENTER]: 'center',
128-
[IS_ALIGN_END]: 'end',
129-
[IS_ALIGN_JUSTIFY]: 'justify',
130-
[IS_ALIGN_LEFT]: 'left',
131-
[IS_ALIGN_RIGHT]: 'right',
132-
[IS_ALIGN_START]: 'start',
133-
};
134-
135113
export const TEXT_MODE_TO_TYPE: Record<TextModeType, 0 | 1 | 2> = {
136114
normal: IS_NORMAL,
137115
segmented: IS_SEGMENTED,

resources/js/wysiwyg/lexical/core/LexicalNode.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ type NodeName = string;
146146
* Output for a DOM conversion.
147147
* Node can be set to 'ignore' to ignore the conversion and handling of the DOMNode
148148
* including all its children.
149+
*
150+
* You can specify a function to run for each converted child (forChild) or on all
151+
* the child nodes after the conversion is complete (after).
152+
* The key difference here is that forChild runs for every deeply nested child node
153+
* of the current node, whereas after will run only once after the
154+
* transformation of the node and all its children is complete.
149155
*/
150156
export type DOMConversionOutput = {
151157
after?: (childLexicalNodes: Array<LexicalNode>) => Array<LexicalNode>;
@@ -1165,6 +1171,16 @@ export class LexicalNode {
11651171
markDirty(): void {
11661172
this.getWritable();
11671173
}
1174+
1175+
/**
1176+
* Insert the DOM of this node into that of the parent.
1177+
* Allows this node to implement custom DOM attachment logic.
1178+
* Boolean result indicates if the insertion was handled by the function.
1179+
* A true return value prevents default insertion logic from taking place.
1180+
*/
1181+
insertDOMIntoParent(nodeDOM: HTMLElement, parentDOM: HTMLElement): boolean {
1182+
return false;
1183+
}
11681184
}
11691185

11701186
function errorOnTypeKlassMismatch(

resources/js/wysiwyg/lexical/core/LexicalReconciler.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,21 @@ function $createNode(
171171
}
172172

173173
if (parentDOM !== null) {
174-
if (insertDOM != null) {
175-
parentDOM.insertBefore(dom, insertDOM);
176-
} else {
177-
// @ts-expect-error: internal field
178-
const possibleLineBreak = parentDOM.__lexicalLineBreak;
179174

180-
if (possibleLineBreak != null) {
181-
parentDOM.insertBefore(dom, possibleLineBreak);
175+
const inserted = node?.insertDOMIntoParent(dom, parentDOM);
176+
177+
if (!inserted) {
178+
if (insertDOM != null) {
179+
parentDOM.insertBefore(dom, insertDOM);
182180
} else {
183-
parentDOM.appendChild(dom);
181+
// @ts-expect-error: internal field
182+
const possibleLineBreak = parentDOM.__lexicalLineBreak;
183+
184+
if (possibleLineBreak != null) {
185+
parentDOM.insertBefore(dom, possibleLineBreak);
186+
} else {
187+
parentDOM.appendChild(dom);
188+
}
184189
}
185190
}
186191
}

resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ import {QuoteNode} from "@lexical/rich-text/LexicalQuoteNode";
3737
import {DetailsNode} from "@lexical/rich-text/LexicalDetailsNode";
3838
import {EditorUiContext} from "../../../../ui/framework/core";
3939
import {EditorUIManager} from "../../../../ui/framework/manager";
40-
import {turtle} from "@codemirror/legacy-modes/mode/turtle";
41-
4240

4341
type TestEnv = {
4442
readonly container: HTMLDivElement;
@@ -47,6 +45,9 @@ type TestEnv = {
4745
readonly innerHTML: string;
4846
};
4947

48+
/**
49+
* @deprecated - Consider using `createTestContext` instead within the test case.
50+
*/
5051
export function initializeUnitTest(
5152
runTests: (testEnv: TestEnv) => void,
5253
editorConfig: CreateEditorArgs = {namespace: 'test', theme: {}},
@@ -795,6 +796,30 @@ export function expectNodeShapeToMatch(editor: LexicalEditor, expected: nodeShap
795796
expect(shape.children).toMatchObject(expected);
796797
}
797798

799+
/**
800+
* Expect a given prop within the JSON editor state structure to be the given value.
801+
* Uses dot notation for the provided `propPath`. Example:
802+
* 0.5.cat => First child, Sixth child, cat property
803+
*/
804+
export function expectEditorStateJSONPropToEqual(editor: LexicalEditor, propPath: string, expected: any) {
805+
let currentItem: any = editor.getEditorState().toJSON().root;
806+
let currentPath = [];
807+
const pathParts = propPath.split('.');
808+
809+
for (const part of pathParts) {
810+
currentPath.push(part);
811+
const childAccess = Number.isInteger(Number(part)) && Array.isArray(currentItem.children);
812+
const target = childAccess ? currentItem.children : currentItem;
813+
814+
if (typeof target[part] === 'undefined') {
815+
throw new Error(`Could not resolve editor state at path ${currentPath.join('.')}`)
816+
}
817+
currentItem = target[part];
818+
}
819+
820+
expect(currentItem).toBe(expected);
821+
}
822+
798823
function formatHtml(s: string): string {
799824
return s.replace(/>\s+</g, '><').replace(/\s*\n\s*/g, ' ').trim();
800825
}

resources/js/wysiwyg/lexical/core/index.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,12 @@ export type {
4949
} from './LexicalNode';
5050
export type {
5151
BaseSelection,
52-
ElementPointType as ElementPoint,
5352
NodeSelection,
5453
Point,
5554
PointType,
5655
RangeSelection,
57-
TextPointType as TextPoint,
5856
} from './LexicalSelection';
5957
export type {
60-
ElementFormatType,
6158
SerializedElementNode,
6259
} from './nodes/LexicalElementNode';
6360
export type {SerializedRootNode} from './nodes/LexicalRootNode';
@@ -87,7 +84,6 @@ export {
8784
DRAGSTART_COMMAND,
8885
DROP_COMMAND,
8986
FOCUS_COMMAND,
90-
FORMAT_ELEMENT_COMMAND,
9187
FORMAT_TEXT_COMMAND,
9288
INDENT_CONTENT_COMMAND,
9389
INSERT_LINE_BREAK_COMMAND,

resources/js/wysiwyg/lexical/core/nodes/LexicalElementNode.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ export type SerializedElementNode<
4646
SerializedLexicalNode
4747
>;
4848

49-
export type ElementFormatType =
50-
| 'left'
51-
| 'start'
52-
| 'center'
53-
| 'right'
54-
| 'end'
55-
| 'justify'
56-
| '';
57-
5849
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
5950
export interface ElementNode {
6051
getTopLevelElement(): ElementNode | null;

0 commit comments

Comments
 (0)