@stll/folio-core 0.53.0 → 0.54.1

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.
Files changed (155) hide show
  1. package/dist/ai-edits/apply.js +415 -166
  2. package/dist/ai-edits/batch-claims.d.ts +21 -6
  3. package/dist/ai-edits/batch-claims.js +47 -16
  4. package/dist/ai-edits/headless.d.ts +20 -0
  5. package/dist/ai-edits/headless.js +140 -11
  6. package/dist/ai-edits/pending-suggestions.js +1 -1
  7. package/dist/ai-edits/read.d.ts +5 -3
  8. package/dist/ai-edits/read.js +97 -47
  9. package/dist/ai-edits/revisionStretches.d.ts +17 -0
  10. package/dist/ai-edits/revisionStretches.js +80 -0
  11. package/dist/ai-edits/snapshot.js +3 -2
  12. package/dist/ai-edits/table-cell-mutations.d.ts +3 -1
  13. package/dist/ai-edits/table-cell-mutations.js +2 -1
  14. package/dist/ai-edits/table-row-column-mutations.d.ts +6 -1
  15. package/dist/ai-edits/table-row-column-mutations.js +27 -10
  16. package/dist/compare/content-alignment.d.ts +5 -1
  17. package/dist/compare/content-alignment.js +39 -32
  18. package/dist/compare/inline-provenance.js +1 -1
  19. package/dist/controller/layoutPipeline.js +3 -2
  20. package/dist/docx/archiveInflation.d.ts +127 -0
  21. package/dist/docx/archiveInflation.js +181 -0
  22. package/dist/docx/metadataPrivacy.js +24 -1
  23. package/dist/docx/noteReferenceMark.d.ts +15 -0
  24. package/dist/docx/noteReferenceMark.js +48 -0
  25. package/dist/docx/paragraphParser.js +5 -3
  26. package/dist/docx/paragraphPropertySource.d.ts +1 -1
  27. package/dist/docx/paragraphPropertySource.js +4 -2
  28. package/dist/docx/parser.js +2 -2
  29. package/dist/docx/rezip.js +4 -2
  30. package/dist/docx/selectiveXmlPatch.d.ts +3 -1
  31. package/dist/docx/selectiveXmlPatch.js +81 -3
  32. package/dist/docx/server/boundedArchive.d.ts +8 -13
  33. package/dist/docx/server/boundedArchive.js +70 -59
  34. package/dist/docx/server/extractDocxText.d.ts +8 -2
  35. package/dist/docx/server/extractDocxText.js +2 -2
  36. package/dist/docx/server/validateDocxConformance.d.ts +1 -1
  37. package/dist/docx/server/validateDocxConformance.js +1 -0
  38. package/dist/docx/unzip.d.ts +19 -2
  39. package/dist/docx/unzip.js +135 -24
  40. package/dist/docx/verticalMergeProjection.d.ts +17 -0
  41. package/dist/docx/verticalMergeProjection.js +120 -0
  42. package/dist/fonts/embeddedFonts.js +1 -1
  43. package/dist/i18n/messages/catalogs.gen.d.ts +34 -34
  44. package/dist/i18n/messages/catalogs.gen.js +34 -34
  45. package/dist/i18n/messages/messages.gen.d.ts +2 -2
  46. package/dist/internal/wholeStoryRevisionResolution.js +95 -25
  47. package/dist/layout-engine/measure/measureParagraph.js +2 -2
  48. package/dist/layout-engine/measure/paragraphMeasureShared.d.ts +12 -1
  49. package/dist/layout-engine/measure/paragraphMeasureShared.js +14 -1
  50. package/dist/markdown/escape.d.ts +2 -2
  51. package/dist/markdown/escape.js +4 -5
  52. package/dist/markdown/renderBlock.js +91 -25
  53. package/dist/markdown/renderRuns.d.ts +10 -1
  54. package/dist/markdown/renderRuns.js +320 -59
  55. package/dist/prosemirror/clearRunColor.d.ts +6 -0
  56. package/dist/prosemirror/clearRunColor.js +46 -0
  57. package/dist/prosemirror/commands/comments.js +62 -22
  58. package/dist/prosemirror/commands/formatPainter.js +1 -1
  59. package/dist/prosemirror/commands/hyperlink.js +2 -1
  60. package/dist/prosemirror/commands/propertyChangeScope.d.ts +3 -2
  61. package/dist/prosemirror/commands/propertyChangeScope.js +28 -4
  62. package/dist/prosemirror/commands/resolveAllTableChanges.js +40 -41
  63. package/dist/prosemirror/commands/resolveParagraphProperties.js +33 -8
  64. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +7 -1
  65. package/dist/prosemirror/commands/tableCellMergeResolution.js +39 -20
  66. package/dist/prosemirror/commands/tableMergeFoldDecisions.d.ts +61 -0
  67. package/dist/prosemirror/commands/tableMergeFoldDecisions.js +79 -0
  68. package/dist/prosemirror/containerFinalParagraph.d.ts +11 -5
  69. package/dist/prosemirror/containerFinalParagraph.js +7 -6
  70. package/dist/prosemirror/conversion/fromProseDoc.d.ts +2 -13
  71. package/dist/prosemirror/conversion/fromProseDoc.js +12 -590
  72. package/dist/prosemirror/conversion/toProseDoc.d.ts +1 -13
  73. package/dist/prosemirror/conversion/toProseDoc.js +28 -262
  74. package/dist/prosemirror/documentSchema.d.ts +8 -0
  75. package/dist/prosemirror/documentSchema.js +18 -0
  76. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  77. package/dist/prosemirror/extensions/core/ParagraphExtension.js +104 -63
  78. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +1 -1
  79. package/dist/prosemirror/extensions/features/EmptyParagraphFormatExtension.js +24 -3
  80. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts +20 -0
  81. package/dist/prosemirror/extensions/features/JoinedRunStyleExtension.js +43 -0
  82. package/dist/prosemirror/extensions/features/ListExtension.js +10 -9
  83. package/dist/prosemirror/extensions/features/pastedHeadingStyles.js +1 -1
  84. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +2 -4
  85. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +14 -8
  86. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +8 -4
  87. package/dist/prosemirror/extensions/marks/StrikeExtension.js +2 -2
  88. package/dist/prosemirror/extensions/marks/SubscriptExtension.js +2 -2
  89. package/dist/prosemirror/extensions/marks/SuperscriptExtension.js +2 -2
  90. package/dist/prosemirror/extensions/marks/TextColorExtension.js +4 -3
  91. package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -6
  92. package/dist/prosemirror/extensions/marks/markUtils.js +17 -8
  93. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +3 -1
  94. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +12 -1
  95. package/dist/prosemirror/extensions/nodes/CommentReferenceExtension.js +2 -2
  96. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +5 -3
  97. package/dist/prosemirror/extensions/nodes/TableExtension.js +104 -210
  98. package/dist/prosemirror/extensions/types.d.ts +7 -0
  99. package/dist/prosemirror/hyperlinkRemoval.d.ts +9 -0
  100. package/dist/prosemirror/hyperlinkRemoval.js +129 -0
  101. package/dist/prosemirror/index.d.ts +2 -1
  102. package/dist/prosemirror/index.js +2 -1
  103. package/dist/prosemirror/listNumbering.d.ts +3 -21
  104. package/dist/prosemirror/listNumbering.js +24 -39
  105. package/dist/prosemirror/listRendering.d.ts +29 -0
  106. package/dist/prosemirror/listRendering.js +26 -0
  107. package/dist/prosemirror/markupViewNotes.d.ts +8 -0
  108. package/dist/prosemirror/markupViewNotes.js +49 -0
  109. package/dist/prosemirror/markupViewProjection.d.ts +3 -1
  110. package/dist/prosemirror/markupViewProjection.js +7 -2
  111. package/dist/prosemirror/noteReferenceReview.d.ts +77 -0
  112. package/dist/prosemirror/noteReferenceReview.js +332 -0
  113. package/dist/prosemirror/paragraphIndentation.js +5 -2
  114. package/dist/prosemirror/paragraphMarkJoin.d.ts +6 -4
  115. package/dist/prosemirror/paragraphMarkJoin.js +21 -19
  116. package/dist/prosemirror/paragraphPropertyCarry.d.ts +64 -0
  117. package/dist/prosemirror/paragraphPropertyCarry.js +155 -0
  118. package/dist/prosemirror/plugins/documentStyleState.d.ts +26 -0
  119. package/dist/prosemirror/plugins/documentStyleState.js +32 -0
  120. package/dist/prosemirror/plugins/documentStyles.d.ts +2 -21
  121. package/dist/prosemirror/plugins/documentStyles.js +66 -29
  122. package/dist/prosemirror/plugins/index.d.ts +2 -1
  123. package/dist/prosemirror/plugins/index.js +2 -1
  124. package/dist/prosemirror/plugins/paragraphStyleResolution.d.ts +15 -0
  125. package/dist/prosemirror/plugins/paragraphStyleResolution.js +230 -0
  126. package/dist/prosemirror/plugins/suggestionMode.d.ts +12 -2
  127. package/dist/prosemirror/plugins/suggestionMode.js +387 -28
  128. package/dist/prosemirror/plugins/templateDirectives.d.ts +6 -0
  129. package/dist/prosemirror/plugins/templateDirectives.js +21 -7
  130. package/dist/prosemirror/plugins/templatePreviewValues.js +14 -21
  131. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +22 -2
  132. package/dist/prosemirror/rebaseParagraphRunFormatting.js +39 -13
  133. package/dist/prosemirror/rebaseParagraphRuns.d.ts +36 -0
  134. package/dist/prosemirror/rebaseParagraphRuns.js +99 -0
  135. package/dist/prosemirror/runFormattingFromMarks.d.ts +18 -0
  136. package/dist/prosemirror/runFormattingFromMarks.js +567 -0
  137. package/dist/prosemirror/runFormattingReconciliation.js +10 -9
  138. package/dist/prosemirror/schema/nodes.d.ts +2 -0
  139. package/dist/prosemirror/styles/paragraphStyleCascade.d.ts +59 -0
  140. package/dist/prosemirror/styles/paragraphStyleCascade.js +145 -0
  141. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +21 -2
  142. package/dist/prosemirror/styles/resolvedStyleAttrs.js +38 -1
  143. package/dist/prosemirror/styles/tableStyleRegions.d.ts +31 -0
  144. package/dist/prosemirror/styles/tableStyleRegions.js +55 -0
  145. package/dist/prosemirror/tableCellPaste.d.ts +74 -0
  146. package/dist/prosemirror/tableCellPaste.js +525 -0
  147. package/dist/prosemirror/tableGridMutation.d.ts +53 -14
  148. package/dist/prosemirror/tableGridMutation.js +166 -18
  149. package/dist/prosemirror/tableRunIn.d.ts +51 -0
  150. package/dist/prosemirror/tableRunIn.js +165 -0
  151. package/dist/prosemirror/textInput.js +11 -2
  152. package/dist/prosemirror/trackedRevisionPath.d.ts +17 -0
  153. package/dist/prosemirror/trackedRevisionPath.js +32 -0
  154. package/dist/server.d.ts +2 -2
  155. package/package.json +6 -6
