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.
// @ts-ignore
window.debugEditorState = () => {
// @ts-ignore
window.debugEditorState = () => {
- console.log(editor.getEditorState().toJSON());
+ return editor.getEditorState().toJSON();
};
registerCommonNodeMutationListeners(context);
};
registerCommonNodeMutationListeners(context);
lastNode instanceof ParagraphNode &&
lastNode.getChildrenSize() === 0
) {
lastNode instanceof ParagraphNode &&
lastNode.getChildrenSize() === 0
) {
+ selection.format = lastNode.getTextFormat();
selection.style = lastNode.getTextStyle();
} else {
selection.format = 0;
selection.style = lastNode.getTextStyle();
} else {
selection.format = 0;
LexicalNode,
NodeKey,
} from '../LexicalNode';
LexicalNode,
NodeKey,
} from '../LexicalNode';
-import type {RangeSelection} from 'lexical';
+import {RangeSelection, TEXT_TYPE_TO_FORMAT, TextFormatType} from 'lexical';
import {
$applyNodeReplacement,
import {
$applyNodeReplacement,
export type SerializedParagraphNode = Spread<
{
export type SerializedParagraphNode = Spread<
{
textStyle: string;
},
SerializedCommonBlockNode
textStyle: string;
},
SerializedCommonBlockNode
export class ParagraphNode extends CommonBlockNode {
['constructor']!: KlassConstructor<typeof ParagraphNode>;
/** @internal */
export class ParagraphNode extends CommonBlockNode {
['constructor']!: KlassConstructor<typeof ParagraphNode>;
/** @internal */
__textStyle: string;
constructor(key?: NodeKey) {
super(key);
__textStyle: string;
constructor(key?: NodeKey) {
super(key);
+ getTextFormat(): number {
+ const self = this.getLatest();
+ return self.__textFormat;
+ }
+
+ setTextFormat(type: number): this {
+ const self = this.getWritable();
+ self.__textFormat = type;
+ return self;
+ }
+
+ hasTextFormat(type: TextFormatType): boolean {
+ const formatFlag = TEXT_TYPE_TO_FORMAT[type];
+ return (this.getTextFormat() & formatFlag) !== 0;
+ }
+
getTextStyle(): string {
const self = this.getLatest();
return self.__textStyle;
getTextStyle(): string {
const self = this.getLatest();
return self.__textStyle;
afterCloneFrom(prevNode: this) {
super.afterCloneFrom(prevNode);
afterCloneFrom(prevNode: this) {
super.afterCloneFrom(prevNode);
+ this.__textFormat = prevNode.__textFormat;
this.__textStyle = prevNode.__textStyle;
copyCommonBlockProperties(prevNode, this);
}
this.__textStyle = prevNode.__textStyle;
copyCommonBlockProperties(prevNode, this);
}
static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode {
const node = $createParagraphNode();
deserializeCommonBlockNode(serializedNode, node);
static importJSON(serializedNode: SerializedParagraphNode): ParagraphNode {
const node = $createParagraphNode();
deserializeCommonBlockNode(serializedNode, node);
+ node.setTextFormat(serializedNode.textFormat);
return node;
}
exportJSON(): SerializedParagraphNode {
return {
...super.exportJSON(),
return node;
}
exportJSON(): SerializedParagraphNode {
return {
...super.exportJSON(),
+ textFormat: this.getTextFormat(),
textStyle: this.getTextStyle(),
type: 'paragraph',
version: 1,
textStyle: this.getTextStyle(),
type: 'paragraph',
version: 1,
restoreSelection: boolean,
): ParagraphNode {
const newElement = $createParagraphNode();
restoreSelection: boolean,
): ParagraphNode {
const newElement = $createParagraphNode();
+ newElement.setTextFormat(rangeSelection.format);
newElement.setTextStyle(rangeSelection.style);
const direction = this.getDirection();
newElement.setDirection(direction);
newElement.setTextStyle(rangeSelection.style);
const direction = this.getDirection();
newElement.setDirection(direction);
$createParagraphNode, $createRangeSelection,
$getRoot,
$getSelection, $isBlockElementNode, $isDecoratorNode,
$createParagraphNode, $createRangeSelection,
$getRoot,
$getSelection, $isBlockElementNode, $isDecoratorNode,
+ $isElementNode, $isParagraphNode,
$isTextNode,
$setSelection,
BaseSelection, DecoratorNode,
$isTextNode,
$setSelection,
BaseSelection, DecoratorNode,
- for (const node of selection.getNodes()) {
+ // Check text nodes
+ const nodes = selection.getNodes();
+ for (const node of nodes) {
if ($isTextNode(node) && node.hasFormat(format)) {
return true;
}
}
if ($isTextNode(node) && node.hasFormat(format)) {
return true;
}
}
+ // If we're in an empty paragraph, check the paragraph format
+ if (nodes.length === 1 && $isParagraphNode(nodes[0]) && nodes[0].hasTextFormat(format)) {
+ return true;
+ }
+