@scrider/formatter 1.7.2 → 1.8.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
@@ -459,6 +459,20 @@ function cloneDelta(delta) {
459
459
  return new import_delta.Delta((0, import_delta.deepClone)(delta.ops));
460
460
  }
461
461
 
462
+ // src/conversion/markdown/table-header-markdown.ts
463
+ function isHeaderDashPlaceholder(text) {
464
+ const t = text.trim();
465
+ return t === "-" && t.length === 1;
466
+ }
467
+ function normalizeHeaderCellForParse(text, isHeaderRow) {
468
+ if (isHeaderRow && isHeaderDashPlaceholder(text)) return "";
469
+ return text;
470
+ }
471
+ function serializeHeaderCell(text) {
472
+ if (text.trim() === "") return "-";
473
+ return text;
474
+ }
475
+
462
476
  // src/conversion/adapters/types.ts
463
477
  var NODE_TYPE = {
464
478
  ELEMENT_NODE: 1,
@@ -580,19 +594,21 @@ function renderGfmTable(data, context) {
580
594
  if (headerRows === 0) {
581
595
  const emptyParts = [];
582
596
  for (let c = 0; c < cols; c++) {
583
- emptyParts.push(" ");
597
+ emptyParts.push("");
584
598
  }
585
599
  lines.push("| " + emptyParts.join(" | ") + " |");
586
600
  lines.push(renderGfmSeparator(cols, data.colAligns));
587
601
  }
588
602
  for (let r = 0; r < rows; r++) {
589
603
  const parts = [];
604
+ const isHeaderRow = headerRows > 0 && r < headerRows;
590
605
  for (let c = 0; c < cols; c++) {
591
606
  const cell = data.cells[`${r}:${c}`];
592
607
  let text = "";
593
608
  if (cell && context.renderDelta) {
594
609
  text = stripCellContent(context.renderDelta(cell.ops));
595
610
  }
611
+ if (isHeaderRow) text = serializeHeaderCell(text);
596
612
  parts.push(text.replace(/\|/g, "\\|"));
597
613
  }
598
614
  lines.push("| " + parts.join(" | ") + " |");
@@ -4558,7 +4574,15 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
4558
4574
  if (headerRows.length > 0) {
4559
4575
  for (const [, row] of headerRows) {
4560
4576
  mdLines.push(
4561
- renderMdRow(row.cells, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
4577
+ renderMdRow(
4578
+ row.cells,
4579
+ maxCol,
4580
+ embedRenderers,
4581
+ useLatexDelimiters,
4582
+ registry,
4583
+ softBreakStyle,
4584
+ true
4585
+ )
4562
4586
  );
4563
4587
  }
4564
4588
  mdLines.push(renderMdSeparator(maxCol, colAligns));
@@ -4568,22 +4592,38 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
4568
4592
  emptyRow.set(col, { ops: [] });
4569
4593
  }
4570
4594
  mdLines.push(
4571
- renderMdRow(emptyRow, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
4595
+ renderMdRow(
4596
+ emptyRow,
4597
+ maxCol,
4598
+ embedRenderers,
4599
+ useLatexDelimiters,
4600
+ registry,
4601
+ softBreakStyle,
4602
+ false
4603
+ )
4572
4604
  );
4573
4605
  mdLines.push(renderMdSeparator(maxCol, colAligns));
4574
4606
  }
4575
4607
  for (const [, row] of bodyRows) {
4576
4608
  mdLines.push(
4577
- renderMdRow(row.cells, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
4609
+ renderMdRow(
4610
+ row.cells,
4611
+ maxCol,
4612
+ embedRenderers,
4613
+ useLatexDelimiters,
4614
+ registry,
4615
+ softBreakStyle,
4616
+ false
4617
+ )
4578
4618
  );
4579
4619
  }
4580
4620
  return mdLines.join("\n");
4581
4621
  }
4582
- function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces") {
4622
+ function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces", isHeaderRow = false) {
4583
4623
  const parts = [];
4584
4624
  for (let col = 0; col <= maxCol; col++) {
4585
4625
  const cell = cells.get(col);
4586
- const content = cell ? renderLineContent2(
4626
+ let content = cell ? renderLineContent2(
4587
4627
  cell.ops,
4588
4628
  embedRenderers,
4589
4629
  false,
@@ -4595,6 +4635,7 @@ function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false,
4595
4635
  true
4596
4636
  // inTableCell — softBreak must use <br>, never " \n"
4597
4637
  ) : "";
4638
+ if (isHeaderRow) content = serializeHeaderCell(content);
4598
4639
  parts.push(content.replace(/\|/g, "\\|"));
4599
4640
  }
4600
4641
  return "| " + parts.join(" | ") + " |";
@@ -4859,7 +4900,138 @@ function renderBlockFormat(content, attributes, orderedIndex, _strict) {
4859
4900
  }
4860
4901
 
4861
4902
  // src/conversion/markdown/markdown-to-delta.ts
4903
+ var import_delta11 = require("@scrider/delta");
4904
+
4905
+ // src/conversion/markdown/table-header-normalize.ts
4862
4906
  var import_delta10 = require("@scrider/delta");
4907
+ function isTableCellTerminator(op) {
4908
+ return (0, import_delta10.isInsert)(op) && typeof op.insert === "string" && op.insert === "\n" && op.attributes !== void 0 && typeof op.attributes["table-row"] === "number";
4909
+ }
4910
+ function normalizeSyntheticEmptyHeaderRow(ops) {
4911
+ const ends = [];
4912
+ let buf = "";
4913
+ const textOpIndicesByCell = [];
4914
+ let currentTextOps = [];
4915
+ for (let i = 0; i < ops.length; i++) {
4916
+ const op = ops[i];
4917
+ if (!(0, import_delta10.isInsert)(op)) continue;
4918
+ if (typeof op.insert === "string" && op.insert !== "\n") {
4919
+ buf += op.insert;
4920
+ currentTextOps.push(i);
4921
+ continue;
4922
+ }
4923
+ if (isTableCellTerminator(op)) {
4924
+ const row = op.attributes["table-row"];
4925
+ const col = op.attributes["table-col"];
4926
+ ends.push({ row, col, newlineIdx: i, text: buf });
4927
+ textOpIndicesByCell.push([...currentTextOps]);
4928
+ buf = "";
4929
+ currentTextOps = [];
4930
+ }
4931
+ }
4932
+ const row0 = ends.filter((e) => e.row === 0);
4933
+ if (row0.length === 0) return [...ops];
4934
+ if (!row0.every((e) => e.text.trim() === "")) return [...ops];
4935
+ if (row0.some((e) => isHeaderDashPlaceholder(e.text))) return [...ops];
4936
+ const remove = /* @__PURE__ */ new Set();
4937
+ for (let j = 0; j < ends.length; j++) {
4938
+ const end = ends[j];
4939
+ if (end.row !== 0) continue;
4940
+ remove.add(end.newlineIdx);
4941
+ for (const ti of textOpIndicesByCell[j] ?? []) remove.add(ti);
4942
+ }
4943
+ const out = [];
4944
+ for (let i = 0; i < ops.length; i++) {
4945
+ if (remove.has(i)) continue;
4946
+ const op = ops[i];
4947
+ if (!isTableCellTerminator(op)) {
4948
+ out.push(op);
4949
+ continue;
4950
+ }
4951
+ const row = op.attributes["table-row"];
4952
+ if (row === 0) continue;
4953
+ const attrs = { ...op.attributes };
4954
+ delete attrs["table-header"];
4955
+ out.push({
4956
+ insert: "\n",
4957
+ attributes: { ...attrs, "table-row": row - 1 }
4958
+ });
4959
+ }
4960
+ return out;
4961
+ }
4962
+ function normalizeHeaderDashPlaceholders(ops) {
4963
+ const ends = [];
4964
+ let buf = "";
4965
+ let currentTextOps = [];
4966
+ for (let i = 0; i < ops.length; i++) {
4967
+ const op = ops[i];
4968
+ if (!(0, import_delta10.isInsert)(op)) continue;
4969
+ if (typeof op.insert === "string" && op.insert !== "\n") {
4970
+ buf += op.insert;
4971
+ currentTextOps.push(i);
4972
+ continue;
4973
+ }
4974
+ if (isTableCellTerminator(op)) {
4975
+ const row = op.attributes["table-row"];
4976
+ const isHeader = row === 0 && op.attributes["table-header"] === true;
4977
+ ends.push({ isHeader, textOpIndices: [...currentTextOps], text: buf });
4978
+ buf = "";
4979
+ currentTextOps = [];
4980
+ }
4981
+ }
4982
+ const dashHeaderCells = ends.filter(
4983
+ (e) => e.isHeader && e.textOpIndices.length > 0 && isHeaderDashPlaceholder(e.text)
4984
+ );
4985
+ if (dashHeaderCells.length === 0) return [...ops];
4986
+ const replaceIndices = /* @__PURE__ */ new Set();
4987
+ for (const end of dashHeaderCells) {
4988
+ for (const ti of end.textOpIndices) replaceIndices.add(ti);
4989
+ }
4990
+ const out = [];
4991
+ for (let i = 0; i < ops.length; i++) {
4992
+ const op = ops[i];
4993
+ if (!replaceIndices.has(i)) {
4994
+ out.push(op);
4995
+ continue;
4996
+ }
4997
+ if (!(0, import_delta10.isInsert)(op)) {
4998
+ out.push(op);
4999
+ continue;
5000
+ }
5001
+ if (typeof op.insert === "string" && op.insert !== "\n") {
5002
+ const normalized = normalizeHeaderCellForParse(op.insert, true);
5003
+ if (normalized.length === 0) continue;
5004
+ out.push(
5005
+ op.attributes ? { insert: normalized, attributes: op.attributes } : { insert: normalized }
5006
+ );
5007
+ } else {
5008
+ out.push(op);
5009
+ }
5010
+ }
5011
+ return out;
5012
+ }
5013
+ function normalizeImportedTableOps(ops) {
5014
+ if (ops.length === 0) return [...ops];
5015
+ const ends = [];
5016
+ let buf = "";
5017
+ for (const op of ops) {
5018
+ if (!(0, import_delta10.isInsert)(op)) continue;
5019
+ if (typeof op.insert === "string" && op.insert !== "\n") {
5020
+ buf += op.insert;
5021
+ continue;
5022
+ }
5023
+ if (isTableCellTerminator(op)) {
5024
+ ends.push({ row: op.attributes["table-row"], text: buf });
5025
+ buf = "";
5026
+ }
5027
+ }
5028
+ const row0 = ends.filter((e) => e.row === 0);
5029
+ const headerless = row0.length > 0 && row0.every((e) => e.text.trim() === "") && !row0.some((e) => isHeaderDashPlaceholder(e.text));
5030
+ if (headerless) return normalizeSyntheticEmptyHeaderRow(ops);
5031
+ return normalizeHeaderDashPlaceholders(ops);
5032
+ }
5033
+
5034
+ // src/conversion/markdown/markdown-to-delta.ts
4863
5035
  var remarkParse = null;
4864
5036
  var remarkGfm = null;
4865
5037
  var remarkMath = null;
@@ -4996,7 +5168,7 @@ function markdownToDeltaSync(markdown, options = {}) {
4996
5168
  );
4997
5169
  }
4998
5170
  function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock, blockHandlers) {
4999
- const delta = new import_delta10.Delta();
5171
+ const delta = new import_delta11.Delta();
5000
5172
  let currentInlineAttrs = {};
5001
5173
  let pendingText = "";
5002
5174
  const spanAttrStack = [];
@@ -5348,6 +5520,7 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
5348
5520
  }
5349
5521
  function processTable(node) {
5350
5522
  if (!node.children) return;
5523
+ const tableStart = delta.ops.length;
5351
5524
  const aligns = node.align || [];
5352
5525
  for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
5353
5526
  const rowNode = node.children[rowIdx];
@@ -5376,6 +5549,15 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
5376
5549
  context.pushNewline(cellBlockAttrs);
5377
5550
  }
5378
5551
  }
5552
+ const tableOps = delta.ops.splice(tableStart);
5553
+ for (const op of normalizeImportedTableOps(tableOps)) {
5554
+ if (!(0, import_delta11.isInsert)(op)) continue;
5555
+ if (op.attributes && Object.keys(op.attributes).length > 0) {
5556
+ delta.insert(op.insert, op.attributes);
5557
+ } else {
5558
+ delta.insert(op.insert);
5559
+ }
5560
+ }
5379
5561
  }
5380
5562
  function isBlockLevelHtml(html) {
5381
5563
  return /^\s*<(div|table|section|article|aside|nav|header|footer|figure|pre|hr|ol|ul|dl|details|iframe|video)\b/i.test(
@@ -5557,9 +5739,9 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
5557
5739
  }
5558
5740
 
5559
5741
  // src/conversion/markdown/table-region.ts
5560
- var import_delta11 = require("@scrider/delta");
5742
+ var import_delta12 = require("@scrider/delta");
5561
5743
  function isTableNewlineOp(op) {
5562
- if (!op || !(0, import_delta11.isInsert)(op) || !(0, import_delta11.isTextInsert)(op)) return false;
5744
+ if (!op || !(0, import_delta12.isInsert)(op) || !(0, import_delta12.isTextInsert)(op)) return false;
5563
5745
  if (!op.insert.includes("\n")) return false;
5564
5746
  return !!op.attributes && "table-row" in op.attributes;
5565
5747
  }
@@ -5568,8 +5750,8 @@ function extractTableRegion(ops, hintOpIdx) {
5568
5750
  let probeIdx = -1;
5569
5751
  for (let i = hintOpIdx; i < ops.length; i++) {
5570
5752
  const op = ops[i];
5571
- if (!op || !(0, import_delta11.isInsert)(op)) continue;
5572
- if ((0, import_delta11.isTextInsert)(op) && op.insert.includes("\n")) {
5753
+ if (!op || !(0, import_delta12.isInsert)(op)) continue;
5754
+ if ((0, import_delta12.isTextInsert)(op) && op.insert.includes("\n")) {
5573
5755
  probeIdx = i;
5574
5756
  break;
5575
5757
  }
@@ -5579,8 +5761,8 @@ function extractTableRegion(ops, hintOpIdx) {
5579
5761
  let endOpIdx = probeIdx;
5580
5762
  for (let i = probeIdx + 1; i < ops.length; i++) {
5581
5763
  const op = ops[i];
5582
- if (!op || !(0, import_delta11.isInsert)(op)) break;
5583
- if ((0, import_delta11.isTextInsert)(op) && op.insert.includes("\n")) {
5764
+ if (!op || !(0, import_delta12.isInsert)(op)) break;
5765
+ if ((0, import_delta12.isTextInsert)(op) && op.insert.includes("\n")) {
5584
5766
  if (isTableNewlineOp(op)) {
5585
5767
  endOpIdx = i;
5586
5768
  } else {
@@ -5591,11 +5773,11 @@ function extractTableRegion(ops, hintOpIdx) {
5591
5773
  let startOpIdx = 0;
5592
5774
  for (let i = probeIdx - 1; i >= 0; i--) {
5593
5775
  const op = ops[i];
5594
- if (!op || !(0, import_delta11.isInsert)(op)) {
5776
+ if (!op || !(0, import_delta12.isInsert)(op)) {
5595
5777
  startOpIdx = i + 1;
5596
5778
  break;
5597
5779
  }
5598
- if ((0, import_delta11.isTextInsert)(op) && op.insert.includes("\n") && !isTableNewlineOp(op)) {
5780
+ if ((0, import_delta12.isTextInsert)(op) && op.insert.includes("\n") && !isTableNewlineOp(op)) {
5599
5781
  startOpIdx = i + 1;
5600
5782
  break;
5601
5783
  }