@@ -1,5 +1,6 @@
1
1
  import { BUILT_IN_STYLE_NAME } from "../../../docx/builtInStyles.js";
2
2
  import { PROSE_PARAGRAPH_SOURCE_TOKEN_ATTR } from "../../../docx/paragraphPropertySource.js";
3
+ import { isStyleSourcedParagraphNumbering } from "../../../internal/paragraphFormattingSerialization.js";
3
4
  import { PARAGRAPH_ALIGNMENT_VALUES } from "../../../types/documentEnumValues.js";
4
5
  import { paragraphToStyle } from "../../../utils/formatToStyle.js";
5
6
  import { collectHeadings } from "../../../utils/headingCollector.js";
@@ -7,12 +8,16 @@ import { tableOfContentsStyleLevel } from "../../../utils/tableOfContentsStyle.j
7
8
  import { expectParagraphAttrs } from "../../attrs/index.js";
8
9
  import { autospacingMatchesBase } from "../../autospacingBase.js";
9
10
  import { removeSectionBreakAtSelection, setSectionBreakType } from "../../commands/sectionBreak.js";
11
+ import { CLEARED_LIST_RENDERING_ATTRS } from "../../listMarker.js";
10
12
  import { directParagraphAlignment } from "../../paragraphAlignment.js";
