lexical 0.14.3 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Lexical.dev.js CHANGED
@@ -1666,6 +1666,7 @@ function $garbageCollectDetachedNodes(prevEditorState, editorState, dirtyLeaves,
1666
1666
  */
1667
1667
  let subTreeTextContent = '';
1668
1668
  let subTreeDirectionedTextContent = '';
1669
+ let subTreeTextFormat = null;
1669
1670
  let editorTextContent = '';
1670
1671
  let activeEditorConfig;
1671
1672
  let activeEditor$1;
@@ -1836,6 +1837,10 @@ function createChildren(children, element, _startIndex, endIndex, dom, insertDOM
1836
1837
  let startIndex = _startIndex;
1837
1838
  for (; startIndex <= endIndex; ++startIndex) {
1838
1839
  createNode(children[startIndex], dom, insertDOM);
1840
+ const node = activeNextNodeMap.get(children[startIndex]);
1841
+ if (node !== null && subTreeTextFormat === null && $isTextNode(node)) {
1842
+ subTreeTextFormat = node.getFormat();
1843
+ }
1839
1844
  }
1840
1845
  if ($textContentRequiresDoubleLinebreakAtEnd(element)) {
1841
1846
  subTreeTextContent += DOUBLE_LINE_BREAK;
@@ -1871,6 +1876,11 @@ function reconcileElementTerminatingLineBreak(prevElement, nextElement, dom) {
1871
1876
  dom.appendChild(element);
1872
1877
  }
1873
1878
  }
1879
+ function reconcileParagraphFormat(element) {
1880
+ if ($isParagraphNode(element) && subTreeTextFormat != null && subTreeTextFormat !== element.__textFormat) {
1881
+ element.setTextFormat(subTreeTextFormat);
1882
+ }
1883
+ }
1874
1884
  function reconcileBlockDirection(element, dom) {
1875
1885
  const previousSubTreeDirectionTextContent =
1876
1886
  // @ts-expect-error: internal field
@@ -1930,9 +1940,12 @@ function reconcileBlockDirection(element, dom) {
1930
1940
  function reconcileChildrenWithDirection(prevElement, nextElement, dom) {
1931
1941
  const previousSubTreeDirectionTextContent = subTreeDirectionedTextContent;
1932
1942
  subTreeDirectionedTextContent = '';
1943
+ subTreeTextFormat = null;
1933
1944
  reconcileChildren(prevElement, nextElement, dom);
1934
1945
  reconcileBlockDirection(nextElement, dom);
1946
+ reconcileParagraphFormat(nextElement);
1935
1947
  subTreeDirectionedTextContent = previousSubTreeDirectionTextContent;
1948
+ subTreeTextFormat = null;
1936
1949
  }
1937
1950
  function createChildrenArray(element, nodeMap) {
1938
1951
  const children = [];
@@ -1965,6 +1978,10 @@ function reconcileChildren(prevElement, nextElement, dom) {
1965
1978
  dom.replaceChild(replacementDOM, lastDOM);
1966
1979
  destroyNode(prevFirstChildKey, null);
1967
1980
  }
1981
+ const nextChildNode = activeNextNodeMap.get(nextFrstChildKey);
1982
+ if (subTreeTextFormat === null && $isTextNode(nextChildNode)) {
1983
+ subTreeTextFormat = nextChildNode.getFormat();
1984
+ }
1968
1985
  } else {
1969
1986
  const prevChildren = createChildrenArray(prevElement, activePrevNodeMap);
1970
1987
  const nextChildren = createChildrenArray(nextElement, activeNextNodeMap);
@@ -2168,6 +2185,10 @@ function reconcileNodeChildren(nextElement, prevChildren, nextChildren, prevChil
2168
2185
  nextIndex++;
2169
2186
  }
2170
2187
  }
2188
+ const node = activeNextNodeMap.get(nextKey);
2189
+ if (node !== null && subTreeTextFormat === null && $isTextNode(node)) {
2190
+ subTreeTextFormat = node.getFormat();
2191
+ }
2171
2192
  }
2172
2193
  const appendNewChildren = prevIndex > prevEndIndex;
2173
2194
  const removeOldChildren = nextIndex > nextEndIndex;
@@ -2377,7 +2398,12 @@ function onSelectionChange(domSelection, editor, isActive) {
2377
2398
  selection.format = anchorNode.getFormat();
2378
2399
  selection.style = anchorNode.getStyle();
2379
2400
  } else if (anchor.type === 'element' && !isRootTextContentEmpty) {
2380
- selection.format = 0;
2401
+ const lastNode = anchor.getNode();
2402
+ if (lastNode instanceof ParagraphNode && lastNode.getChildrenSize() === 0) {
2403
+ selection.format = lastNode.getTextFormat();
2404
+ } else {
2405
+ selection.format = 0;
2406
+ }
2381
2407
  selection.style = '';
2382
2408
  }
2383
2409
  }
@@ -3048,7 +3074,7 @@ function addRootElementEvents(rootElement, editor) {
3048
3074
  // between all editor instances.
3049
3075
  const doc = rootElement.ownerDocument;
3050
3076
  const documentRootElementsCount = rootElementsRegistered.get(doc);
3051
- if (documentRootElementsCount === undefined) {
3077
+ if (documentRootElementsCount === undefined || documentRootElementsCount < 1) {
3052
3078
  doc.addEventListener('selectionchange', onDocumentSelectionChange);
3053
3079
  }
3054
3080
  rootElementsRegistered.set(doc, documentRootElementsCount || 0 + 1);
@@ -3110,7 +3136,7 @@ function removeRootElementEvents(rootElement) {
3110
3136
  } // We only want to have a single global selectionchange event handler, shared
3111
3137
  // between all editor instances.
3112
3138
  rootElementsRegistered.set(doc, documentRootElementsCount - 1);
3113
- if (documentRootElementsCount === 1) {
3139
+ if (rootElementsRegistered.get(doc) === 0) {
3114
3140
  doc.removeEventListener('selectionchange', onDocumentSelectionChange);
3115
3141
  }
3116
3142
 
@@ -3711,6 +3737,9 @@ class LexicalNode {
3711
3737
  mutableNode.__next = latestNode.__next;
3712
3738
  mutableNode.__prev = latestNode.__prev;
3713
3739
  if ($isElementNode(latestNode) && $isElementNode(mutableNode)) {
3740
+ if ($isParagraphNode(latestNode) && $isParagraphNode(mutableNode)) {
3741
+ mutableNode.__textFormat = latestNode.__textFormat;
3742
+ }
3714
3743
  mutableNode.__first = latestNode.__first;
3715
3744
  mutableNode.__last = latestNode.__last;
3716
3745
  mutableNode.__size = latestNode.__size;
@@ -4716,7 +4745,7 @@ class TextNode extends LexicalNode {
4716
4745
  * Sets the node detail to the provided TextDetailType or 32-bit integer. Note that the TextDetailType
4717
4746
  * version of the argument can only specify one detail value and doing so will remove all other detail values that
4718
4747
  * may be applied to the node. For toggling behavior, consider using {@link TextNode.toggleDirectionless}
4719
- * or {@link TextNode.togglerUnmergeable}
4748
+ * or {@link TextNode.toggleUnmergeable}
4720
4749
  *
4721
4750
  * @param detail - TextDetailType or 32-bit integer representing the node detail.
4722
4751
  *
@@ -5074,16 +5103,18 @@ class TextNode extends LexicalNode {
5074
5103
  function convertSpanElement(domNode) {
5075
5104
  // domNode is a <span> since we matched it by nodeName
5076
5105
  const span = domNode;
5106
+ const style = span.style;
5107
+ const fontWeight = style.fontWeight;
5077
5108
  // Google Docs uses span tags + font-weight for bold text
5078
- const hasBoldFontWeight = span.style.fontWeight === '700';
5109
+ const hasBoldFontWeight = fontWeight === '700' || fontWeight === 'bold';
5079
5110
  // Google Docs uses span tags + text-decoration: line-through for strikethrough text
5080
- const hasLinethroughTextDecoration = span.style.textDecoration === 'line-through';
5111
+ const hasLinethroughTextDecoration = style.textDecoration === 'line-through';
5081
5112
  // Google Docs uses span tags + font-style for italic text
5082
- const hasItalicFontStyle = span.style.fontStyle === 'italic';
5113
+ const hasItalicFontStyle = style.fontStyle === 'italic';
5083
5114
  // Google Docs uses span tags + text-decoration: underline for underline text
5084
- const hasUnderlineTextDecoration = span.style.textDecoration === 'underline';
5115
+ const hasUnderlineTextDecoration = style.textDecoration === 'underline';
5085
5116
  // Google Docs uses span tags + vertical-align to specify subscript and superscript
5086
- const verticalAlign = span.style.verticalAlign;
5117
+ const verticalAlign = style.verticalAlign;
5087
5118
  return {
5088
5119
  forChild: lexicalNode => {
5089
5120
  if (!$isTextNode(lexicalNode)) {
@@ -8728,9 +8759,28 @@ class EditorState {
8728
8759
  */
8729
8760
  /** @noInheritDoc */
8730
8761
  class ParagraphNode extends ElementNode {
8762
+ /** @internal */
8763
+
8764
+ constructor(key) {
8765
+ super(key);
8766
+ this.__textFormat = 0;
8767
+ }
8731
8768
  static getType() {
8732
8769
  return 'paragraph';
8733
8770
  }
8771
+ getTextFormat() {
8772
+ const self = this.getLatest();
8773
+ return self.__textFormat;
8774
+ }
8775
+ setTextFormat(type) {
8776
+ const self = this.getWritable();
8777
+ self.__textFormat = type;
8778
+ return self;
8779
+ }
8780
+ hasTextFormat(type) {
8781
+ const formatFlag = TEXT_TYPE_TO_FORMAT[type];
8782
+ return (this.getTextFormat() & formatFlag) !== 0;
8783
+ }
8734
8784
  static clone(node) {
8735
8785
  return new ParagraphNode(node.__key);
8736
8786
  }
@@ -8787,11 +8837,13 @@ class ParagraphNode extends ElementNode {
8787
8837
  node.setFormat(serializedNode.format);
8788
8838
  node.setIndent(serializedNode.indent);
8789
8839
  node.setDirection(serializedNode.direction);
8840
+ node.setTextFormat(serializedNode.textFormat);
8790
8841
  return node;
8791
8842
  }
8792
8843
  exportJSON() {
8793
8844
  return {
8794
8845
  ...super.exportJSON(),
8846
+ textFormat: this.getTextFormat(),
8795
8847
  type: 'paragraph',
8796
8848
  version: 1
8797
8849
  };
@@ -8799,10 +8851,12 @@ class ParagraphNode extends ElementNode {
8799
8851
 
8800
8852
  // Mutation
8801
8853
 
8802
- insertNewAfter(_, restoreSelection) {
8854
+ insertNewAfter(rangeSelection, restoreSelection) {
8803
8855
  const newElement = $createParagraphNode();
8856
+ newElement.setTextFormat(rangeSelection.format);
8804
8857
  const direction = this.getDirection();
8805
8858
  newElement.setDirection(direction);
8859
+ newElement.setFormat(this.getFormatType());
8806
8860
  this.insertAfter(newElement, restoreSelection);
8807
8861
  return newElement;
8808
8862
  }
package/Lexical.dev.mjs CHANGED
@@ -1664,6 +1664,7 @@ function $garbageCollectDetachedNodes(prevEditorState, editorState, dirtyLeaves,
1664
1664
  */
1665
1665
  let subTreeTextContent = '';
1666
1666
  let subTreeDirectionedTextContent = '';
1667
+ let subTreeTextFormat = null;
1667
1668
  let editorTextContent = '';
1668
1669
  let activeEditorConfig;
1669
1670
  let activeEditor$1;
@@ -1834,6 +1835,10 @@ function createChildren(children, element, _startIndex, endIndex, dom, insertDOM
1834
1835
  let startIndex = _startIndex;
1835
1836
  for (; startIndex <= endIndex; ++startIndex) {
1836
1837
  createNode(children[startIndex], dom, insertDOM);
1838
+ const node = activeNextNodeMap.get(children[startIndex]);
1839
+ if (node !== null && subTreeTextFormat === null && $isTextNode(node)) {
1840
+ subTreeTextFormat = node.getFormat();
1841
+ }
1837
1842
  }
1838
1843
  if ($textContentRequiresDoubleLinebreakAtEnd(element)) {
1839
1844
  subTreeTextContent += DOUBLE_LINE_BREAK;
@@ -1869,6 +1874,11 @@ function reconcileElementTerminatingLineBreak(prevElement, nextElement, dom) {
1869
1874
  dom.appendChild(element);
1870
1875
  }
1871
1876
  }
1877
+ function reconcileParagraphFormat(element) {
1878
+ if ($isParagraphNode(element) && subTreeTextFormat != null && subTreeTextFormat !== element.__textFormat) {
1879
+ element.setTextFormat(subTreeTextFormat);
1880
+ }
1881
+ }
1872
1882
  function reconcileBlockDirection(element, dom) {
1873
1883
  const previousSubTreeDirectionTextContent =
1874
1884
  // @ts-expect-error: internal field
@@ -1928,9 +1938,12 @@ function reconcileBlockDirection(element, dom) {
1928
1938
  function reconcileChildrenWithDirection(prevElement, nextElement, dom) {
1929
1939
  const previousSubTreeDirectionTextContent = subTreeDirectionedTextContent;
1930
1940
  subTreeDirectionedTextContent = '';
1941
+ subTreeTextFormat = null;
1931
1942
  reconcileChildren(prevElement, nextElement, dom);
1932
1943
  reconcileBlockDirection(nextElement, dom);
1944
+ reconcileParagraphFormat(nextElement);
1933
1945
  subTreeDirectionedTextContent = previousSubTreeDirectionTextContent;
1946
+ subTreeTextFormat = null;
1934
1947
  }
1935
1948
  function createChildrenArray(element, nodeMap) {
1936
1949
  const children = [];
@@ -1963,6 +1976,10 @@ function reconcileChildren(prevElement, nextElement, dom) {
1963
1976
  dom.replaceChild(replacementDOM, lastDOM);
1964
1977
  destroyNode(prevFirstChildKey, null);
1965
1978
  }
1979
+ const nextChildNode = activeNextNodeMap.get(nextFrstChildKey);
1980
+ if (subTreeTextFormat === null && $isTextNode(nextChildNode)) {
1981
+ subTreeTextFormat = nextChildNode.getFormat();
1982
+ }
1966
1983
  } else {
1967
1984
  const prevChildren = createChildrenArray(prevElement, activePrevNodeMap);
1968
1985
  const nextChildren = createChildrenArray(nextElement, activeNextNodeMap);
@@ -2166,6 +2183,10 @@ function reconcileNodeChildren(nextElement, prevChildren, nextChildren, prevChil
2166
2183
  nextIndex++;
2167
2184
  }
2168
2185
  }
2186
+ const node = activeNextNodeMap.get(nextKey);
2187
+ if (node !== null && subTreeTextFormat === null && $isTextNode(node)) {
2188
+ subTreeTextFormat = node.getFormat();
2189
+ }
2169
2190
  }
2170
2191
  const appendNewChildren = prevIndex > prevEndIndex;
2171
2192
  const removeOldChildren = nextIndex > nextEndIndex;
@@ -2375,7 +2396,12 @@ function onSelectionChange(domSelection, editor, isActive) {
2375
2396
  selection.format = anchorNode.getFormat();
2376
2397
  selection.style = anchorNode.getStyle();
2377
2398
  } else if (anchor.type === 'element' && !isRootTextContentEmpty) {
2378
- selection.format = 0;
2399
+ const lastNode = anchor.getNode();
2400
+ if (lastNode instanceof ParagraphNode && lastNode.getChildrenSize() === 0) {
2401
+ selection.format = lastNode.getTextFormat();
2402
+ } else {
2403
+ selection.format = 0;
2404
+ }
2379
2405
  selection.style = '';
2380
2406
  }
2381
2407
  }
@@ -3046,7 +3072,7 @@ function addRootElementEvents(rootElement, editor) {
3046
3072
  // between all editor instances.
3047
3073
  const doc = rootElement.ownerDocument;
3048
3074
  const documentRootElementsCount = rootElementsRegistered.get(doc);
3049
- if (documentRootElementsCount === undefined) {
3075
+ if (documentRootElementsCount === undefined || documentRootElementsCount < 1) {
3050
3076
  doc.addEventListener('selectionchange', onDocumentSelectionChange);
3051
3077
  }
3052
3078
  rootElementsRegistered.set(doc, documentRootElementsCount || 0 + 1);
@@ -3108,7 +3134,7 @@ function removeRootElementEvents(rootElement) {
3108
3134
  } // We only want to have a single global selectionchange event handler, shared
3109
3135
  // between all editor instances.
3110
3136
  rootElementsRegistered.set(doc, documentRootElementsCount - 1);
3111
- if (documentRootElementsCount === 1) {
3137
+ if (rootElementsRegistered.get(doc) === 0) {
3112
3138
  doc.removeEventListener('selectionchange', onDocumentSelectionChange);
3113
3139
  }
3114
3140
 
@@ -3709,6 +3735,9 @@ class LexicalNode {
3709
3735
  mutableNode.__next = latestNode.__next;
3710
3736
  mutableNode.__prev = latestNode.__prev;
3711
3737
  if ($isElementNode(latestNode) && $isElementNode(mutableNode)) {
3738
+ if ($isParagraphNode(latestNode) && $isParagraphNode(mutableNode)) {
3739
+ mutableNode.__textFormat = latestNode.__textFormat;
3740
+ }
3712
3741
  mutableNode.__first = latestNode.__first;
3713
3742
  mutableNode.__last = latestNode.__last;
3714
3743
  mutableNode.__size = latestNode.__size;
@@ -4714,7 +4743,7 @@ class TextNode extends LexicalNode {
4714
4743
  * Sets the node detail to the provided TextDetailType or 32-bit integer. Note that the TextDetailType
4715
4744
  * version of the argument can only specify one detail value and doing so will remove all other detail values that
4716
4745
  * may be applied to the node. For toggling behavior, consider using {@link TextNode.toggleDirectionless}
4717
- * or {@link TextNode.togglerUnmergeable}
4746
+ * or {@link TextNode.toggleUnmergeable}
4718
4747
  *
4719
4748
  * @param detail - TextDetailType or 32-bit integer representing the node detail.
4720
4749
  *
@@ -5072,16 +5101,18 @@ class TextNode extends LexicalNode {
5072
5101
  function convertSpanElement(domNode) {
5073
5102
  // domNode is a <span> since we matched it by nodeName
5074
5103
  const span = domNode;
5104
+ const style = span.style;
5105
+ const fontWeight = style.fontWeight;
5075
5106
  // Google Docs uses span tags + font-weight for bold text
5076
- const hasBoldFontWeight = span.style.fontWeight === '700';
5107
+ const hasBoldFontWeight = fontWeight === '700' || fontWeight === 'bold';
5077
5108
  // Google Docs uses span tags + text-decoration: line-through for strikethrough text
5078
- const hasLinethroughTextDecoration = span.style.textDecoration === 'line-through';
5109
+ const hasLinethroughTextDecoration = style.textDecoration === 'line-through';
5079
5110
  // Google Docs uses span tags + font-style for italic text
5080
- const hasItalicFontStyle = span.style.fontStyle === 'italic';
5111
+ const hasItalicFontStyle = style.fontStyle === 'italic';
5081
5112
  // Google Docs uses span tags + text-decoration: underline for underline text
5082
- const hasUnderlineTextDecoration = span.style.textDecoration === 'underline';
5113
+ const hasUnderlineTextDecoration = style.textDecoration === 'underline';
5083
5114
  // Google Docs uses span tags + vertical-align to specify subscript and superscript
5084
- const verticalAlign = span.style.verticalAlign;
5115
+ const verticalAlign = style.verticalAlign;
5085
5116
  return {
5086
5117
  forChild: lexicalNode => {
5087
5118
  if (!$isTextNode(lexicalNode)) {
@@ -8726,9 +8757,28 @@ class EditorState {
8726
8757
  */
8727
8758
  /** @noInheritDoc */
8728
8759
  class ParagraphNode extends ElementNode {
8760
+ /** @internal */
8761
+
8762
+ constructor(key) {
8763
+ super(key);
8764
+ this.__textFormat = 0;
8765
+ }
8729
8766
  static getType() {
8730
8767
  return 'paragraph';
8731
8768
  }
8769
+ getTextFormat() {
8770
+ const self = this.getLatest();
8771
+ return self.__textFormat;
8772
+ }
8773
+ setTextFormat(type) {
8774
+ const self = this.getWritable();
8775
+ self.__textFormat = type;
8776
+ return self;
8777
+ }
8778
+ hasTextFormat(type) {
8779
+ const formatFlag = TEXT_TYPE_TO_FORMAT[type];
8780
+ return (this.getTextFormat() & formatFlag) !== 0;
8781
+ }
8732
8782
  static clone(node) {
8733
8783
  return new ParagraphNode(node.__key);
8734
8784
  }
@@ -8785,11 +8835,13 @@ class ParagraphNode extends ElementNode {
8785
8835
  node.setFormat(serializedNode.format);
8786
8836
  node.setIndent(serializedNode.indent);
8787
8837
  node.setDirection(serializedNode.direction);
8838
+ node.setTextFormat(serializedNode.textFormat);
8788
8839
  return node;
8789
8840
  }
8790
8841
  exportJSON() {
8791
8842
  return {
8792
8843
  ...super.exportJSON(),
8844
+ textFormat: this.getTextFormat(),
8793
8845
  type: 'paragraph',
8794
8846
  version: 1
8795
8847
  };
@@ -8797,10 +8849,12 @@ class ParagraphNode extends ElementNode {
8797
8849
 
8798
8850
  // Mutation
8799
8851
 
8800
- insertNewAfter(_, restoreSelection) {
8852
+ insertNewAfter(rangeSelection, restoreSelection) {
8801
8853
  const newElement = $createParagraphNode();
8854
+ newElement.setTextFormat(rangeSelection.format);
8802
8855
  const direction = this.getDirection();
8803
8856
  newElement.setDirection(direction);
8857
+ newElement.setFormat(this.getFormatType());
8804
8858
  this.insertAfter(newElement, restoreSelection);
8805
8859
  return newElement;
8806
8860
  }
package/Lexical.js.flow CHANGED
@@ -782,7 +782,10 @@ declare export class ParagraphNode extends ElementNode {
782
782
  constructor(key?: NodeKey): void;
783
783
  createDOM(config: EditorConfig): HTMLElement;
784
784
  updateDOM(prevNode: ParagraphNode, dom: HTMLElement): boolean;
785
- insertNewAfter(): ParagraphNode;
785
+ insertNewAfter(
786
+ selection: RangeSelection,
787
+ restoreSelection?: boolean,
788
+ ): ParagraphNode;
786
789
  collapseAtStart(): boolean;
787
790
  static importJSON(
788
791
  serializedParagraphNode: SerializedParagraphNode,