@stll/folio-core 0.22.2 → 0.23.0

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 (62) hide show
  1. package/dist/ai-edits/apply.d.ts +1 -1
  2. package/dist/controller/layoutPipeline.js +28 -0
  3. package/dist/document-operations.d.ts +4 -4
  4. package/dist/document-operations.js +17 -1
  5. package/dist/docx/imageParser.js +6 -9
  6. package/dist/docx/rezip.d.ts +1 -1
  7. package/dist/docx/rezip.js +12 -31
  8. package/dist/docx/server/inspectDocxPackage.js +8 -7
  9. package/dist/docx/styleParser.js +16 -16
  10. package/dist/docx/xmlParser.d.ts +7 -3
  11. package/dist/docx/xmlParser.js +20 -7
  12. package/dist/layout-bridge/convert/toFlowBlocks.js +35 -61
  13. package/dist/layout-engine/measure/measureHelpers.d.ts +2 -1
  14. package/dist/layout-engine/measure/measureHelpers.js +5 -2
  15. package/dist/layout-engine/types.d.ts +6 -0
  16. package/dist/layout-painter/anchoredImagePosition.d.ts +2 -1
  17. package/dist/layout-painter/anchoredImagePosition.js +14 -6
  18. package/dist/layout-painter/imageLayout.d.ts +1 -1
  19. package/dist/layout-painter/renderPage.js +11 -1
  20. package/dist/layout-painter/renderParagraph.js +3 -4
  21. package/dist/managers/AutoSaveManager.js +8 -40
  22. package/dist/managers/TableSelectionManager.d.ts +1 -1
  23. package/dist/managers/autoSaveCodec.d.ts +17 -0
  24. package/dist/managers/autoSaveCodec.js +109 -0
  25. package/dist/prosemirror/attrs/index.js +278 -29
  26. package/dist/prosemirror/commands/comments.js +3 -3
  27. package/dist/prosemirror/commands/formatting.js +19 -19
  28. package/dist/prosemirror/commands/index.d.ts +2 -2
  29. package/dist/prosemirror/commands/paragraph.js +32 -32
  30. package/dist/prosemirror/commands/propertyChangeScope.d.ts +5 -3
  31. package/dist/prosemirror/commands/propertyChangeScope.js +9 -8
  32. package/dist/prosemirror/commands/table.d.ts +10 -52
  33. package/dist/prosemirror/commands/table.js +34 -34
  34. package/dist/prosemirror/conversion/fromProseDoc.js +33 -20
  35. package/dist/prosemirror/conversion/sdtAttrs.d.ts +2 -1
  36. package/dist/prosemirror/conversion/sdtAttrs.js +9 -4
  37. package/dist/prosemirror/conversion/toProseDoc.js +1 -0
  38. package/dist/prosemirror/extensions/ExtensionManager.d.ts +6 -3
  39. package/dist/prosemirror/extensions/ExtensionManager.js +5 -3
  40. package/dist/prosemirror/extensions/core/ParagraphExtension.d.ts +1 -1
  41. package/dist/prosemirror/extensions/core/ParagraphExtension.js +30 -3
  42. package/dist/prosemirror/extensions/features/ListExtension.js +4 -4
  43. package/dist/prosemirror/extensions/marks/UnderlineExtension.js +9 -7
  44. package/dist/prosemirror/extensions/marks/markUtils.d.ts +2 -1
  45. package/dist/prosemirror/extensions/marks/markUtils.js +92 -16
  46. package/dist/prosemirror/extensions/nodes/ShapeExtension.d.ts +1 -1
  47. package/dist/prosemirror/extensions/nodes/TextBoxExtension.d.ts +1 -1
  48. package/dist/prosemirror/extensions/types.d.ts +134 -1
  49. package/dist/prosemirror/index.d.ts +2 -2
  50. package/dist/prosemirror/plugins/selectionTracker.js +25 -94
  51. package/dist/prosemirror/revisionCarriers.js +3 -1
  52. package/dist/prosemirror/schema/index.d.ts +2 -2
  53. package/dist/prosemirror/schema/index.js +87 -0
  54. package/dist/prosemirror/schema/nodes.d.ts +14 -2
  55. package/dist/prosemirror/selectionMarks.d.ts +11 -0
  56. package/dist/prosemirror/selectionMarks.js +19 -0
  57. package/dist/prosemirror/selectionState.d.ts +11 -5
  58. package/dist/prosemirror/selectionState.js +99 -74
  59. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  60. package/dist/utils/formatToStyle.js +1 -1
  61. package/dist/utils/tableOperations.d.ts +7 -6
  62. package/package.json +3 -3
