Skip to content

Commit

Permalink
apply text format to more tags
Browse files Browse the repository at this point in the history
  • Loading branch information
2wheeh committed May 11, 2024
1 parent 4091c45 commit 7f6820a
Showing 1 changed file with 66 additions and 62 deletions.
128 changes: 66 additions & 62 deletions packages/lexical/src/nodes/LexicalTextNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1092,45 +1092,9 @@ function convertSpanElement(domNode: Node): DOMConversionOutput {
// domNode is a <span> since we matched it by nodeName
const span = domNode as HTMLSpanElement;
const style = span.style;
const fontWeight = style.fontWeight;
const textDecoration = style.textDecoration.split(' ');
// Google Docs uses span tags + font-weight for bold text
const hasBoldFontWeight = fontWeight === '700' || fontWeight === 'bold';
// Google Docs uses span tags + text-decoration: line-through for strikethrough text
const hasLinethroughTextDecoration = textDecoration.includes('line-through');
// Google Docs uses span tags + font-style for italic text
const hasItalicFontStyle = style.fontStyle === 'italic';
// Google Docs uses span tags + text-decoration: underline for underline text
const hasUnderlineTextDecoration = textDecoration.includes('underline');
// Google Docs uses span tags + vertical-align to specify subscript and superscript
const verticalAlign = style.verticalAlign;

return {
forChild: (lexicalNode) => {
if (!$isTextNode(lexicalNode)) {
return lexicalNode;
}
if (hasBoldFontWeight) {
lexicalNode.toggleFormat('bold');
}
if (hasLinethroughTextDecoration) {
lexicalNode.toggleFormat('strikethrough');
}
if (hasItalicFontStyle) {
lexicalNode.toggleFormat('italic');
}
if (hasUnderlineTextDecoration) {
lexicalNode.toggleFormat('underline');
}
if (verticalAlign === 'sub') {
lexicalNode.toggleFormat('subscript');
}
if (verticalAlign === 'super') {
lexicalNode.toggleFormat('superscript');
}

return lexicalNode;
},
forChild: applyTextFormatFromStyle(style),
node: null,
};
}
Expand All @@ -1140,14 +1104,12 @@ function convertBringAttentionToElement(domNode: Node): DOMConversionOutput {
const b = domNode as HTMLElement;
// Google Docs wraps all copied HTML in a <b> with font-weight normal
const hasNormalFontWeight = b.style.fontWeight === 'normal';
return {
forChild: (lexicalNode) => {
if ($isTextNode(lexicalNode) && !hasNormalFontWeight) {
lexicalNode.toggleFormat('bold');
}

return lexicalNode;
},
return {
forChild: applyTextFormatFromStyle(
b.style,
hasNormalFontWeight ? undefined : 'bold',
),
node: null,
};
}
Expand Down Expand Up @@ -1298,30 +1260,13 @@ function findTextInLine(text: Text, forward: boolean): null | Text {
}
}

const nodeNameToTextFormat: Record<string, TextFormatType> = {
code: 'code',
em: 'italic',
i: 'italic',
s: 'strikethrough',
strong: 'bold',
sub: 'subscript',
sup: 'superscript',
u: 'underline',
};

function convertTextFormatElement(domNode: Node): DOMConversionOutput {
const format = nodeNameToTextFormat[domNode.nodeName.toLowerCase()];
if (format === undefined) {
return {node: null};
}
return {
forChild: (lexicalNode) => {
if ($isTextNode(lexicalNode) && !lexicalNode.hasFormat(format)) {
lexicalNode.toggleFormat(format);
}

return lexicalNode;
},
forChild: applyTextFormatFromStyle((domNode as HTMLElement).style, format),
node: null,
};
}
Expand All @@ -1335,3 +1280,62 @@ export function $isTextNode(
): node is TextNode {
return node instanceof TextNode;
}

const nodeNameToTextFormat: Record<string, TextFormatType> = {
code: 'code',
em: 'italic',
i: 'italic',
s: 'strikethrough',
strong: 'bold',
sub: 'subscript',
sup: 'superscript',
u: 'underline',
};

function applyTextFormatFromStyle(
style: CSSStyleDeclaration,
shouldApply?: TextFormatType,
) {
const fontWeight = style.fontWeight;
const textDecoration = style.textDecoration.split(' ');
// Google Docs uses span tags + font-weight for bold text
const hasBoldFontWeight = fontWeight === '700' || fontWeight === 'bold';
// Google Docs uses span tags + text-decoration: line-through for strikethrough text
const hasLinethroughTextDecoration = textDecoration.includes('line-through');
// Google Docs uses span tags + font-style for italic text
const hasItalicFontStyle = style.fontStyle === 'italic';
// Google Docs uses span tags + text-decoration: underline for underline text
const hasUnderlineTextDecoration = textDecoration.includes('underline');
// Google Docs uses span tags + vertical-align to specify subscript and superscript
const verticalAlign = style.verticalAlign;

return (lexicalNode: LexicalNode) => {
if (!$isTextNode(lexicalNode)) {
return lexicalNode;
}
if (hasBoldFontWeight) {
lexicalNode.toggleFormat('bold');
}
if (hasLinethroughTextDecoration) {
lexicalNode.toggleFormat('strikethrough');
}
if (hasItalicFontStyle) {
lexicalNode.toggleFormat('italic');
}
if (hasUnderlineTextDecoration) {
lexicalNode.toggleFormat('underline');
}
if (verticalAlign === 'sub') {
lexicalNode.toggleFormat('subscript');
}
if (verticalAlign === 'super') {
lexicalNode.toggleFormat('superscript');
}

if (shouldApply && !lexicalNode.hasFormat(shouldApply)) {
lexicalNode.toggleFormat(shouldApply);
}

return lexicalNode;
};
}

0 comments on commit 7f6820a

Please sign in to comment.