@scrider/formatter 1.0.1 → 1.2.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.
package/dist/index.cjs CHANGED
@@ -63,6 +63,8 @@ __export(index_exports, {
63
63
  dividerFormat: () => dividerFormat,
64
64
  escapeHtml: () => escapeHtml,
65
65
  extractBoxOpAttributes: () => extractBoxOpAttributes,
66
+ extractTableRegion: () => extractTableRegion,
67
+ fontFormat: () => fontFormat,
66
68
  footnoteRefFormat: () => footnoteRefFormat,
67
69
  footnotesBlockHandler: () => footnotesBlockHandler,
68
70
  formulaFormat: () => formulaFormat,
@@ -76,6 +78,7 @@ __export(index_exports, {
76
78
  isAdapterAvailable: () => isAdapterAvailable,
77
79
  isElement: () => isElement,
78
80
  isRemarkAvailable: () => isRemarkAvailable,
81
+ isTableNewlineOp: () => isTableNewlineOp,
79
82
  isTextNode: () => isTextNode,
80
83
  isValidColor: () => isValidColor,
81
84
  isValidHexColor: () => isValidHexColor,
@@ -88,7 +91,9 @@ __export(index_exports, {
88
91
  markdownToDeltaSync: () => markdownToDeltaSync,
89
92
  nodeAdapter: () => nodeAdapter,
90
93
  normalizeDelta: () => normalizeDelta,
94
+ preloadRemark: () => preloadRemark,
91
95
  sanitizeDelta: () => sanitizeDelta,
96
+ sizeFormat: () => sizeFormat,
92
97
  slugify: () => slugify,
93
98
  slugifyWithDedup: () => slugifyWithDedup,
94
99
  strikeFormat: () => strikeFormat,
@@ -1663,6 +1668,15 @@ var colorFormat = {
1663
1668
  }
1664
1669
  };
1665
1670
 
1671
+ // src/schema/formats/inline/font.ts
1672
+ var fontFormat = {
1673
+ name: "font",
1674
+ scope: "inline",
1675
+ validate(value) {
1676
+ return typeof value === "string" && value.length > 0;
1677
+ }
1678
+ };
1679
+
1666
1680
  // src/schema/formats/inline/italic.ts
1667
1681
  var italicFormat = {
1668
1682
  name: "italic",
@@ -1720,6 +1734,15 @@ var markFormat = {
1720
1734
  }
1721
1735
  };
1722
1736
 
1737
+ // src/schema/formats/inline/size.ts
1738
+ var sizeFormat = {
1739
+ name: "size",
1740
+ scope: "inline",
1741
+ validate(value) {
1742
+ return typeof value === "string" && value.length > 0;
1743
+ }
1744
+ };
1745
+
1723
1746
  // src/schema/formats/inline/strike.ts
1724
1747
  var strikeFormat = {
1725
1748
  name: "strike",
@@ -1927,7 +1950,9 @@ var INLINE_FORMAT_ORDER = [
1927
1950
  ];
1928
1951
  var INLINE_STYLE_FORMATS = {
1929
1952
  color: "color",
1930
- background: "background-color"
1953
+ background: "background-color",
1954
+ font: "font-family",
1955
+ size: "font-size"
1931
1956
  };
1932
1957
  var BLOCK_FORMAT_TAGS = {
1933
1958
  header: (value) => `h${String(value)}`,
@@ -2312,6 +2337,8 @@ var defaultInlineFormats = [
2312
2337
  linkFormat,
2313
2338
  colorFormat,
2314
2339
  backgroundFormat,
2340
+ fontFormat,
2341
+ sizeFormat,
2315
2342
  markFormat,
2316
2343
  kbdFormat
2317
2344
  ];
@@ -3342,6 +3369,14 @@ function htmlToDelta(html, options = {}) {
3342
3369
  if (bg) {
3343
3370
  currentAttributes.background = bg;
3344
3371
  }
3372
+ const fontFamily = element.style?.fontFamily || element.style?.getPropertyValue?.("font-family");
3373
+ if (fontFamily) {
3374
+ currentAttributes.font = fontFamily.replace(/^["']|["']$/g, "");
3375
+ }
3376
+ const fontSize = element.style?.fontSize || element.style?.getPropertyValue?.("font-size");
3377
+ if (fontSize) {
3378
+ currentAttributes.size = fontSize;
3379
+ }
3345
3380
  processChildren(element);
3346
3381
  flushText();
3347
3382
  currentAttributes = prevAttrs;
@@ -3724,7 +3759,8 @@ function deltaToMarkdown(delta, options = {}) {
3724
3759
  embedRenderers = {},
3725
3760
  blockHandlers,
3726
3761
  prettyHtml = false,
3727
- registry
3762
+ registry,
3763
+ trimTrailingNewlines = false
3728
3764
  } = options;
3729
3765
  const useLatexDelimiters = mathSyntax === "latex";
3730
3766
  const lines = splitIntoLines2(delta.ops);
@@ -3822,7 +3858,8 @@ ${code}
3822
3858
  lastIndent = indent;
3823
3859
  lastWasBlockquote = isBlockquote;
3824
3860
  }
3825
- return result.join("\n");
3861
+ const md = result.join("\n");
3862
+ return trimTrailingNewlines ? md.replace(/\n+$/, "") : md;
3826
3863
  }
3827
3864
  function hasBlockFormat(attrs) {
3828
3865
  return !!(attrs.header || attrs.list || attrs.blockquote || attrs["code-block"] || attrs.align || attrs.indent);
@@ -4043,11 +4080,14 @@ function renderInlineText2(text, attributes) {
4043
4080
  if (link) {
4044
4081
  result = renderLink(result, link);
4045
4082
  }
4046
- if (typeof attributes.color === "string") {
4047
- result = `<span style="color: ${attributes.color}">${result}</span>`;
4048
- }
4049
- if (typeof attributes.background === "string") {
4050
- result = `<span style="background-color: ${attributes.background}">${result}</span>`;
4083
+ const styleProps = [];
4084
+ if (typeof attributes.color === "string") styleProps.push(`color: ${attributes.color}`);
4085
+ if (typeof attributes.background === "string")
4086
+ styleProps.push(`background-color: ${attributes.background}`);
4087
+ if (typeof attributes.font === "string") styleProps.push(`font-family: ${attributes.font}`);
4088
+ if (typeof attributes.size === "string") styleProps.push(`font-size: ${attributes.size}`);
4089
+ if (styleProps.length > 0) {
4090
+ result = `<span style="${styleProps.join("; ")}">${result}</span>`;
4051
4091
  }
4052
4092
  return result;
4053
4093
  }
@@ -4208,6 +4248,8 @@ var remarkGfm = null;
4208
4248
  var remarkMath = null;
4209
4249
  var unified = null;
4210
4250
  function isRemarkAvailable() {
4251
+ if (unified && remarkParse) return true;
4252
+ if (typeof require === "undefined") return false;
4211
4253
  try {
4212
4254
  require.resolve("unified");
4213
4255
  require.resolve("remark-parse");
@@ -4216,8 +4258,8 @@ function isRemarkAvailable() {
4216
4258
  return false;
4217
4259
  }
4218
4260
  }
4219
- async function loadRemark() {
4220
- if (unified) return;
4261
+ async function preloadRemark() {
4262
+ if (unified && remarkParse && remarkGfm) return true;
4221
4263
  try {
4222
4264
  const [unifiedMod, remarkParseMod, remarkGfmMod] = await Promise.all([
4223
4265
  import("unified"),
@@ -4228,15 +4270,16 @@ async function loadRemark() {
4228
4270
  remarkParse = remarkParseMod.default;
4229
4271
  remarkGfm = remarkGfmMod.default;
4230
4272
  } catch {
4231
- throw new Error(
4232
- "remark is not installed. Install with: pnpm add unified remark-parse remark-gfm"
4233
- );
4273
+ return false;
4234
4274
  }
4235
- try {
4236
- const remarkMathMod = await import("remark-math");
4237
- remarkMath = remarkMathMod.default;
4238
- } catch {
4275
+ if (!remarkMath) {
4276
+ try {
4277
+ const remarkMathMod = await import("remark-math");
4278
+ remarkMath = remarkMathMod.default;
4279
+ } catch {
4280
+ }
4239
4281
  }
4282
+ return true;
4240
4283
  }
4241
4284
  function preprocessMarkdown(markdown, mathBlock) {
4242
4285
  markdown = markdown.replace(/\\\((.+?)\\\)/g, (_match, content) => `$${content}$`);
@@ -4260,9 +4303,11 @@ async function markdownToDelta(markdown, options = {}) {
4260
4303
  nodeHandlers = {}
4261
4304
  } = options;
4262
4305
  markdown = preprocessMarkdown(markdown, mathBlock);
4263
- await loadRemark();
4264
- if (!unified || !remarkParse) {
4265
- throw new Error("Failed to load remark");
4306
+ const loaded = await preloadRemark();
4307
+ if (!loaded || !unified || !remarkParse) {
4308
+ throw new Error(
4309
+ "remark is not installed. Install with: pnpm add unified remark-parse remark-gfm"
4310
+ );
4266
4311
  }
4267
4312
  let processor = unified().use(remarkParse);
4268
4313
  if (gfm && remarkGfm) {
@@ -4291,6 +4336,11 @@ function markdownToDeltaSync(markdown, options = {}) {
4291
4336
  } = options;
4292
4337
  markdown = preprocessMarkdown(markdown, mathBlock);
4293
4338
  if (!unified || !remarkParse) {
4339
+ if (typeof require === "undefined") {
4340
+ throw new Error(
4341
+ "markdownToDeltaSync requires remark to be preloaded in this environment. `require()` is not available (likely browser ESM). Call `await preloadRemark()` once on application startup before using the sync API, or use the async `markdownToDelta()` instead."
4342
+ );
4343
+ }
4294
4344
  try {
4295
4345
  const unifiedMod = require("unified");
4296
4346
  const remarkParseMod = require("remark-parse");
@@ -4789,6 +4839,19 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
4789
4839
  currentInlineAttrs = { ...currentInlineAttrs, background: bgMatch[1].trim() };
4790
4840
  addedKeys.push("background");
4791
4841
  }
4842
+ const fontMatch = style.match(/(?:^|;)\s*font-family\s*:\s*([^;]+)/i);
4843
+ if (fontMatch) {
4844
+ currentInlineAttrs = {
4845
+ ...currentInlineAttrs,
4846
+ font: fontMatch[1].trim().replace(/^["']|["']$/g, "")
4847
+ };
4848
+ addedKeys.push("font");
4849
+ }
4850
+ const sizeMatch = style.match(/(?:^|;)\s*font-size\s*:\s*([^;]+)/i);
4851
+ if (sizeMatch) {
4852
+ currentInlineAttrs = { ...currentInlineAttrs, size: sizeMatch[1].trim() };
4853
+ addedKeys.push("size");
4854
+ }
4792
4855
  spanAttrStack.push(addedKeys);
4793
4856
  return;
4794
4857
  }
@@ -4866,6 +4929,54 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
4866
4929
  }
4867
4930
  return delta;
4868
4931
  }
4932
+
4933
+ // src/conversion/markdown/table-region.ts
4934
+ var import_delta11 = require("@scrider/delta");
4935
+ function isTableNewlineOp(op) {
4936
+ if (!op || !(0, import_delta11.isInsert)(op) || !(0, import_delta11.isTextInsert)(op)) return false;
4937
+ if (!op.insert.includes("\n")) return false;
4938
+ return !!op.attributes && "table-row" in op.attributes;
4939
+ }
4940
+ function extractTableRegion(ops, hintOpIdx) {
4941
+ if (hintOpIdx < 0 || hintOpIdx >= ops.length) return null;
4942
+ let probeIdx = -1;
4943
+ for (let i = hintOpIdx; i < ops.length; i++) {
4944
+ const op = ops[i];
4945
+ if (!op || !(0, import_delta11.isInsert)(op)) continue;
4946
+ if ((0, import_delta11.isTextInsert)(op) && op.insert.includes("\n")) {
4947
+ probeIdx = i;
4948
+ break;
4949
+ }
4950
+ }
4951
+ if (probeIdx < 0) return null;
4952
+ if (!isTableNewlineOp(ops[probeIdx])) return null;
4953
+ let endOpIdx = probeIdx;
4954
+ for (let i = probeIdx + 1; i < ops.length; i++) {
4955
+ const op = ops[i];
4956
+ if (!op || !(0, import_delta11.isInsert)(op)) break;
4957
+ if ((0, import_delta11.isTextInsert)(op) && op.insert.includes("\n")) {
4958
+ if (isTableNewlineOp(op)) {
4959
+ endOpIdx = i;
4960
+ } else {
4961
+ break;
4962
+ }
4963
+ }
4964
+ }
4965
+ let startOpIdx = 0;
4966
+ for (let i = probeIdx - 1; i >= 0; i--) {
4967
+ const op = ops[i];
4968
+ if (!op || !(0, import_delta11.isInsert)(op)) {
4969
+ startOpIdx = i + 1;
4970
+ break;
4971
+ }
4972
+ if ((0, import_delta11.isTextInsert)(op) && op.insert.includes("\n") && !isTableNewlineOp(op)) {
4973
+ startOpIdx = i + 1;
4974
+ break;
4975
+ }
4976
+ }
4977
+ const regionOps = ops.slice(startOpIdx, endOpIdx + 1);
4978
+ return { startOpIdx, endOpIdx, ops: regionOps };
4979
+ }
4869
4980
  // Annotate the CommonJS export names for ESM import in node:
4870
4981
  0 && (module.exports = {
4871
4982
  ALERT_TYPES,
@@ -4900,6 +5011,8 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
4900
5011
  dividerFormat,
4901
5012
  escapeHtml,
4902
5013
  extractBoxOpAttributes,
5014
+ extractTableRegion,
5015
+ fontFormat,
4903
5016
  footnoteRefFormat,
4904
5017
  footnotesBlockHandler,
4905
5018
  formulaFormat,
@@ -4913,6 +5026,7 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
4913
5026
  isAdapterAvailable,
4914
5027
  isElement,
4915
5028
  isRemarkAvailable,
5029
+ isTableNewlineOp,
4916
5030
  isTextNode,
4917
5031
  isValidColor,
4918
5032
  isValidHexColor,
@@ -4925,7 +5039,9 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
4925
5039
  markdownToDeltaSync,
4926
5040
  nodeAdapter,
4927
5041
  normalizeDelta,
5042
+ preloadRemark,
4928
5043
  sanitizeDelta,
5044
+ sizeFormat,
4929
5045
  slugify,
4930
5046
  slugifyWithDedup,
4931
5047
  strikeFormat,