@@ -0,0 +1,11 @@
1
+ import { Mark, Node } from "prosemirror-model";
2
+ //#region src/prosemirror/selectionMarks.d.ts
3
+ type CollectMarksInRangeOptions = {
4
+ doc: Node;
5
+ from: number;
6
+ to: number;
7
+ };
8
+ /** Collect one representative per mark type, preferring visible underline state. */
9
+ declare const collectMarksInRange: ({ doc, from, to }: CollectMarksInRangeOptions) => Mark[];
10
+ //#endregion
11
+ export { collectMarksInRange };
@@ -0,0 +1,19 @@
1
+ //#region src/prosemirror/selectionMarks.ts
2
+ const UNDERLINE_MARK = "underline";
3
+ const HIDDEN_UNDERLINE_STYLE = "none";
4
+ const shouldReplaceMark = (current, incoming) => current.type.name === UNDERLINE_MARK && current.attrs["style"] === HIDDEN_UNDERLINE_STYLE && incoming.attrs["style"] !== HIDDEN_UNDERLINE_STYLE;
5
+ /** Collect one representative per mark type, preferring visible underline state. */
6
+ const collectMarksInRange = ({ doc, from, to }) => {
7
+ const seen = /* @__PURE__ */ new Map();
8
+ doc.nodesBetween(from, to, (node) => {
9
+ if (!node.isText) return;
10
+ for (const mark of node.marks) {
11
+ const name = mark.type.name;
12
+ const current = seen.get(name);
13
+ if (!current || shouldReplaceMark(current, mark)) seen.set(name, mark);
14
+ }
15
+ });
16
+ return Array.from(seen.values());
17
+ };
18
+ //#endregion
19
+ export { collectMarksInRange };
@@ -2,9 +2,11 @@ import { document_d_exports } from "../types/document.js";
2
2
  import { EditorState } from "prosemirror-state";
3
3
  //#region src/prosemirror/selectionState.d.ts
4
4
  /**
5
- * Selection state for toolbar integration
5
+ * Canonical selection projection shared by toolbar and selection-change APIs.
6
+ * Adapter-specific context belongs on top of this snapshot rather than in a
7
+ * second formatting extractor.
6
8
  */
