@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 +110 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +110 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
530
|
+
const styleParts = [];
|
|
489
531
|
if (effectiveAlign !== "left") {
|
|
490
|
-
|
|
532
|
+
styleParts.push(`text-align: ${effectiveAlign}`);
|
|
491
533
|
} else if (cell.align === "left" && colDefault !== "left") {
|
|
492
|
-
|
|
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 (
|
|
495
|
-
attrs.push(`style="${
|
|
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;
|