11
13
  import { directionIsRtl } from "../../paragraphDirection.js";
12
- import { withDirectParagraphSpacing } from "../../paragraphSpacing.js";
13
- import { getDocumentBuiltInStyles } from "../../plugins/documentStyles.js";
14
+ import { directParagraphIndentation } from "../../paragraphIndentation.js";
15
+ import { directParagraphSpacing, withDirectParagraphSpacing } from "../../paragraphSpacing.js";
16
+ import { getDocumentNumbering } from "../../plugins/documentNumbering.js";
17
+ import { getDocumentBuiltInStyles, getDocumentStyleResolver } from "../../plugins/documentStyleState.js";
18
+ import { rebaseParagraphRuns } from "../../rebaseParagraphRuns.js";
14
19
  import { mintSectionProperties, parseSectionBreakType, sectionBreakTypeOf } from "../../sectionCarrier.js";
15
- import { listAttrsFromResolvedStyle, paragraphAttrsFromResolvedStyle } from "../../styles/resolvedStyleAttrs.js";
20
+ import { listAttrsFromResolvedStyle, listLevelIndentAttrPatch, paragraphAttrsFromResolvedStyle } from "../../styles/resolvedStyleAttrs.js";
16
21
  import { createNodeExtension } from "../create.js";
17
22
  import { headingOutlineLevel, paragraphNumberingLevel, paragraphNumberingReferenceId } from "@stll/docx-core/model";
18
23
  import { Fragment } from "prosemirror-model";
@@ -399,6 +404,51 @@ function setParagraphSpacingAttr(side, twips) {
399
404
  return true;
400
405
  };
401
406
  }
407
+ const DIRECT_PARAGRAPH_TOGGLES = [
408
+ "outlineLevel",
409
+ "borders",
410
+ "shading",
411
+ "tabs",
412
+ "keepNext",
413
+ "keepLines",
414
+ "widowControl",
415
+ "pageBreakBefore",
416
+ "contextualSpacing"
417
+ ];
418
+ /** The attrs a paragraph states itself, over whatever style it reads. */
419
+ function directParagraphAttrs(attrs) {
420
+ const direct = {};
421
+ const alignment = directParagraphAlignment(attrs);
422
+ if (alignment !== void 0) direct["alignment"] = alignment;
423
+ const spacing = directParagraphSpacing(attrs);
424
+ for (const key of [
425
+ "spaceBefore",
426
+ "spaceAfter",
427
+ "lineSpacing",
428
+ "lineSpacingRule"
429
+ ]) if (spacing?.[key] !== void 0) direct[key] = spacing[key];
430
+ const indentation = directParagraphIndentation(attrs);
431
+ if (indentation?.indentLeft !== void 0) direct["indentLeft"] = indentation.indentLeft;
432
+ if (indentation?.indentRight !== void 0) direct["indentRight"] = indentation.indentRight;
433
+ if (indentation?.indentFirstLine !== void 0) {
434
+ direct["indentFirstLine"] = Math.abs(indentation.indentFirstLine);
435
+ direct["hangingIndent"] = indentation.hangingIndent === true;
436
+ }
437
+ const original = attrs._originalFormatting;
438
+ for (const key of DIRECT_PARAGRAPH_TOGGLES) if (original?.[key] !== void 0) direct[key] = attrs[key];
439
+ return direct;
440
+ }
441
+ /**
442
+ * The indentation a restyled paragraph still states itself: a field its
443
+ * source stated that the new style's attrs keep a value for. Every other
444
+ * field now reads the style's value, which a save leaves to the style.
445
+ */
446
+ function restyledIndentation(styleAttrs, originalFormatting) {
447
+ const stated = {};
448
+ if (originalFormatting?.indentLeft !== void 0 && typeof styleAttrs.indentLeft === "number") stated.indentLeft = styleAttrs.indentLeft;
449
+ if (originalFormatting?.indentFirstLine !== void 0 && typeof styleAttrs.indentFirstLine === "number") stated.indentFirstLine = styleAttrs.indentFirstLine;
450
+ return stated;
451
+ }
402
452
  function setParagraphAttrsCmd(attrs) {
403
453
  return (state, dispatch) => {
404
454
  const { $from, $to } = state.selection;
@@ -479,9 +529,10 @@ function makeDecreaseIndent(amount = 720) {
479
529
  seen.add(pos);
480
530
  const currentIndent = node.attrs["indentLeft"] || 0;
481
531
  const newIndent = Math.max(0, currentIndent - amount);
532
+ const numbered = paragraphNumberingReferenceId(expectParagraphAttrs(node).numPr ?? void 0) !== void 0;
482
533
  tr = tr.setNodeMarkup(pos, void 0, {
483
534
  ...node.attrs,
484
- indentLeft: newIndent > 0 ? newIndent : null
535
+ indentLeft: newIndent > 0 || numbered ? newIndent : null
485
536
  });
486
537
  }
487
538
  });
@@ -489,79 +540,61 @@ function makeDecreaseIndent(amount = 720) {
489
540
  return true;
490
541
  };
491
542
  }
