@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.js CHANGED
@@ -333,6 +333,20 @@ function cloneDelta(delta) {
333
333
  return new Delta(deepClone(delta.ops));
334
334
  }
335
335
 
336
+ // src/conversion/markdown/table-header-markdown.ts
337
+ function isHeaderDashPlaceholder(text) {
338
+ const t = text.trim();
339
+ return t === "-" && t.length === 1;
340
+ }
341
+ function normalizeHeaderCellForParse(text, isHeaderRow) {
342
+ if (isHeaderRow && isHeaderDashPlaceholder(text)) return "";
343
+ return text;
344
+ }
345
+ function serializeHeaderCell(text) {
346
+ if (text.trim() === "") return "-";
347
+ return text;
348
+ }
349
+
336
350
  // src/conversion/adapters/types.ts
337
351
  var NODE_TYPE = {
338
352
  ELEMENT_NODE: 1,
@@ -454,19 +468,21 @@ function renderGfmTable(data, context) {
454
468
  if (headerRows === 0) {
455
469
  const emptyParts = [];
456
470
  for (let c = 0; c < cols; c++) {
457
- emptyParts.push(" ");
471
+ emptyParts.push("");
458
472
  }
459
473
  lines.push("| " + emptyParts.join(" | ") + " |");
460
474
  lines.push(renderGfmSeparator(cols, data.colAligns));
461
475
  }
462
476
  for (let r = 0; r < rows; r++) {
463
477
  const parts = [];
478
+ const isHeaderRow = headerRows > 0 && r < headerRows;
464
479
  for (let c = 0; c < cols; c++) {
465
480
  const cell = data.cells[`${r}:${c}`];
466
481
  let text = "";
467
482
  if (cell && context.renderDelta) {
468
483
  text = stripCellContent(context.renderDelta(cell.ops));
469
484
  }
485
+ if (isHeaderRow) text = serializeHeaderCell(text);
470
486
  parts.push(text.replace(/\|/g, "\\|"));
471
487
  }
472
488
  lines.push("| " + parts.join(" | ") + " |");
@@ -4432,7 +4448,15 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
4432
4448
  if (headerRows.length > 0) {
4433
4449
  for (const [, row] of headerRows) {
4434
4450
  mdLines.push(
4435
- renderMdRow(row.cells, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
4451
+ renderMdRow(
4452
+ row.cells,
4453
+ maxCol,
4454
+ embedRenderers,
4455
+ useLatexDelimiters,
4456
+ registry,
4457
+ softBreakStyle,
4458
+ true
4459
+ )
4436
4460
  );
4437
4461
  }
4438
4462
  mdLines.push(renderMdSeparator(maxCol, colAligns));
@@ -4442,22 +4466,38 @@ function renderMarkdownTable(tableLines, embedRenderers, useLatexDelimiters = fa
4442
4466
  emptyRow.set(col, { ops: [] });
4443
4467
  }
4444
4468
  mdLines.push(
4445
- renderMdRow(emptyRow, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
4469
+ renderMdRow(
4470
+ emptyRow,
4471
+ maxCol,
4472
+ embedRenderers,
4473
+ useLatexDelimiters,
4474
+ registry,
4475
+ softBreakStyle,
4476
+ false
4477
+ )
4446
4478
  );
4447
4479
  mdLines.push(renderMdSeparator(maxCol, colAligns));
4448
4480
  }
4449
4481
  for (const [, row] of bodyRows) {
4450
4482
  mdLines.push(
4451
- renderMdRow(row.cells, maxCol, embedRenderers, useLatexDelimiters, registry, softBreakStyle)
4483
+ renderMdRow(
4484
+ row.cells,
4485
+ maxCol,
4486
+ embedRenderers,
4487
+ useLatexDelimiters,
4488
+ registry,
4489
+ softBreakStyle,
4490
+ false
4491
+ )
4452
4492
  );
4453
4493
  }
4454
4494
  return mdLines.join("\n");
4455
4495
  }
4456
- function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces") {
4496
+ function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false, registry, softBreakStyle = "spaces", isHeaderRow = false) {
4457
4497
  const parts = [];
4458
4498
  for (let col = 0; col <= maxCol; col++) {
4459
4499
  const cell = cells.get(col);
4460
- const content = cell ? renderLineContent2(
4500
+ let content = cell ? renderLineContent2(
4461
4501
  cell.ops,
4462
4502
  embedRenderers,
4463
4503
  false,
@@ -4469,6 +4509,7 @@ function renderMdRow(cells, maxCol, embedRenderers, useLatexDelimiters = false,
4469
4509
  true
4470
4510
  // inTableCell — softBreak must use <br>, never " \n"
4471
4511
  ) : "";
4512
+ if (isHeaderRow) content = serializeHeaderCell(content);
4472
4513
  parts.push(content.replace(/\|/g, "\\|"));
4473
4514
  }
4474
4515
  return "| " + parts.join(" | ") + " |";
@@ -4733,7 +4774,138 @@ function renderBlockFormat(content, attributes, orderedIndex, _strict) {
4733
4774
  }
4734
4775
 
4735
4776
  // src/conversion/markdown/markdown-to-delta.ts
4736
- import { Delta as Delta10 } from "@scrider/delta";
4777
+ import { Delta as Delta10, isInsert as isInsert5 } from "@scrider/delta";
4778
+
4779
+ // src/conversion/markdown/table-header-normalize.ts
4780
+ import { isInsert as isInsert4 } from "@scrider/delta";
4781
+ function isTableCellTerminator(op) {
4782
+ return isInsert4(op) && typeof op.insert === "string" && op.insert === "\n" && op.attributes !== void 0 && typeof op.attributes["table-row"] === "number";
4783
+ }
4784
+ function normalizeSyntheticEmptyHeaderRow(ops) {
4785
+ const ends = [];
4786
+ let buf = "";
4787
+ const textOpIndicesByCell = [];
4788
+ let currentTextOps = [];
4789
+ for (let i = 0; i < ops.length; i++) {
4790
+ const op = ops[i];
4791
+ if (!isInsert4(op)) continue;
4792
+ if (typeof op.insert === "string" && op.insert !== "\n") {
4793
+ buf += op.insert;
4794
+ currentTextOps.push(i);
4795
+ continue;
4796
+ }
4797
+ if (isTableCellTerminator(op)) {
4798
+ const row = op.attributes["table-row"];
4799
+ const col = op.attributes["table-col"];
4800
+ ends.push({ row, col, newlineIdx: i, text: buf });
4801
+ textOpIndicesByCell.push([...currentTextOps]);
4802
+ buf = "";
4803
+ currentTextOps = [];
4804
+ }
4805
+ }
4806
+ const row0 = ends.filter((e) => e.row === 0);
4807
+ if (row0.length === 0) return [...ops];
4808
+ if (!row0.every((e) => e.text.trim() === "")) return [...ops];
4809
+ if (row0.some((e) => isHeaderDashPlaceholder(e.text))) return [...ops];
4810
+ const remove = /* @__PURE__ */ new Set();
4811
+ for (let j = 0; j < ends.length; j++) {
4812
+ const end = ends[j];
4813
+ if (end.row !== 0) continue;
4814
+ remove.add(end.newlineIdx);
4815
+ for (const ti of textOpIndicesByCell[j] ?? []) remove.add(ti);
4816
+ }
4817
+ const out = [];
4818
+ for (let i = 0; i < ops.length; i++) {
4819
+ if (remove.has(i)) continue;
4820
+ const op = ops[i];
4821
+ if (!isTableCellTerminator(op)) {
4822
+ out.push(op);
4823
+ continue;
4824
+ }
4825
+ const row = op.attributes["table-row"];
4826
+ if (row === 0) continue;
4827
+ const attrs = { ...op.attributes };
4828
+ delete attrs["table-header"];
4829
+ out.push({
4830
+ insert: "\n",
4831
+ attributes: { ...attrs, "table-row": row - 1 }
4832
+ });
4833
+ }
4834
+ return out;
4835
+ }
4836
+ function normalizeHeaderDashPlaceholders(ops) {
4837
+ const ends = [];
4838
+ let buf = "";
4839
+ let currentTextOps = [];
4840
+ for (let i = 0; i < ops.length; i++) {
4841
+ const op = ops[i];
4842
+ if (!isInsert4(op)) continue;
4843
+ if (typeof op.insert === "string" && op.insert !== "\n") {
4844
+ buf += op.insert;
4845
+ currentTextOps.push(i);
4846
+ continue;
4847
+ }
4848
+ if (isTableCellTerminator(op)) {
4849
+ const row = op.attributes["table-row"];
4850
+ const isHeader = row === 0 && op.attributes["table-header"] === true;
4851
+ ends.push({ isHeader, textOpIndices: [...currentTextOps], text: buf });
4852
+ buf = "";
4853
+ currentTextOps = [];
4854
+ }
4855
+ }
4856
+ const dashHeaderCells = ends.filter(
4857
+ (e) => e.isHeader && e.textOpIndices.length > 0 && isHeaderDashPlaceholder(e.text)
4858
+ );
4859
+ if (dashHeaderCells.length === 0) return [...ops];
4860
+ const replaceIndices = /* @__PURE__ */ new Set();
4861
+ for (const end of dashHeaderCells) {
4862
+ for (const ti of end.textOpIndices) replaceIndices.add(ti);
4863
+ }
4864
+ const out = [];
4865
+ for (let i = 0; i < ops.length; i++) {
4866
+ const op = ops[i];
4867
+ if (!replaceIndices.has(i)) {
4868
+ out.push(op);
4869
+ continue;
4870
+ }
4871
+ if (!isInsert4(op)) {
4872
+ out.push(op);
4873
+ continue;
4874
+ }
4875
+ if (typeof op.insert === "string" && op.insert !== "\n") {
4876
+ const normalized = normalizeHeaderCellForParse(op.insert, true);
4877
+ if (normalized.length === 0) continue;
4878
+ out.push(
4879
+ op.attributes ? { insert: normalized, attributes: op.attributes } : { insert: normalized }
4880
+ );
4881
+ } else {
4882
+ out.push(op);
4883
+ }
4884
+ }
4885
+ return out;
4886
+ }
4887
+ function normalizeImportedTableOps(ops) {
4888
+ if (ops.length === 0) return [...ops];
4889
+ const ends = [];
4890
+ let buf = "";
4891
+ for (const op of ops) {
4892
+ if (!isInsert4(op)) continue;
4893
+ if (typeof op.insert === "string" && op.insert !== "\n") {
4894
+ buf += op.insert;
4895
+ continue;
4896
+ }
4897
+ if (isTableCellTerminator(op)) {
4898
+ ends.push({ row: op.attributes["table-row"], text: buf });
4899
+ buf = "";
4900
+ }
4901
+ }
4902
+ const row0 = ends.filter((e) => e.row === 0);
4903
+ const headerless = row0.length > 0 && row0.every((e) => e.text.trim() === "") && !row0.some((e) => isHeaderDashPlaceholder(e.text));
4904
+ if (headerless) return normalizeSyntheticEmptyHeaderRow(ops);
4905
+ return normalizeHeaderDashPlaceholders(ops);
4906
+ }
4907
+
4908
+ // src/conversion/markdown/markdown-to-delta.ts
4737
4909
  var remarkParse = null;
4738
4910
  var remarkGfm = null;
4739
4911
  var remarkMath = null;
@@ -5222,6 +5394,7 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
5222
5394
  }
5223
5395
  function processTable(node) {
5224
5396
  if (!node.children) return;
5397
+ const tableStart = delta.ops.length;
5225
5398
  const aligns = node.align || [];
5226
5399
  for (let rowIdx = 0; rowIdx < node.children.length; rowIdx++) {
5227
5400
  const rowNode = node.children[rowIdx];
@@ -5250,6 +5423,15 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
5250
5423
  context.pushNewline(cellBlockAttrs);
5251
5424
  }
5252
5425
  }
5426
+ const tableOps = delta.ops.splice(tableStart);
5427
+ for (const op of normalizeImportedTableOps(tableOps)) {
5428
+ if (!isInsert5(op)) continue;
5429
+ if (op.attributes && Object.keys(op.attributes).length > 0) {
5430
+ delta.insert(op.insert, op.attributes);
5431
+ } else {
5432
+ delta.insert(op.insert);
5433
+ }
5434
+ }
5253
5435
  }
5254
5436
  function isBlockLevelHtml(html) {
5255
5437
  return /^\s*<(div|table|section|article|aside|nav|header|footer|figure|pre|hr|ol|ul|dl|details|iframe|video)\b/i.test(
@@ -5431,9 +5613,9 @@ function astToDelta(tree, customHandlers, mathBlock, mermaidBlock, plantumlBlock
5431
5613
  }
5432
5614
 
5433
5615
  // src/conversion/markdown/table-region.ts
5434
- import { isInsert as isInsert4, isTextInsert as isTextInsert3 } from "@scrider/delta";
5616
+ import { isInsert as isInsert6, isTextInsert as isTextInsert3 } from "@scrider/delta";
5435
5617
  function isTableNewlineOp(op) {
5436
- if (!op || !isInsert4(op) || !isTextInsert3(op)) return false;
5618
+ if (!op || !isInsert6(op) || !isTextInsert3(op)) return false;
5437
5619
  if (!op.insert.includes("\n")) return false;
5438
5620
  return !!op.attributes && "table-row" in op.attributes;
5439
5621
  }
@@ -5442,7 +5624,7 @@ function extractTableRegion(ops, hintOpIdx) {
5442
5624
  let probeIdx = -1;
5443
5625
  for (let i = hintOpIdx; i < ops.length; i++) {
5444
5626
  const op = ops[i];
5445
- if (!op || !isInsert4(op)) continue;
5627
+ if (!op || !isInsert6(op)) continue;
5446
5628
  if (isTextInsert3(op) && op.insert.includes("\n")) {
5447
5629
  probeIdx = i;
5448
5630
  break;
@@ -5453,7 +5635,7 @@ function extractTableRegion(ops, hintOpIdx) {
5453
5635
  let endOpIdx = probeIdx;
5454
5636
  for (let i = probeIdx + 1; i < ops.length; i++) {
5455
5637
  const op = ops[i];
5456
- if (!op || !isInsert4(op)) break;
5638
+ if (!op || !isInsert6(op)) break;
5457
5639
  if (isTextInsert3(op) && op.insert.includes("\n")) {
5458
5640
  if (isTableNewlineOp(op)) {
5459
5641
  endOpIdx = i;
@@ -5465,7 +5647,7 @@ function extractTableRegion(ops, hintOpIdx) {
5465
5647
  let startOpIdx = 0;
5466
5648
  for (let i = probeIdx - 1; i >= 0; i--) {
5467
5649
  const op = ops[i];
5468
- if (!op || !isInsert4(op)) {
5650
+ if (!op || !isInsert6(op)) {
5469
5651
  startOpIdx = i + 1;
5470
5652
  break;
5471
5653
  }