Skip to content

Commit 8b062d4

Browse files
committed
Lexical: Fixed strange paragraph formatting behaviour
Formatting was not persisted on empty paragraphs, and was instead based upon last format encountered in selection. This was due to overly-hasty removal of other formatting code, which this got caught it. Restored required parts from prior codebase. Also updated inline format button active indicator to reflect formats using the above, so correct buttons are shown as active even when just in an empty paragraph.
1 parent 717b516 commit 8b062d4

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed

resources/js/wysiwyg/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export function createPageEditorInstance(container: HTMLElement, htmlContent: st
8484

8585
// @ts-ignore
8686
window.debugEditorState = () => {
87-
console.log(editor.getEditorState().toJSON());
87+
return editor.getEditorState().toJSON();
8888
};
8989

9090
registerCommonNodeMutationListeners(context);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ function onSelectionChange(
355355
lastNode instanceof ParagraphNode &&
356356
lastNode.getChildrenSize() === 0
357357
) {
358+
selection.format = lastNode.getTextFormat();
358359
selection.style = lastNode.getTextStyle();
359360
} else {
360361
selection.format = 0;

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import type {
1919
LexicalNode,
2020
NodeKey,
2121
} from '../LexicalNode';
22-
import type {RangeSelection} from 'lexical';
22+
import {RangeSelection, TEXT_TYPE_TO_FORMAT, TextFormatType} from 'lexical';
2323

2424
import {
2525
$applyNodeReplacement,
@@ -36,6 +36,7 @@ import {CommonBlockNode, copyCommonBlockProperties, SerializedCommonBlockNode} f
3636

3737
export type SerializedParagraphNode = Spread<
3838
{
39+
textFormat: number;
3940
textStyle: string;
4041
},
4142
SerializedCommonBlockNode
@@ -45,17 +46,35 @@ export type SerializedParagraphNode = Spread<
4546
export class ParagraphNode extends CommonBlockNode {
4647
['constructor']!: KlassConstructor<typeof ParagraphNode>;
4748
/** @internal */
49+
__textFormat: number;
4850
__textStyle: string;
4951

5052
constructor(key?: NodeKey) {
5153
super(key);
54+
this.__textFormat = 0;
5255
this.__textStyle = '';
5356
}
5457

5558
static getType(): string {
5659
return 'paragraph';
5760
}
5861

62+
getTextFormat(): number {
63+
const self = this.getLatest();
64+
return self.__textFormat;
65+
}
66+
67+
setTextFormat(type: number): this {
68+
const self = this.getWritable();
69+
self.__textFormat = type;
70+
return self;
71+
}
72+
73+
hasTextFormat(type: TextFormatType): boolean {
74+
const formatFlag = TEXT_TYPE_TO_FORMAT[type];
75+
return (this.getTextFormat() & formatFlag) !== 0;
76+
}
77+
5978
getTextStyle(): string {
6079
const self = this.getLatest();
6180
return self.__textStyle;
@@ -73,6 +92,7 @@ export class ParagraphNode extends CommonBlockNode {
7392

7493
afterCloneFrom(prevNode: this) {
7594
super.afterCloneFrom(prevNode);
95+
this.__textFormat = prevNode.__textFormat;
7696
this.__textStyle = prevNode.__textStyle;
7797
copyCommonBlockProperties(prevNode, this);
7898
}
@@ -125,12 +145,14 @@ export class ParagraphNode extends CommonBlockNode {
125145
static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode {
126146
const node = $createParagraphNode();
127147
deserializeCommonBlockNode(serializedNode, node);
148+
node.setTextFormat(serializedNode.textFormat);
128149
return node;
129150
}
130151

131152
exportJSON(): SerializedParagraphNode {
132153
return {
133154
...super.exportJSON(),
155+
textFormat: this.getTextFormat(),
134156
textStyle: this.getTextStyle(),
135157
type: 'paragraph',
136158
version: 1,
@@ -144,6 +166,7 @@ export class ParagraphNode extends CommonBlockNode {
144166
restoreSelection: boolean,
145167
): ParagraphNode {
146168
const newElement = $createParagraphNode();
169+
newElement.setTextFormat(rangeSelection.format);
147170
newElement.setTextStyle(rangeSelection.style);
148171
const direction = this.getDirection();
149172
newElement.setDirection(direction);

resources/js/wysiwyg/utils/selection.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
$createParagraphNode, $createRangeSelection,
44
$getRoot,
55
$getSelection, $isBlockElementNode, $isDecoratorNode,
6-
$isElementNode,
6+
$isElementNode, $isParagraphNode,
77
$isTextNode,
88
$setSelection,
99
BaseSelection, DecoratorNode,
@@ -60,12 +60,19 @@ export function $selectionContainsTextFormat(selection: BaseSelection | null, fo
6060
return false;
6161
}
6262

63-
for (const node of selection.getNodes()) {
63+
// Check text nodes
64+
const nodes = selection.getNodes();
65+
for (const node of nodes) {
6466
if ($isTextNode(node) && node.hasFormat(format)) {
6567
return true;
6668
}
6769
}
6870

71+
// If we're in an empty paragraph, check the paragraph format
72+
if (nodes.length === 1 && $isParagraphNode(nodes[0]) && nodes[0].hasTextFormat(format)) {
73+
return true;
74+
}
75+
6976
return false;
7077
}
7178

0 commit comments

Comments
 (0)