492
- function makeApplyStyle(schema) {
543
+ function makeApplyStyle() {
493
544
  return (styleId, resolvedAttrs) => (state, dispatch) => {
494
545
  const { $from, $to } = state.selection;
495
546
  if (!dispatch) return true;
496
547
  let tr = state.tr;
497
548
  const seen = /* @__PURE__ */ new Set();
498
- const styleMarks = [];
499
- if (resolvedAttrs?.runFormatting) {
500
- const rpr = resolvedAttrs.runFormatting;
501
- if (rpr.bold && schema.marks["bold"]) styleMarks.push(schema.marks["bold"].create());
502
- if (rpr.italic && schema.marks["italic"]) styleMarks.push(schema.marks["italic"].create());
503
- if (rpr.fontSize && schema.marks["fontSize"]) styleMarks.push(schema.marks["fontSize"].create({ size: rpr.fontSize }));
504
- if (rpr.fontFamily && schema.marks["fontFamily"]) styleMarks.push(schema.marks["fontFamily"].create({
505
- ascii: rpr.fontFamily.ascii,
506
- hAnsi: rpr.fontFamily.hAnsi,
507
- asciiTheme: rpr.fontFamily.asciiTheme
508
- }));
509
- if (rpr.color && !rpr.color.auto && schema.marks["textColor"]) styleMarks.push(schema.marks["textColor"].create({
510
- rgb: rpr.color.rgb,
511
- themeColor: rpr.color.themeColor,
512
- themeTint: rpr.color.themeTint,
513
- themeShade: rpr.color.themeShade
514
- }));
515
- if (rpr.underline && rpr.underline.style !== "none" && schema.marks["underline"]) styleMarks.push(schema.marks["underline"].create({
516
- style: rpr.underline.style,
517
- color: rpr.underline.color
518
- }));
519
- if ((rpr.strike || rpr.doubleStrike) && schema.marks["strike"]) styleMarks.push(schema.marks["strike"].create({ double: rpr.doubleStrike || false }));
520
- }
521
- const styleControlledMarks = [
522
- schema.marks["bold"],
523
- schema.marks["italic"],
524
- schema.marks["fontSize"],
525
- schema.marks["fontFamily"],
526
- schema.marks["textColor"],
527
- schema.marks["underline"],
528
- schema.marks["strike"]
529
- ].filter(Boolean);
530
549
  state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
531
550
  if (node.type.name === "paragraph" && !seen.has(pos)) {
532
551
  seen.add(pos);
533
552
  const newAttrs = {
534
553
  ...node.attrs,
535
554
  styleId,
536
- _tableOfContentsLevel: tableOfContentsStyleLevel({ styleId }) ?? null
555
+ _tableOfContentsLevel: styleId ? tableOfContentsStyleLevel({ styleId }) ?? null : null
537
556
  };
538
557
  if (resolvedAttrs) {
539
- Object.assign(newAttrs, paragraphAttrsFromResolvedStyle(resolvedAttrs, {
540
- styleId,
558
+ const current = expectParagraphAttrs(node);
559
+ const styleAttrs = paragraphAttrsFromResolvedStyle(resolvedAttrs, {
560
+ styleId: styleId ?? "",
541
561
  ...resolvedAttrs.styleName ? { styleName: resolvedAttrs.styleName } : {}
542
- }));
543
- const originalFormatting = {
544
- ...expectParagraphAttrs(node)._originalFormatting,
545
- styleId
546
- };
547
- Reflect.deleteProperty(originalFormatting, "alignment");
548
- newAttrs["_originalFormatting"] = withDirectParagraphSpacing(originalFormatting, void 0);
549
- newAttrs["spacingExplicit"] = null;
562
+ });
563
+ Object.assign(newAttrs, styleAttrs);
564
+ if (!styleId) newAttrs["_tableOfContentsLevel"] = null;
565
+ const originalFormatting = { ...current._originalFormatting };
566
+ if (styleId) originalFormatting.styleId = styleId;
567
+ else Reflect.deleteProperty(originalFormatting, "styleId");
568
+ let restyledOriginal = originalFormatting;
569
+ if (styleId) {
570
+ Reflect.deleteProperty(originalFormatting, "alignment");
571
+ Reflect.deleteProperty(originalFormatting, "outlineLevel");
572
+ restyledOriginal = withDirectParagraphSpacing(originalFormatting, void 0);
573
+ newAttrs["spacingExplicit"] = null;
574
+ } else Object.assign(newAttrs, directParagraphAttrs(current));
575
+ newAttrs["_originalFormatting"] = restyledOriginal ?? null;
550
576
  const listAttrs = listAttrsFromResolvedStyle(resolvedAttrs, resolvedAttrs.numbering);
577
+ const directNumId = current.numPrFromStyle == null ? paragraphNumberingReferenceId(current.numPr ?? void 0) : void 0;
551
578
  if (listAttrs) Object.assign(newAttrs, listAttrs);
579
+ else if (isStyleSourcedParagraphNumbering(current.numPr, current.numPrFromStyle)) Object.assign(newAttrs, CLEARED_LIST_RENDERING_ATTRS, {
580
+ numPr: null,
581
+ numPrFromStyle: null
582
+ });
583
+ else if (directNumId !== void 0) Object.assign(newAttrs, listLevelIndentAttrPatch(restyledIndentation(styleAttrs, restyledOriginal), {
584
+ numId: directNumId,
585
+ ilvl: paragraphNumberingLevel(current.numPr ?? void 0) ?? 0
586
+ }, resolvedAttrs.numbering ?? getDocumentNumbering(state)));
552
587
  }
553
588
  tr = tr.setNodeMarkup(pos, void 0, newAttrs);
554
- if (resolvedAttrs) {
555
- const paragraphStart = pos + 1;
556
- const paragraphEnd = pos + node.nodeSize - 1;
557
- if (paragraphEnd > paragraphStart) {
558
- for (const markType of styleControlledMarks) tr = tr.removeMark(paragraphStart, paragraphEnd, markType);
559
- for (const mark of styleMarks) tr = tr.addMark(paragraphStart, paragraphEnd, mark);
560
- }
561
- }
589
+ rebaseParagraphRuns({
590
+ tr,
591
+ position: pos,
592
+ previous: node,
593
+ styleResolver: getDocumentStyleResolver(state),
594
+ storedMarks: state.storedMarks ?? state.selection.$from.marks()
595
+ });
562
596
  }
563
597
  });
564
- if (styleMarks.length > 0) tr = tr.setStoredMarks(styleMarks);
565
598
  dispatch(tr.scrollIntoView());
566
599
  return true;
567
600
  };
