@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.cjs CHANGED
@@ -596,10 +596,52 @@ function promoteAlignFromCellOps(cell) {
596
596
  }
597
597
  return cell;
598
598
  }
599
+ function parseVerticalAlign(value) {
600
+ const normalized = value?.trim().toLowerCase();
601
+ if (!normalized) return null;
602
+ if (normalized === "top" || normalized === "baseline" || normalized === "text-top") return "top";
603
+ if (normalized === "middle" || normalized === "center") return "middle";
604
+ if (normalized === "bottom" || normalized === "text-bottom") return "bottom";
605
+ return null;
606
+ }
607
+ function extractInlineVerticalAlign(element) {
608
+ const verticalAlign = element.style?.getPropertyValue?.("vertical-align");
609
+ const fromStyle = parseVerticalAlign(verticalAlign);
610
+ if (fromStyle) return fromStyle;
611
+ const style = element.getAttribute("style") || "";
612
+ const match = style.match(/vertical-align:\s*(top|middle|bottom|center|baseline|text-top|text-bottom)/i);
613
+ if (match?.[1]) {
614
+ const parsed = parseVerticalAlign(match[1]);
615
+ if (parsed) return parsed;
616
+ }
617
+ const msoMatch = style.match(/mso-vertical-align:\s*(top|middle|bottom|center)/i);
618
+ if (msoMatch?.[1]) {
619
+ const parsed = parseVerticalAlign(msoMatch[1]);
620
+ if (parsed) return parsed;
621
+ }
622
+ return null;
623
+ }
624
+ function extractCellVAlign(cell) {
625
+ const direct = extractInlineVerticalAlign(cell);
626
+ if (direct) return direct;
627
+ const children = cell.childNodes;
628
+ for (let i = 0; i < children.length; i++) {
629
+ const child = children[i];
630
+ if (!child || !isElement(child)) continue;
631
+ const tag = child.tagName.toLowerCase();
632
+ if (tag === "p" || tag === "div") {
633
+ const vAlign = extractInlineVerticalAlign(child);
634
+ if (vAlign) return vAlign;
635
+ }
636
+ }
637
+ return null;
638
+ }
599
639
  function renderExtendedRow(data, row, cols, defaultCellTag, context, pretty) {
600
640
  const nl = pretty ? "\n" : "";
601
641
  const ind = (level) => pretty ? " ".repeat(level) : "";
602
- let html = `${ind(2)}<tr>${nl}`;
642
+ const rowHeight = data.rowHeights?.[row];
643
+ const trStyle = rowHeight !== void 0 && rowHeight > 0 ? ` style="height: ${rowHeight}px"` : "";
644
+ let html = `${ind(2)}<tr${trStyle}>${nl}`;
603
645
  for (let c = 0; c < cols; c++) {
604
646
  const key = `${row}:${c}`;
605
647
  const cell = data.cells[key];
@@ -615,14 +657,17 @@ function renderExtendedRow(data, row, cols, defaultCellTag, context, pretty) {
615
657
  }
616
658
  const colDefault = data.colAligns?.[c] ?? "left";
617
659
  const effectiveAlign = resolveCellHorizontalAlign(cell, c, data.colAligns);
618
- let alignStyle = null;
660
+ const styleParts = [];
619
661
  if (effectiveAlign !== "left") {
620
- alignStyle = `text-align: ${effectiveAlign}`;
662
+ styleParts.push(`text-align: ${effectiveAlign}`);
621
663
  } else if (cell.align === "left" && colDefault !== "left") {
622
- alignStyle = "text-align: left";
664
+ styleParts.push("text-align: left");
665
+ }
666
+ if (cell.vAlign !== void 0 && cell.vAlign !== "top") {
667
+ styleParts.push(`vertical-align: ${cell.vAlign}`);
623
668
  }
624
- if (alignStyle) {
625
- attrs.push(`style="${alignStyle}"`);
669
+ if (styleParts.length > 0) {
670
+ attrs.push(`style="${styleParts.join("; ")}"`);
626
671
  }
627
672
  const attrStr = attrs.length > 0 ? " " + attrs.join(" ") : "";
628
673
  let content = "";
@@ -638,9 +683,15 @@ function isGfmCompatible(data) {
638
683
  if (data.colWidths && data.colWidths.some((w) => w > 0)) {
639
684
  return false;
640
685
  }
686
+ if (data.rowHeights && data.rowHeights.some((h) => h > 0)) {
687
+ return false;
688
+ }
641
689
  for (const cell of Object.values(data.cells)) {
642
690
  if (cell !== null && cell.align !== void 0) return false;
643
691
  }
692
+ for (const cell of Object.values(data.cells)) {
693
+ if (cell !== null && cell.vAlign !== void 0) return false;
694
+ }
644
695
  for (const cell of Object.values(data.cells)) {
645
696
  if (cell === null) return false;
646
697
  if (cell.colspan && cell.colspan > 1) return false;
@@ -750,6 +801,39 @@ function extractColWidths(table) {
750
801
  }
751
802
  return void 0;
752
803
  }
804
+ function extractRowHeightPx(row) {
805
+ const style = row.getAttribute("style") || "";
806
+ const heightMatch = style.match(/(?:^|;)\s*height:\s*([\d.]+)px/i);
807
+ if (heightMatch?.[1]) {
808
+ const n = parseFloat(heightMatch[1]);
809
+ if (Number.isFinite(n) && n > 0) return n;
810
+ }
811
+ const minHeightMatch = style.match(/(?:^|;)\s*min-height:\s*([\d.]+)px/i);
812
+ if (minHeightMatch?.[1]) {
813
+ const n = parseFloat(minHeightMatch[1]);
814
+ if (Number.isFinite(n) && n > 0) return n;
815
+ }
816
+ const heightAttr = row.getAttribute("height");
817
+ if (heightAttr) {
818
+ const n = parseFloat(heightAttr);
819
+ if (Number.isFinite(n) && n > 0) return n;
820
+ }
821
+ return null;
822
+ }
823
+ function extractRowHeights(rows) {
824
+ const heights = [];
825
+ let any = false;
826
+ for (const row of rows) {
827
+ const h = extractRowHeightPx(row);
828
+ if (h != null) {
829
+ heights.push(h);
830
+ any = true;
831
+ } else {
832
+ heights.push(0);
833
+ }
834
+ }
835
+ return any ? heights : void 0;
836
+ }
753
837
  function extractCellAlign(cell) {
754
838
  const direct = extractInlineHorizontalAlign(cell);
755
839
  if (direct) return direct;
@@ -821,6 +905,10 @@ function parseTableElement(table, context) {
821
905
  delete withoutAlign.align;
822
906
  cellData = withoutAlign;
823
907
  }
908
+ const htmlVAlign = extractCellVAlign(cell);
909
+ if (htmlVAlign && htmlVAlign !== "top") {
910
+ cellData = { ...cellData, vAlign: htmlVAlign };
911
+ }
824
912
  const cellKey = `${rowIdx}:${colIdx}`;
825
913
  cells[cellKey] = cellData;
826
914
  rawAligns[cellKey] = effectiveAlign;
@@ -875,6 +963,14 @@ function parseTableElement(table, context) {
875
963
  if (colWidths.length > totalCols) colWidths.length = totalCols;
876
964
  result.colWidths = colWidths;
877
965
  }
966
+ const rowHeights = extractRowHeights(rows);
967
+ if (rowHeights) {
968
+ while (rowHeights.length < totalRows) rowHeights.push(0);
969
+ if (rowHeights.length > totalRows) rowHeights.length = totalRows;
970
+ if (rowHeights.some((h) => h > 0)) {
971
+ result.rowHeights = rowHeights;
972
+ }
973
+ }
878
974
  if (colAligns.length > 0 && colAligns.some((a) => a !== null)) {
879
975
  while (colAligns.length < totalCols) colAligns.push(null);
880
976
  if (colAligns.length > totalCols) colAligns.length = totalCols;
@@ -934,6 +1030,14 @@ var tableBlockHandler = {
934
1030
  if (typeof w !== "number" || w < 0) return false;
935
1031
  }
936
1032
  }
1033
+ if (data.rowHeights !== void 0) {
1034
+ if (!Array.isArray(data.rowHeights) || data.rowHeights.length !== rows) {
1035
+ return false;
1036
+ }
1037
+ for (const h of data.rowHeights) {
1038
+ if (typeof h !== "number" || h < 0) return false;
1039
+ }
1040
+ }
937
1041
  if (data.colAligns !== void 0) {
938
1042
  if (!Array.isArray(data.colAligns) || data.colAligns.length !== cols) {
939
1043
  return false;