@scrider/formatter 1.8.2 → 1.8.4

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.d.cts CHANGED
@@ -523,6 +523,8 @@ interface TableBlockData {
523
523
  headerRows?: number;
524
524
  /** Column widths (percentages by default) */
525
525
  colWidths?: number[];
526
+ /** Row heights in pixels (optional; auto when absent). */
527
+ rowHeights?: number[];
526
528
  /** Column alignments */
527
529
  colAligns?: (CellAlign | null)[];
528
530
  /** Cells indexed by "row:col" */
package/dist/index.d.ts CHANGED
@@ -523,6 +523,8 @@ interface TableBlockData {
523
523
  headerRows?: number;
524
524
  /** Column widths (percentages by default) */
525
525
  colWidths?: number[];
526
+ /** Row heights in pixels (optional; auto when absent). */
527
+ rowHeights?: number[];
526
528
  /** Column alignments */
527
529
  colAligns?: (CellAlign | null)[];
528
530
  /** Cells indexed by "row:col" */
package/dist/index.js CHANGED
@@ -466,10 +466,52 @@ function promoteAlignFromCellOps(cell) {
466
466
  }
467
467
  return cell;
468
468
  }
469
+ function parseVerticalAlign(value) {
470
+ const normalized = value?.trim().toLowerCase();
471
+ if (!normalized) return null;
472
+ if (normalized === "top" || normalized === "baseline" || normalized === "text-top") return "top";
473
+ if (normalized === "middle" || normalized === "center") return "middle";
474
+ if (normalized === "bottom" || normalized === "text-bottom") return "bottom";
475
+ return null;
476
+ }
477
+ function extractInlineVerticalAlign(element) {
478
+ const verticalAlign = element.style?.getPropertyValue?.("vertical-align");
479
+ const fromStyle = parseVerticalAlign(verticalAlign);
480
+ if (fromStyle) return fromStyle;
481
+ const style = element.getAttribute("style") || "";
482
+ const match = style.match(/vertical-align:\s*(top|middle|bottom|center|baseline|text-top|text-bottom)/i);
483
+ if (match?.[1]) {
484
+ const parsed = parseVerticalAlign(match[1]);
485
+ if (parsed) return parsed;
486
+ }
487
+ const msoMatch = style.match(/mso-vertical-align:\s*(top|middle|bottom|center)/i);
488
+ if (msoMatch?.[1]) {
489
+ const parsed = parseVerticalAlign(msoMatch[1]);
490
+ if (parsed) return parsed;
491
+ }
492
+ return null;
493
+ }
494
+ function extractCellVAlign(cell) {
495
+ const direct = extractInlineVerticalAlign(cell);
496
+ if (direct) return direct;
497
+ const children = cell.childNodes;
498
+ for (let i = 0; i < children.length; i++) {
499
+ const child = children[i];
500
+ if (!child || !isElement(child)) continue;
501
+ const tag = child.tagName.toLowerCase();
502
+ if (tag === "p" || tag === "div") {
503
+ const vAlign = extractInlineVerticalAlign(child);
504
+ if (vAlign) return vAlign;
505
+ }
506
+ }
507
+ return null;
508
+ }
469
509
  function renderExtendedRow(data, row, cols, defaultCellTag, context, pretty) {
470
510
  const nl = pretty ? "\n" : "";
471
511
  const ind = (level) => pretty ? " ".repeat(level) : "";
472
- let html = `${ind(2)}<tr>${nl}`;
512
+ const rowHeight = data.rowHeights?.[row];
513
+ const trStyle = rowHeight !== void 0 && rowHeight > 0 ? ` style="height: ${rowHeight}px"` : "";
514
+ let html = `${ind(2)}<tr${trStyle}>${nl}`;
473
515
  for (let c = 0; c < cols; c++) {
474
516
  const key = `${row}:${c}`;
475
517
  const cell = data.cells[key];
@@ -485,14 +527,17 @@ function renderExtendedRow(data, row, cols, defaultCellTag, context, pretty) {
485
527
  }
486
528
  const colDefault = data.colAligns?.[c] ?? "left";
487
529
  const effectiveAlign = resolveCellHorizontalAlign(cell, c, data.colAligns);
488
- let alignStyle = null;
530
+ const styleParts = [];
489
531
  if (effectiveAlign !== "left") {
490
- alignStyle = `text-align: ${effectiveAlign}`;
532
+ styleParts.push(`text-align: ${effectiveAlign}`);
491
533
  } else if (cell.align === "left" && colDefault !== "left") {
492
- alignStyle = "text-align: left";
534
+ styleParts.push("text-align: left");
535
+ }
536
+ if (cell.vAlign !== void 0 && cell.vAlign !== "top") {
537
+ styleParts.push(`vertical-align: ${cell.vAlign}`);
493
538
  }
494
- if (alignStyle) {
495
- attrs.push(`style="${alignStyle}"`);
539
+ if (styleParts.length > 0) {
540
+ attrs.push(`style="${styleParts.join("; ")}"`);
496
541
  }
497
542
  const attrStr = attrs.length > 0 ? " " + attrs.join(" ") : "";
498
543
  let content = "";
@@ -508,9 +553,15 @@ function isGfmCompatible(data) {
508
553
  if (data.colWidths && data.colWidths.some((w) => w > 0)) {
509
554
  return false;
510
555
  }
556
+ if (data.rowHeights && data.rowHeights.some((h) => h > 0)) {
557
+ return false;
558
+ }
511
559
  for (const cell of Object.values(data.cells)) {
512
560
  if (cell !== null && cell.align !== void 0) return false;
513
561
  }
562
+ for (const cell of Object.values(data.cells)) {
563
+ if (cell !== null && cell.vAlign !== void 0) return false;
564
+ }
514
565
  for (const cell of Object.values(data.cells)) {
515
566
  if (cell === null) return false;
516
567
  if (cell.colspan && cell.colspan > 1) return false;
@@ -620,6 +671,39 @@ function extractColWidths(table) {
620
671
  }
621
672
  return void 0;
622
673
  }
674
+ function extractRowHeightPx(row) {
675
+ const style = row.getAttribute("style") || "";
676
+ const heightMatch = style.match(/(?:^|;)\s*height:\s*([\d.]+)px/i);
677
+ if (heightMatch?.[1]) {
678
+ const n = parseFloat(heightMatch[1]);
679
+ if (Number.isFinite(n) && n > 0) return n;
680
+ }
681
+ const minHeightMatch = style.match(/(?:^|;)\s*min-height:\s*([\d.]+)px/i);
682
+ if (minHeightMatch?.[1]) {
683
+ const n = parseFloat(minHeightMatch[1]);
684
+ if (Number.isFinite(n) && n > 0) return n;
685
+ }
686
+ const heightAttr = row.getAttribute("height");
687
+ if (heightAttr) {
688
+ const n = parseFloat(heightAttr);
689
+ if (Number.isFinite(n) && n > 0) return n;
690
+ }
691
+ return null;
692
+ }
693
+ function extractRowHeights(rows) {
694
+ const heights = [];
695
+ let any = false;
696
+ for (const row of rows) {
697
+ const h = extractRowHeightPx(row);
698
+ if (h != null) {
699
+ heights.push(h);
700
+ any = true;
701
+ } else {
702
+ heights.push(0);
703
+ }
704
+ }
705
+ return any ? heights : void 0;
706
+ }
623
707
  function extractCellAlign(cell) {
624
708
  const direct = extractInlineHorizontalAlign(cell);
625
709
  if (direct) return direct;
@@ -691,6 +775,10 @@ function parseTableElement(table, context) {
691
775
  delete withoutAlign.align;
692
776
  cellData = withoutAlign;
693
777
  }
778
+ const htmlVAlign = extractCellVAlign(cell);
779
+ if (htmlVAlign && htmlVAlign !== "top") {
780
+ cellData = { ...cellData, vAlign: htmlVAlign };
781
+ }
694
782
  const cellKey = `${rowIdx}:${colIdx}`;
695
783
  cells[cellKey] = cellData;
696
784
  rawAligns[cellKey] = effectiveAlign;
@@ -745,6 +833,14 @@ function parseTableElement(table, context) {
745
833
  if (colWidths.length > totalCols) colWidths.length = totalCols;
746
834
  result.colWidths = colWidths;
747
835
  }
836
+ const rowHeights = extractRowHeights(rows);
837
+ if (rowHeights) {
838
+ while (rowHeights.length < totalRows) rowHeights.push(0);
839
+ if (rowHeights.length > totalRows) rowHeights.length = totalRows;
840
+ if (rowHeights.some((h) => h > 0)) {
841
+ result.rowHeights = rowHeights;
842
+ }
843
+ }
748
844
  if (colAligns.length > 0 && colAligns.some((a) => a !== null)) {
749
845
  while (colAligns.length < totalCols) colAligns.push(null);
750
846
  if (colAligns.length > totalCols) colAligns.length = totalCols;
@@ -804,6 +900,14 @@ var tableBlockHandler = {
804
900
  if (typeof w !== "number" || w < 0) return false;
805
901
  }
806
902
  }
903
+ if (data.rowHeights !== void 0) {
904
+ if (!Array.isArray(data.rowHeights) || data.rowHeights.length !== rows) {
905
+ return false;
906
+ }
907
+ for (const h of data.rowHeights) {
908
+ if (typeof h !== "number" || h < 0) return false;
909
+ }
910
+ }
807
911
  if (data.colAligns !== void 0) {
808
912
  if (!Array.isArray(data.colAligns) || data.colAligns.length !== cols) {
809
913
  return false;