@@ -594,8 +627,8 @@ const ParagraphExtension = createNodeExtension({
594
627
  name: "paragraph",
595
628
  schemaNodeName: "paragraph",
596
629
  nodeSpec: paragraphNodeSpec,
597
- onSchemaReady(ctx) {
598
- const applyStyleFn = makeApplyStyle(ctx.schema);
630
+ onSchemaReady() {
631
+ const applyStyleFn = makeApplyStyle();
599
632
  return { commands: {
600
633
  setAlignment: (alignment) => makeSetAlignment(alignment),
601
634
  alignLeft: () => makeSetAlignment("left"),
@@ -617,10 +650,18 @@ const ParagraphExtension = createNodeExtension({
617
650
  hangingIndent: hanging ?? false
618
651
  }),
619
652
  applyStyle: (styleId, resolvedAttrs) => applyStyleFn(styleId, resolvedAttrs),
620
- clearStyle: () => setParagraphAttrsCmd({
621
- styleId: null,
622
- _tableOfContentsLevel: null
623
- }),
653
+ clearStyle: () => (state, dispatch) => {
654
+ const resolver = getDocumentStyleResolver(state);
655
+ if (!resolver) return applyStyleFn(null)(state, dispatch);
656
+ const resolved = resolver.resolveParagraphStyle(null);
657
+ const styleName = resolver.getDefaultParagraphStyle()?.name;
658
+ return applyStyleFn(null, {
659
+ ...resolved.paragraphFormatting && { paragraphFormatting: resolved.paragraphFormatting },
660
+ ...resolved.runFormatting && { runFormatting: resolved.runFormatting },
661
+ ...styleName && { styleName },
662
+ numbering: getDocumentNumbering(state)
663
+ })(state, dispatch);
664
+ },
624
665
  insertSectionBreak: (breakType) => setSectionBreakType(breakType),
625
666
  removeSectionBreak: () => removeSectionBreakAtSelection,
626
667
  generateTOC: ({ title }) => (state, dispatch) => {
@@ -1,7 +1,7 @@
1
1
  import { mergeTextFormatting } from "../../../utils/textFormattingMerge.js";
2
2
  import { expectCharacterStyleMarkAttrs, expectRunFormattingOverrideMarkAttrs } from "../../attrs/index.js";
3
3
  import { keepSectionBreaksOnSurvivingMarks } from "../../commands/sectionBreak.js";
4
- import { getDocumentStyleResolver } from "../../plugins/documentStyles.js";
4
+ import { getDocumentStyleResolver } from "../../plugins/documentStyleState.js";
5
5
  import { RUN_FORMATTING_MARK_NAMES } from "../../runFormattingMarkNames.js";
6
6
  import { authoredRunFormattingFromAttrs } from "../../runFormattingProvenance.js";
7
7
  import { paragraphAttrsFromResolvedStyle } from "../../styles/resolvedStyleAttrs.js";
@@ -2,6 +2,26 @@ import { createExtension } from "../create.js";
2
2
  import { textFormattingToMarks } from "../marks/markUtils.js";
3
3
  import { Plugin, PluginKey } from "prosemirror-state";
4
4
  //#region src/prosemirror/extensions/features/EmptyParagraphFormatExtension.ts
5
+ /**
6
+ * EmptyParagraphFormat — re-establishes stored marks for an empty styled
7
+ * paragraph so typed text inherits the style's run formatting (bold, color,
8
+ * size, font).
9
+ *
10
+ * Why this exists:
11
+ * An empty paragraph carries its run defaults in the `defaultTextFormatting`
12
+ * attr (set at load by `toProseDoc`, and when a style is applied via
13
+ * `applyStyle`). The visible painter only derives font/size from that attr,
14
+ * so an empty heading renders a correctly sized caret — but typed text only
15
+ * becomes bold/colored if it carries real marks. Those marks live in
16
+ * `storedMarks`, which ProseMirror clears on the next selection change
17
+ * (e.g. when the style picker dropdown returns focus to the editor).
18
+ *
19
+ * This plugin watches for the caret sitting in an empty paragraph with no
20
+ * stored marks and re-derives them from `defaultTextFormatting`, but only
21
+ * when the defaults carry formatting the painter can't reproduce on its own
22
+ * (bold/italic/color/…). Plain body paragraphs (font + size only) are left
23
+ * untouched so ordinary typed text stays mark-free and serializes cleanly.
24
+ */
5
25
  const emptyParagraphFormatKey = new PluginKey("emptyParagraphFormat");
6
26
  /**
7
27
  * Run-formatting properties the painter does NOT reproduce from
@@ -15,7 +35,7 @@ const FONT_ONLY_DEFAULTS = /* @__PURE__ */ new Set(["fontFamily", "fontSize"]);
15
35
  function hasNonFontDefaults(dtf) {
16
36
  return Object.entries(dtf).some(([property, value]) => value !== void 0 && !FONT_ONLY_DEFAULTS.has(property));
17
37
  }
18
- function createEmptyParagraphFormatPlugin(schema) {
38
+ function createEmptyParagraphFormatPlugin() {
19
39
  return new Plugin({
20
40
  key: emptyParagraphFormatKey,
21
41
  appendTransaction(transactions, _oldState, newState) {
@@ -27,6 +47,7 @@ function createEmptyParagraphFormatPlugin(schema) {
27
47
  if (para.type.name !== "paragraph" || para.content.size !== 0) return null;
28
48
  const dtf = para.attrs["defaultTextFormatting"];
29
49
  if (!dtf || !hasNonFontDefaults(dtf)) return null;
50
+ const { schema } = newState;
30
51
  const marks = textFormattingToMarks(dtf, schema);
31
52
  if (dtf.styleId) marks.push(schema.mark("characterStyle", { styleId: dtf.styleId }));
32
53
  if (marks.length === 0) return null;
@@ -38,8 +59,8 @@ function createEmptyParagraphFormatPlugin(schema) {
38
59
  }
39
60
  const EmptyParagraphFormatExtension = createExtension({
40
61
  name: "emptyParagraphFormat",
41
- onSchemaReady(ctx) {
42
- return { plugins: [createEmptyParagraphFormatPlugin(ctx.schema)] };
62
+ onSchemaReady() {
63
+ return { plugins: [createEmptyParagraphFormatPlugin()] };
43
64
  }
44
65
  });
45
66
  //#endregion
@@ -0,0 +1,20 @@
1
+ import { Extension } from "../types.js";
2
+ //#region src/prosemirror/extensions/features/JoinedRunStyleExtension.d.ts
3
+ /**
4
+ * Runs that a join moves into another paragraph take that paragraph's style.
5
+ *
6
+ * Deleting across a paragraph break (Backspace or Delete at the break, a
7
+ * deletion or typing over a selection that spans paragraphs) runs the later
8
+ * paragraph's remaining text on into the earlier one. A run's direct
9
+ * formatting is its own and stays; what the later paragraph's style lent it
10
+ * does not travel, and it reads in the style of the paragraph it now belongs
11
+ * to. The document styles plugin re-reads those runs after an ordinary edit.
12
+ *
13
+ * A transaction that re-reads the runs it moves itself (resolving a tracked
14
+ * change, an operation that merges paragraphs) says so with
15
+ * {@link JOINED_RUNS_RESTYLED_META}, and is left as it is.
16
+ */
17
+ declare const JOINED_RUNS_RESTYLED_META = "joinedRunsRestyled";
18
+ declare const JoinedRunStyleExtension: (options?: Partial<{}> | undefined) => Extension;
19
+ //#endregion
20
+ export { JOINED_RUNS_RESTYLED_META, JoinedRunStyleExtension };
@@ -0,0 +1,43 @@
1
+ import { createExtension } from "../create.js";
2
+ import { Plugin, PluginKey } from "prosemirror-state";
3
+ //#region src/prosemirror/extensions/features/JoinedRunStyleExtension.ts
4
+ /**
5
+ * Runs that a join moves into another paragraph take that paragraph's style.
6
+ *
7
+ * Deleting across a paragraph break (Backspace or Delete at the break, a
8
+ * deletion or typing over a selection that spans paragraphs) runs the later
9
+ * paragraph's remaining text on into the earlier one. A run's direct
10
+ * formatting is its own and stays; what the later paragraph's style lent it
11
+ * does not travel, and it reads in the style of the paragraph it now belongs
12
+ * to. The document styles plugin re-reads those runs after an ordinary edit.
13
+ *
14
+ * A transaction that re-reads the runs it moves itself (resolving a tracked
15
+ * change, an operation that merges paragraphs) says so with
16
+ * {@link JOINED_RUNS_RESTYLED_META}, and is left as it is.
17
+ */
18
+ const JOINED_RUNS_RESTYLED_META = "joinedRunsRestyled";
19
+ const pastedTableEndKey = new PluginKey("pastedTableEnd");
20
+ /**
21
+ * A table pasted over a story's last paragraph leaves that paragraph, emptied,
22
+ * after it: a story ends with a paragraph, and the paste replaced the words,
23
+ * not the break that ends the story. ProseMirror's paste replaces the whole
24
+ * paragraph, so the empty one is put back.
25
+ */
26
+ const createPastedTableEndPlugin = () => new Plugin({
27
+ key: pastedTableEndKey,
28
+ appendTransaction(transactions, oldState, newState) {
29
+ if (!transactions.some((transaction) => transaction.docChanged && transaction.getMeta("uiEvent") === "paste")) return null;
30
+ if (newState.doc.lastChild?.type.spec["tableRole"] !== "table" || oldState.doc.lastChild?.type.name !== "paragraph") return null;
31
+ const paragraph = newState.schema.nodes["paragraph"]?.createAndFill();
32
+ return paragraph ? newState.tr.insert(newState.doc.content.size, paragraph) : null;
33
+ }
34
+ });
35
+ const JoinedRunStyleExtension = createExtension({
36
+ name: "joinedRunStyle",
37
+ defaultOptions: {},
38
+ onSchemaReady() {
39
+ return { plugins: [createPastedTableEndPlugin()] };
40
+ }
41
+ });
42
+ //#endregion
43
+ export { JOINED_RUNS_RESTYLED_META, JoinedRunStyleExtension };
@@ -7,7 +7,7 @@ import { resolveListState } from "../../listState.js";
7
7
  import { removedNumberingAttr } from "../../numberingAttr.js";
8
8
  import { getDocumentNumbering } from "../../plugins/documentNumbering.js";
9
9
  import { SUGGESTION_META, makeRevisionInfo, suggestRangeDeletion } from "../../plugins/suggestionMode.js";
10
- import { listLevelAttrPatch } from "../../styles/resolvedStyleAttrs.js";
10
+ import { listLevelAttrPatch, listLevelIndentRemovalPatch } from "../../styles/resolvedStyleAttrs.js";
11
11
  import { createExtension } from "../create.js";
12
12
  import { goToNextCell, goToPrevCell } from "../nodes/TableExtension.js";
13
13
  import { Priority } from "../types.js";
@@ -27,9 +27,10 @@ function chainCommands(...commands) {
27
27
  return false;
28
28
  };
29
29
  }
30
- function clearListAttrs(attrs) {
30
+ function clearListAttrs(attrs, numbering) {
31
31
  return {
32
32
  ...attrs,
33
+ ...listLevelIndentRemovalPatch(attrs, numbering),
33
34
  numPr: removedNumberingAttr(attrs.numPrFromStyle),
34
35
  ...CLEARED_LIST_RENDERING_ATTRS
35
36
  };
@@ -69,7 +70,7 @@ const numberParagraphs = ({ state, tr, from, to, requests }) => {
69
70
  updates: paragraphsBetween(tr.doc, from, to).map(({ pos, node }) => ({
70
71
  pos,
71
72
  node,
72
- next: listItemAttrs(node.attrs, {
73
+ next: listItemAttrs(expectParagraphAttrs(node), {
73
74
  numId: target.numId,
74
75
  ilvl: paragraphNumberingLevel(expectParagraphAttrs(node).numPr) ?? target.ilvl
75
76
  }, target.numbering)
@@ -92,7 +93,7 @@ function toggleList(intent) {
92
93
  updates: paragraphsBetween(state.doc, $from.pos, $to.pos).filter(({ node }) => isItemOfKind(node)).map(({ pos, node }) => ({
93
94
  pos,
94
95
  node,
95
- next: clearListAttrs(expectParagraphAttrs(node))
96
+ next: clearListAttrs(expectParagraphAttrs(node), getDocumentNumbering(state))
96
97
  }))
97
98
  });
98
99
  else numberParagraphs({
@@ -141,7 +142,7 @@ const decreaseListLevel = (state, dispatch) => {
141
142
  if (!dispatch) return true;
142
143
  const paragraphPos = $from.before($from.depth);
143
144
  if (currentLevel <= 0) dispatch(state.tr.setNodeMarkup(paragraphPos, void 0, {
144
- ...clearListAttrs(attrs),
145
+ ...clearListAttrs(attrs, getDocumentNumbering(state)),
145
146
  indentLeft: null,
146
147
  indentFirstLine: null,
147
148
  hangingIndent: null
@@ -157,7 +158,7 @@ const removeList = (state, dispatch) => {
157
158
  state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
158
159
  if (node.type.name === "paragraph" && hasActiveListNumbering(expectParagraphAttrs(node)) && !seen.has(pos)) {
159
160
  seen.add(pos);
160
- tr = tr.setNodeMarkup(pos, void 0, clearListAttrs(expectParagraphAttrs(node)));
161
+ tr = tr.setNodeMarkup(pos, void 0, clearListAttrs(expectParagraphAttrs(node), getDocumentNumbering(state)));
161
162
  }
162
163
  });
163
164
  dispatch(tr.scrollIntoView());
@@ -197,7 +198,7 @@ function exitListOnEmptyEnter() {
197
198
  updates: [{
198
199
  pos: $from.before(),
199
200
  node: paragraph,
200
- next: clearListAttrs(attrs)
201
+ next: clearListAttrs(attrs, getDocumentNumbering(state))
201
202
  }]
202
203
  });
203
204
  dispatch(tr);
@@ -250,7 +251,7 @@ function backspaceExitList() {
250
251
  updates: [{
251
252
  pos: $from.before(),
252
253
  node: paragraph,
253
- next: clearListAttrs(attrs)
254
+ next: clearListAttrs(attrs, getDocumentNumbering(state))
254
255
  }]
255
256
  });
256
257
  dispatch(tr);
@@ -300,7 +301,7 @@ function decreaseListIndent() {
300
301
  for (const { pos, attrs } of positions) {
301
302
  const currentLevel = attrs.numPr.ilvl ?? 0;
302
303
  if (currentLevel <= 0) tr = tr.setNodeMarkup(pos, void 0, {
303
- ...clearListAttrs(attrs),
304
+ ...clearListAttrs(attrs, getDocumentNumbering(state)),
304
305
  indentLeft: null,
305
306
  indentFirstLine: null,
306
307
  hangingIndent: null
@@ -1,5 +1,5 @@
1
1
  import { readOutlineLevelAttr } from "../../outlineLevelAttr.js";
2
- import { getDocumentBuiltInStyles, getDocumentStyleResolver } from "../../plugins/documentStyles.js";
2
+ import { getDocumentBuiltInStyles, getDocumentStyleResolver } from "../../plugins/documentStyleState.js";
3
3
  import { headingLevelOf } from "@stll/docx-core/model";
4
4
  import { Fragment, Slice } from "prosemirror-model";
5
5
  //#region src/prosemirror/extensions/features/pastedHeadingStyles.ts
@@ -103,10 +103,8 @@ const numberPastedHtmlLists = (slice, view) => {
103
103
  groups.set(hint.group, group);
104
104
  }
105
105
  if (!numbering) panic("Pasted list group has no numbering definition");
106
- result = node.type.create(listItemAttrs({
107
- ...attrs,
108
- _pastedHtmlList: void 0
109
- }, {
106
+ const { _pastedHtmlList: _consumed, ...unhinted } = attrs;
107
+ result = node.type.create(listItemAttrs(unhinted, {
110
108
  numId: group.numId,
111
109
  ilvl: hint.level
112
110
  }, numbering), node.content, node.marks);
@@ -1,7 +1,7 @@
1
1
  import { expectFootnoteRefMarkAttrs } from "../../attrs/index.js";
2
- import { suggestionModeKey } from "../../plugins/suggestionMode.js";
2
+ import { suggestRangeDeletion, suggestionModeKey } from "../../plugins/suggestionMode.js";
3
3
  import { createMarkExtension } from "../create.js";
4
- import { expandNoteReferenceDeletionRange } from "./noteReferenceDeletion.js";
4
+ import { expandNoteReferenceDeletionRange, noteReferenceRanges } from "./noteReferenceDeletion.js";
5
5
  import { panic } from "better-result";
6
6
  //#region src/prosemirror/extensions/marks/FootnoteRefExtension.ts
7
7
  /**
@@ -59,8 +59,7 @@ const FootnoteRefExtension = createMarkExtension({
59
59
  ];
60
60
  }
61
61
  },
62
- onSchemaReady(ctx) {
63
- const { schema } = ctx;
62
+ onSchemaReady() {
64
63
  const deleteWholeNoteReference = (direction) => (state, dispatch) => {
65
64
  if (suggestionModeKey.getState(state)?.active) return false;
66
65
  const { from, to, empty } = state.selection;
@@ -72,6 +71,7 @@ const FootnoteRefExtension = createMarkExtension({
72
71
  function makeInsertNote(noteType) {
73
72
  return (id) => (state, dispatch) => {
74
73
  if (!dispatch) return true;
74
+ const { schema } = state;
75
75
  const footnoteRefType = schema.marks["footnoteRef"];
76
76
  if (!footnoteRefType) panic("Missing mark type: footnoteRef");
77
77
  const mark = footnoteRefType.create({
@@ -84,12 +84,18 @@ const FootnoteRefExtension = createMarkExtension({
84
84
  return true;
85
85
  };
86
86
  }
87
+ /**
88
+ * Delete the note references the selection touches (the one beside a
89
+ * caret), each whole: tracked as a deletion of the reference run when
90
+ * suggesting, removed outright otherwise.
91
+ */
87
92
  const deleteNoteRef = (state, dispatch) => {
88
- const { $from, $to } = state.selection;
93
+ const { from, to, empty } = state.selection;
94
+ const references = noteReferenceRanges(state.doc, empty ? Math.max(0, from - 1) : from, empty ? Math.min(state.doc.content.size, to + 1) : to);
95
+ if (references.length === 0) return false;
89
96
  if (!dispatch) return true;
90
- let tr = state.tr;
91
- const markType = schema.marks["footnoteRef"];
92
- tr = tr.removeMark($from.pos, $to.pos, markType);
97
+ const tr = state.tr;
98
+ for (const reference of references.toReversed()) if (!suggestRangeDeletion(state, tr, reference.from, reference.to)) tr.delete(reference.from, reference.to);
93
99
  dispatch(tr.scrollIntoView());
94
100
  return true;
95
101
  };
@@ -1,5 +1,6 @@
1
1
  import { anchorTargetAttrs, normalizeUserUrl, sanitizeExternalUrl } from "../../../utils/urlSecurity.js";
2
2
  import { expectHyperlinkMarkAttrs } from "../../attrs/index.js";
3
+ import { removeHyperlinkInRange } from "../../hyperlinkRemoval.js";
3
4
  import { createMarkExtension } from "../create.js";
4
5
  import { isMarkActive } from "./markUtils.js";
5
6
  import { panic } from "better-result";
@@ -118,9 +119,10 @@ const HyperlinkExtension = createMarkExtension({
118
119
  }
119
120
  },
120
121
  onSchemaReady(ctx) {
121
- const hlType = ctx.schema.marks["hyperlink"];
122
- if (!hlType) panic("Missing mark type: hyperlink");
122
+ if (!ctx.schema.marks["hyperlink"]) panic("Missing mark type: hyperlink");
123
+ const documentHyperlinkType = (state) => state.schema.marks["hyperlink"] ?? panic("Missing mark type: hyperlink");
123
124
  const setHyperlink = (href, tooltip) => (state, dispatch) => {
125
+ const hlType = documentHyperlinkType(state);
124
126
  const { from, to, empty } = state.selection;
125
127
  if (empty) return false;
126
128
  if (dispatch) {
@@ -136,6 +138,7 @@ const HyperlinkExtension = createMarkExtension({
136
138
  return true;
137
139
  };
138
140
  const removeHyperlink = (state, dispatch) => {
141
+ const hlType = documentHyperlinkType(state);
139
142
  const { from, to, empty } = state.selection;
140
143
  if (empty) {
141
144
  const $pos = state.selection.$from;
@@ -154,13 +157,14 @@ const HyperlinkExtension = createMarkExtension({
154
157
  }
155
158
  }
156
159
  });
157
- if (dispatch) dispatch(state.tr.removeMark(start, end, hlType).scrollIntoView());
160
+ if (dispatch) dispatch(removeHyperlinkInRange(state, state.tr, start, end).scrollIntoView());
158
161
  return true;
159
162
  }
160
- if (dispatch) dispatch(state.tr.removeMark(from, to, hlType).scrollIntoView());
163
+ if (dispatch) dispatch(removeHyperlinkInRange(state, state.tr, from, to).scrollIntoView());
161
164
  return true;
162
165
  };
163
166
  const insertHyperlink = (text, href, tooltip) => (state, dispatch) => {
167
+ const hlType = documentHyperlinkType(state);
164
168
  if (dispatch) {
165
169
  const mark = hlType.create({
166
170
  href: normalizeHyperlinkInput(href),
@@ -1,6 +1,6 @@
1
1
  import { createMarkExtension } from "../create.js";
2
+ import { toggleDocumentMark } from "./markUtils.js";
2
3
  import { panic } from "better-result";
3
- import { toggleMark } from "prosemirror-commands";
4
4
  //#region src/prosemirror/extensions/marks/StrikeExtension.ts
5
5
  /**
6
6
  * Strikethrough Mark Extension
@@ -26,7 +26,7 @@ const StrikeExtension = createMarkExtension({
26
26
  onSchemaReady(ctx) {
27
27
  const strikeType = ctx.schema.marks["strike"];
28
28
  if (!strikeType) panic("Missing mark type: strike");
29
- return { commands: { toggleStrike: () => toggleMark(strikeType) } };
29
+ return { commands: { toggleStrike: () => toggleDocumentMark(strikeType) } };
30
30
  }
31
31
  });
32
32
  //#endregion
@@ -1,6 +1,6 @@
1
1
  import { createMarkExtension } from "../create.js";
2
+ import { toggleDocumentMark } from "./markUtils.js";
2
3
  import { panic } from "better-result";
3
- import { toggleMark } from "prosemirror-commands";
4
4
  //#region src/prosemirror/extensions/marks/SubscriptExtension.ts
5
5
  /**
6
6
  * Subscript Mark Extension
@@ -18,7 +18,7 @@ const SubscriptExtension = createMarkExtension({
18
18
  onSchemaReady(ctx) {
19
19
  const subscriptType = ctx.schema.marks["subscript"];
20
20
  if (!subscriptType) panic("Missing mark type: subscript");
21
- return { commands: { toggleSubscript: () => toggleMark(subscriptType) } };
21
+ return { commands: { toggleSubscript: () => toggleDocumentMark(subscriptType) } };
22
22
  }
23
23
  });
24
24
  //#endregion
@@ -1,6 +1,6 @@
1
1
  import { createMarkExtension } from "../create.js";
2
+ import { toggleDocumentMark } from "./markUtils.js";
2
3
  import { panic } from "better-result";
3
- import { toggleMark } from "prosemirror-commands";
4
4
  //#region src/prosemirror/extensions/marks/SuperscriptExtension.ts
5
5
  /**
6
6
  * Superscript Mark Extension
@@ -18,7 +18,7 @@ const SuperscriptExtension = createMarkExtension({
18
18
  onSchemaReady(ctx) {
19
19
  const superscriptType = ctx.schema.marks["superscript"];
20
20
  if (!superscriptType) panic("Missing mark type: superscript");
21
- return { commands: { toggleSuperscript: () => toggleMark(superscriptType) } };
21
+ return { commands: { toggleSuperscript: () => toggleDocumentMark(superscriptType) } };
22
22
  }
23
23
  });
24
24
  //#endregion
@@ -1,7 +1,8 @@
1
1
  import { textToStyle } from "../../../utils/formatToStyle.js";
2
2
  import { expectTextColorMarkAttrs } from "../../attrs/index.js";
3
+ import { clearRunColor } from "../../clearRunColor.js";
3
4
  import { createMarkExtension } from "../create.js";
4
- import { removeMark, setMark } from "./markUtils.js";
5
+ import { setMark } from "./markUtils.js";
5
6
  import { panic } from "better-result";
6
7
  //#region src/prosemirror/extensions/marks/TextColorExtension.ts
7
8
  /**
@@ -39,10 +40,10 @@ const TextColorExtension = createMarkExtension({
39
40
  if (!textColorType) panic("Missing mark type: textColor");
40
41
  return { commands: {
41
42
  setTextColor: (attrs) => {
42
- if (!attrs.rgb && !attrs.themeColor) return removeMark(textColorType);
43
+ if (!attrs.rgb && !attrs.themeColor) return clearRunColor();
43
44
  return setMark(textColorType, attrs);
44
45
  },
45
- clearTextColor: () => removeMark(textColorType)
46
+ clearTextColor: () => clearRunColor()
46
47
  } };
47
48
  }
48
49
  });