2024-08-18 23:51:08 +08:00
|
|
|
import {LexicalNode, Spread} from "lexical";
|
|
|
|
import type {SerializedElementNode} from "lexical/nodes/LexicalElementNode";
|
2024-09-21 20:00:16 +08:00
|
|
|
import {el, sizeToPixels} from "../utils/dom";
|
2024-08-18 23:51:08 +08:00
|
|
|
|
|
|
|
export type CommonBlockAlignment = 'left' | 'right' | 'center' | 'justify' | '';
|
|
|
|
const validAlignments: CommonBlockAlignment[] = ['left', 'right', 'center', 'justify'];
|
|
|
|
|
2024-09-21 20:00:16 +08:00
|
|
|
type EditorNodeDirection = 'ltr' | 'rtl' | null;
|
|
|
|
|
2024-08-18 23:51:08 +08:00
|
|
|
export type SerializedCommonBlockNode = Spread<{
|
|
|
|
id: string;
|
|
|
|
alignment: CommonBlockAlignment;
|
2024-09-10 22:55:46 +08:00
|
|
|
inset: number;
|
2024-08-18 23:51:08 +08:00
|
|
|
}, SerializedElementNode>
|
|
|
|
|
|
|
|
export interface NodeHasAlignment {
|
|
|
|
readonly __alignment: CommonBlockAlignment;
|
|
|
|
setAlignment(alignment: CommonBlockAlignment): void;
|
|
|
|
getAlignment(): CommonBlockAlignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface NodeHasId {
|
|
|
|
readonly __id: string;
|
|
|
|
setId(id: string): void;
|
|
|
|
getId(): string;
|
|
|
|
}
|
|
|
|
|
2024-09-10 22:55:46 +08:00
|
|
|
export interface NodeHasInset {
|
|
|
|
readonly __inset: number;
|
|
|
|
setInset(inset: number): void;
|
|
|
|
getInset(): number;
|
|
|
|
}
|
|
|
|
|
2024-09-21 20:00:16 +08:00
|
|
|
export interface NodeHasDirection {
|
|
|
|
readonly __dir: EditorNodeDirection;
|
|
|
|
setDirection(direction: EditorNodeDirection): void;
|
|
|
|
getDirection(): EditorNodeDirection;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface CommonBlockInterface extends NodeHasId, NodeHasAlignment, NodeHasInset, NodeHasDirection {}
|
2024-08-18 23:51:08 +08:00
|
|
|
|
|
|
|
export function extractAlignmentFromElement(element: HTMLElement): CommonBlockAlignment {
|
|
|
|
const textAlignStyle: string = element.style.textAlign || '';
|
|
|
|
if (validAlignments.includes(textAlignStyle as CommonBlockAlignment)) {
|
|
|
|
return textAlignStyle as CommonBlockAlignment;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (element.classList.contains('align-left')) {
|
|
|
|
return 'left';
|
|
|
|
} else if (element.classList.contains('align-right')) {
|
|
|
|
return 'right'
|
|
|
|
} else if (element.classList.contains('align-center')) {
|
|
|
|
return 'center'
|
|
|
|
} else if (element.classList.contains('align-justify')) {
|
|
|
|
return 'justify'
|
|
|
|
}
|
|
|
|
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
|
2024-09-10 22:55:46 +08:00
|
|
|
export function extractInsetFromElement(element: HTMLElement): number {
|
|
|
|
const elemPadding: string = element.style.paddingLeft || '0';
|
|
|
|
return sizeToPixels(elemPadding);
|
|
|
|
}
|
|
|
|
|
2024-09-22 19:07:24 +08:00
|
|
|
export function extractDirectionFromElement(element: HTMLElement): EditorNodeDirection {
|
2024-09-21 20:00:16 +08:00
|
|
|
const elemDir = (element.dir || '').toLowerCase();
|
|
|
|
if (elemDir === 'rtl' || elemDir === 'ltr') {
|
|
|
|
return elemDir;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2024-08-18 23:51:08 +08:00
|
|
|
export function setCommonBlockPropsFromElement(element: HTMLElement, node: CommonBlockInterface): void {
|
|
|
|
if (element.id) {
|
|
|
|
node.setId(element.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
node.setAlignment(extractAlignmentFromElement(element));
|
2024-09-10 22:55:46 +08:00
|
|
|
node.setInset(extractInsetFromElement(element));
|
2024-09-21 20:00:16 +08:00
|
|
|
node.setDirection(extractDirectionFromElement(element));
|
2024-08-18 23:51:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function commonPropertiesDifferent(nodeA: CommonBlockInterface, nodeB: CommonBlockInterface): boolean {
|
|
|
|
return nodeA.__id !== nodeB.__id ||
|
2024-09-10 22:55:46 +08:00
|
|
|
nodeA.__alignment !== nodeB.__alignment ||
|
2024-09-21 20:00:16 +08:00
|
|
|
nodeA.__inset !== nodeB.__inset ||
|
|
|
|
nodeA.__dir !== nodeB.__dir;
|
2024-08-18 23:51:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function updateElementWithCommonBlockProps(element: HTMLElement, node: CommonBlockInterface): void {
|
|
|
|
if (node.__id) {
|
|
|
|
element.setAttribute('id', node.__id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (node.__alignment) {
|
|
|
|
element.classList.add('align-' + node.__alignment);
|
|
|
|
}
|
2024-09-10 22:55:46 +08:00
|
|
|
|
|
|
|
if (node.__inset) {
|
|
|
|
element.style.paddingLeft = `${node.__inset}px`;
|
|
|
|
}
|
2024-09-21 20:00:16 +08:00
|
|
|
|
|
|
|
if (node.__dir) {
|
|
|
|
element.dir = node.__dir;
|
|
|
|
}
|
2024-09-10 22:55:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function deserializeCommonBlockNode(serializedNode: SerializedCommonBlockNode, node: CommonBlockInterface): void {
|
|
|
|
node.setId(serializedNode.id);
|
|
|
|
node.setAlignment(serializedNode.alignment);
|
|
|
|
node.setInset(serializedNode.inset);
|
2024-09-21 20:00:16 +08:00
|
|
|
node.setDirection(serializedNode.direction);
|
2024-09-08 20:37:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface NodeHasSize {
|
|
|
|
setHeight(height: number): void;
|
|
|
|
setWidth(width: number): void;
|
|
|
|
getHeight(): number;
|
|
|
|
getWidth(): number;
|
2024-08-18 23:51:08 +08:00
|
|
|
}
|