7
- type SelectionState = {
9
+ type SelectionSnapshot = {
8
10
  /** Whether there's an active selection (not just cursor) */
9
11
  hasSelection: boolean;
10
12
  /** Whether selection spans multiple paragraphs */
@@ -20,10 +22,14 @@ type SelectionState = {
20
22
  /** End paragraph index */
21
23
  endParagraphIndex: number;
22
24
  };
25
+ /** Compatibility name for the public toolbar selection contract. */
26
+ type SelectionState = SelectionSnapshot;
23
27
  /**
24
- * Extract selection state from editor state.
25
- * Used by PagedEditor integration in DocxEditor for toolbar state.
28
+ * Extract the canonical selection snapshot from editor state.
29
+ * Used by both the toolbar callback and the selection tracker plugin.
26
30
  */
31
+ declare function extractSelectionSnapshot(state: EditorState): SelectionSnapshot;
32
+ /** Compatibility entry point used by existing React and Vue integrations. */
27
33
  declare function extractSelectionState(state: EditorState): SelectionState | null;
28
34
  //#endregion
29
- export { SelectionState, extractSelectionState };
35
+ export { SelectionSnapshot, SelectionState, extractSelectionSnapshot, extractSelectionState };
@@ -1,112 +1,137 @@
1
+ import { FONT_THEME_VALUES } from "../types/documentEnumValues.js";
2
+ import { expectFontFamilyMarkAttrs, expectFontSizeMarkAttrs, expectHighlightMarkAttrs, expectParagraphAttrs, expectStrikeMarkAttrs, expectTextColorMarkAttrs, expectUnderlineMarkAttrs } from "./attrs/index.js";
1
3
  import { directionIsRtl } from "./paragraphDirection.js";
4
+ import { collectMarksInRange } from "./selectionMarks.js";
2
5
  //#region src/prosemirror/selectionState.ts
6
+ const isFontTheme = (value) => value !== void 0 && FONT_THEME_VALUES.some((theme) => theme === value);
3
7
  /**
4
- * Extract selection state from editor state.
5
- * Used by PagedEditor integration in DocxEditor for toolbar state.
8
+ * Extract the canonical selection snapshot from editor state.
9
+ * Used by both the toolbar callback and the selection tracker plugin.
6
10
  */
7
- function extractSelectionState(state) {
11
+ function extractSelectionSnapshot(state) {
8
12
  const { selection, doc } = state;
9
13
  const { from, to, empty } = selection;
10
14
  const $from = doc.resolve(from);
15
+ const { startParagraphIndex, endParagraphIndex } = paragraphIndexes(doc, from, to);
16
+ const paragraph = $from.parent;
17
+ const paragraphAttrs = paragraph.type.name === "paragraph" ? expectParagraphAttrs(paragraph) : null;
18
+ const marks = selectionMarks(state);
19
+ let textFormatting = extractTextFormatting(marks);
20
+ if (paragraph.type.name === "paragraph" && paragraph.textContent.length === 0 && marks.length === 0 && paragraphAttrs?.defaultTextFormatting) textFormatting = { ...paragraphAttrs.defaultTextFormatting };
21
+ const paragraphFormatting = {};
22
+ let styleId = null;
23
+ if (paragraphAttrs) {
24
+ if (paragraphAttrs.alignment !== void 0) paragraphFormatting.alignment = paragraphAttrs.alignment;
25
+ if (paragraphAttrs.lineSpacing !== void 0) {
26
+ paragraphFormatting.lineSpacing = paragraphAttrs.lineSpacing;
27
+ if (paragraphAttrs.lineSpacingRule !== void 0) paragraphFormatting.lineSpacingRule = paragraphAttrs.lineSpacingRule;
28
+ }
29
+ if (paragraphAttrs.snapToGrid !== void 0) paragraphFormatting.snapToGrid = paragraphAttrs.snapToGrid;
30
+ if (paragraphAttrs.numPr !== void 0) paragraphFormatting.numPr = paragraphAttrs.numPr;
31
+ if (paragraphAttrs.indentLeft !== void 0) paragraphFormatting.indentLeft = paragraphAttrs.indentLeft;
32
+ if (paragraphAttrs.indentRight !== void 0) paragraphFormatting.indentRight = paragraphAttrs.indentRight;
33
+ if (paragraphAttrs.indentFirstLine !== void 0) paragraphFormatting.indentFirstLine = paragraphAttrs.indentFirstLine;
34
+ if (paragraphAttrs.hangingIndent !== void 0) paragraphFormatting.hangingIndent = paragraphAttrs.hangingIndent;
35
+ if (paragraphAttrs.tabs !== void 0) paragraphFormatting.tabs = paragraphAttrs.tabs;
36
+ if (directionIsRtl(paragraphAttrs.direction)) paragraphFormatting.bidi = true;
37
+ if (paragraphAttrs.styleId !== void 0) styleId = paragraphAttrs.styleId;
38
+ }
39
+ return {
40
+ hasSelection: !empty,
41
+ isMultiParagraph: startParagraphIndex !== endParagraphIndex,
42
+ textFormatting,
43
+ paragraphFormatting,
44
+ styleId,
45
+ startParagraphIndex,
46
+ endParagraphIndex
47
+ };
48
+ }
49
+ /** Compatibility entry point used by existing React and Vue integrations. */
50
+ function extractSelectionState(state) {
51
+ return extractSelectionSnapshot(state);
52
+ }
53
+ function paragraphIndexes(doc, from, to) {
11
54
  let startParagraphIndex = 0;
12
55
  let endParagraphIndex = 0;
13
56
  doc.forEach((_node, offset, index) => {
14
57
  if (offset <= from) startParagraphIndex = index;
15
58
  if (offset <= to) endParagraphIndex = index;
16
59
  });
17
- let textFormatting = {};
18
- const paragraph = $from.parent;
19
- const isEmptyParagraph = paragraph.type.name === "paragraph" && paragraph.textContent.length === 0;
20
- const paragraphDefaultFormatting = paragraph.attrs["defaultTextFormatting"];
21
- const marks = empty ? state.storedMarks || selection.$from.marks() : collectMarksInRange(doc, from, to);
22
- if (isEmptyParagraph && marks.length === 0 && paragraphDefaultFormatting) textFormatting = { ...paragraphDefaultFormatting };
60
+ return {
61
+ startParagraphIndex,
62
+ endParagraphIndex
63
+ };
64
+ }
65
+ function selectionMarks(state) {
66
+ const { selection, doc } = state;
67
+ const { from, to, empty } = selection;
68
+ return empty ? state.storedMarks || selection.$from.marks() : collectMarksInRange({
69
+ doc,
70
+ from,
71
+ to
72
+ });
73
+ }
74
+ function extractTextFormatting(marks) {
75
+ const formatting = {};
23
76
  for (const mark of marks) switch (mark.type.name) {
24
77
  case "bold":
25
- textFormatting.bold = true;
78
+ formatting.bold = true;
26
79
  break;
27
80
  case "italic":
28
- textFormatting.italic = true;
81
+ formatting.italic = true;
29
82
  break;
30
- case "underline":
31
- textFormatting.underline = {
32
- style: mark.attrs["style"] || "single",
33
- color: mark.attrs["color"]
83
+ case "underline": {
84
+ const attrs = expectUnderlineMarkAttrs(mark);
85
+ if (attrs.style !== "none") formatting.underline = {
86
+ style: attrs.style ?? "single",
87
+ ...attrs.color !== void 0 ? { color: attrs.color } : {}
34
88
  };
35
89
  break;
90
+ }
36
91
  case "strike":
37
- if (mark.attrs["double"]) textFormatting.doubleStrike = true;
38
- else textFormatting.strike = true;
92
+ if (expectStrikeMarkAttrs(mark).double) formatting.doubleStrike = true;
93
+ else formatting.strike = true;
39
94
  break;
40
- case "textColor":
41
- textFormatting.color = {
42
- rgb: mark.attrs["rgb"],
43
- themeColor: mark.attrs["themeColor"]
95
+ case "textColor": {
96
+ const attrs = expectTextColorMarkAttrs(mark);
97
+ formatting.color = {
98
+ ...attrs.rgb !== void 0 ? { rgb: attrs.rgb } : {},
99
+ ...attrs.themeColor !== void 0 ? { themeColor: attrs.themeColor } : {},
100
+ ...attrs.themeTint !== void 0 ? { themeTint: attrs.themeTint } : {},
101
+ ...attrs.themeShade !== void 0 ? { themeShade: attrs.themeShade } : {}
44
102
  };
45
103
  break;
104
+ }
46
105
  case "highlight":
47
- textFormatting.highlight = mark.attrs["color"];
106
+ formatting.highlight = expectHighlightMarkAttrs(mark).color;
48
107
  break;
49
108
  case "fontSize":
50
- textFormatting.fontSize = mark.attrs["size"];
109
+ formatting.fontSize = expectFontSizeMarkAttrs(mark).size;
51
110
  break;
52
- case "fontFamily":
53
- textFormatting.fontFamily = {
54
- ascii: mark.attrs["ascii"],
55
- hAnsi: mark.attrs["hAnsi"]
111
+ case "fontFamily": {
112
+ const attrs = expectFontFamilyMarkAttrs(mark);
113
+ formatting.fontFamily = {
114
+ ...attrs.ascii !== void 0 ? { ascii: attrs.ascii } : {},
115
+ ...attrs.hAnsi !== void 0 ? { hAnsi: attrs.hAnsi } : {},
116
+ ...attrs.eastAsia !== void 0 ? { eastAsia: attrs.eastAsia } : {},
117
+ ...attrs.cs !== void 0 ? { cs: attrs.cs } : {},
118
+ ...attrs.hint !== void 0 ? { hint: attrs.hint } : {},
119
+ ...isFontTheme(attrs.asciiTheme) ? { asciiTheme: attrs.asciiTheme } : {},
120
+ ...attrs.hAnsiTheme !== void 0 ? { hAnsiTheme: attrs.hAnsiTheme } : {},
121
+ ...attrs.eastAsiaTheme !== void 0 ? { eastAsiaTheme: attrs.eastAsiaTheme } : {},
122
+ ...attrs.csTheme !== void 0 ? { csTheme: attrs.csTheme } : {}
56
123
  };
57
124
  break;
125
+ }
58
126
  case "superscript":
59
- textFormatting.vertAlign = "superscript";
127
+ formatting.vertAlign = "superscript";
60
128
  break;
61
129
  case "subscript":
62
- textFormatting.vertAlign = "subscript";
130
+ formatting.vertAlign = "subscript";
63
131
  break;
64
132
  default: break;
65
133
  }
66
- const paragraphFormatting = {};
67
- let styleId = null;
68
- if (paragraph.type.name === "paragraph") {
69
- if (paragraph.attrs["alignment"]) paragraphFormatting.alignment = paragraph.attrs["alignment"];
70
- if (paragraph.attrs["lineSpacing"]) {
71
- paragraphFormatting.lineSpacing = paragraph.attrs["lineSpacing"];
72
- paragraphFormatting.lineSpacingRule = paragraph.attrs["lineSpacingRule"];
73
- }
74
- if (typeof paragraph.attrs["snapToGrid"] === "boolean") paragraphFormatting.snapToGrid = paragraph.attrs["snapToGrid"];
75
- if (paragraph.attrs["numPr"]) paragraphFormatting.numPr = paragraph.attrs["numPr"];
76
- if (paragraph.attrs["indentLeft"]) paragraphFormatting.indentLeft = paragraph.attrs["indentLeft"];
77
- if (paragraph.attrs["indentRight"]) paragraphFormatting.indentRight = paragraph.attrs["indentRight"];
78
- if (paragraph.attrs["indentFirstLine"]) paragraphFormatting.indentFirstLine = paragraph.attrs["indentFirstLine"];
79
- if (paragraph.attrs["hangingIndent"]) paragraphFormatting.hangingIndent = paragraph.attrs["hangingIndent"];
80
- if (paragraph.attrs["tabs"]) paragraphFormatting.tabs = paragraph.attrs["tabs"];
81
- if (directionIsRtl(paragraph.attrs["direction"])) paragraphFormatting.bidi = true;
82
- if (paragraph.attrs["styleId"]) styleId = paragraph.attrs["styleId"];
83
- }
84
- return {
85
- hasSelection: !empty,
86
- isMultiParagraph: startParagraphIndex !== endParagraphIndex,
87
- textFormatting,
88
- paragraphFormatting,
89
- styleId,
90
- startParagraphIndex,
91
- endParagraphIndex
92
- };
93
- }
94
- /**
95
- * Collect the first occurrence of each mark type found on any text node within
96
- * the range. Mirrors the "any inline child has this mark" semantics that
97
- * prosemirror-commands' toggleMark uses to decide add-vs-remove, so the
98
- * toolbar's active state stays consistent with what a toggle click will do.
99
- */
100
- function collectMarksInRange(doc, from, to) {
101
- const seen = /* @__PURE__ */ new Map();
102
- doc.nodesBetween(from, to, (node) => {
103
- if (!node.isText) return;
104
- for (const mark of node.marks) {
105
- const name = mark.type.name;
106
- if (!seen.has(name)) seen.set(name, mark);
107
- }
108
- });
109
- return Array.from(seen.values());
134
+ return formatting;
110
135
  }
111
136
  //#endregion
112
- export { extractSelectionState };
137
+ export { extractSelectionSnapshot, extractSelectionState };
@@ -27,6 +27,7 @@ function paragraphAttrsFromResolvedStyle(resolved) {
27
27
  spaceAfter: ppr?.spaceAfter ?? null,
28
28
  lineSpacing: ppr?.lineSpacing ?? null,
29
29
  lineSpacingRule: ppr?.lineSpacingRule ?? null,
30
+ lineSpacingExplicit: null,
30
31
  snapToGrid: ppr?.snapToGrid ?? null,
31
32
  indentLeft: ppr?.indentLeft ?? null,
32
33
  indentRight: ppr?.indentRight ?? null,
@@ -108,7 +108,7 @@ function paragraphToStyle(formatting, theme) {
108
108
  }
109
109
  if (formatting.indentLeft !== void 0) style.marginLeft = formatPx(twipsToPixels(formatting.indentLeft));
110
110
  if (formatting.indentRight !== void 0) style.marginRight = formatPx(twipsToPixels(formatting.indentRight));
111
- if (formatting.indentFirstLine !== void 0) style.textIndent = formatPx(twipsToPixels(formatting.indentFirstLine));
111
+ if (formatting.indentFirstLine !== void 0) style.textIndent = formatPx(twipsToPixels(formatting.hangingIndent ? -Math.abs(formatting.indentFirstLine) : formatting.indentFirstLine));
112
112
  if (formatting.borders) {
113
113
  if (formatting.borders.top) Object.assign(style, borderToStyle(formatting.borders.top, "Top", theme));
114
114
  if (formatting.borders.bottom) Object.assign(style, borderToStyle(formatting.borders.bottom, "Bottom", theme));
@@ -1,5 +1,10 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  //#region src/utils/tableOperations.d.ts
3
+ type TablePropertiesCommand = {
4
+ width?: number | null;
5
+ widthType?: document_d_exports.TableWidthType | null;
6
+ justification?: "left" | "center" | "right" | null;
7
+ };
3
8
  type TableAction = "addRowAbove" | "addRowBelow" | "addColumnLeft" | "addColumnRight" | "deleteRow" | "deleteColumn" | "mergeCells" | "splitCell" | "deleteTable" | "selectTable" | "selectRow" | "selectColumn" | "borderAll" | "borderOutside" | "borderInside" | "borderNone" | "borderTop" | "borderBottom" | "borderLeft" | "borderRight" | {
4
9
  type: "cellFillColor";
5
10
  color: string | null;
@@ -43,11 +48,7 @@ type TableAction = "addRowAbove" | "addRowBelow" | "addColumnLeft" | "addColumnR
43
48
  type: "autoFitContents";
44
49
  } | {
45
50
  type: "tableProperties";
46
- props: {
47
- width?: number | null;
48
- widthType?: string | null;
49
- justification?: "left" | "center" | "right" | null;
50
- };
51
+ props: TablePropertiesCommand;
51
52
  } | {
52
53
  type: "openTableProperties";
53
54
  } | {
@@ -83,4 +84,4 @@ declare const deleteColumn: (table: document_d_exports.Table, columnIndex: numbe
83
84
  declare const mergeCells: (table: document_d_exports.Table, selection: TableSelection) => document_d_exports.Table;
84
85
  declare const splitCell: (table: document_d_exports.Table, rowIndex: number, columnIndex: number) => document_d_exports.Table;
85
86
  //#endregion
86
- export { TableAction, TableContext, TableSelection, addColumn, addRow, createTableContext, deleteColumn, deleteRow, getCellAt, getColumnCount, mergeCells, splitCell };
87
+ export { TableAction, TableContext, TablePropertiesCommand, TableSelection, addColumn, addRow, createTableContext, deleteColumn, deleteRow, getCellAt, getColumnCount, mergeCells, splitCell };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/folio-core",
3
- "version": "0.22.2",
3
+ "version": "0.23.0",
4
4
  "description": "Headless, framework-neutral core of folio: the OOXML (.docx) parser, document model, ProseMirror integration, and page-layout engine. No React.",
5
5
  "keywords": [
6
6
  "document-model",
@@ -113,13 +113,13 @@
113
113
  "perf": "bun scripts/profile-editor.ts"
114
114
  },
115
115
  "dependencies": {
116
- "@stll/docx-core": "^0.15.1",
116
+ "@stll/docx-core": "^0.15.2",
117
117
  "@stll/docx-utils": "^0.1.0",
118
118
  "@stll/template-conditions": "^0.1.0",
119
119
  "better-result": "3.0.1",
120
120
  "csstype": "^3.1.3",
121
121
  "dompurify": "^3.4.13",
122
- "fast-xml-parser": "^5.9.3",
122
+ "fast-xml-parser": "^5.10.1",
123
123
  "hyphen": "1.14.1",
124
124
  "jszip": "3.10.1",
125
125
  "marked": "^18.0.5",