@scrider/formatter 1.8.1 → 1.8.2
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 +120 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +149 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -492,6 +492,13 @@ function isTextNode(node) {
|
|
|
492
492
|
}
|
|
493
493
|
|
|
494
494
|
// src/schema/blocks/table.ts
|
|
495
|
+
var VALID_CELL_HORIZONTAL_ALIGNS = [
|
|
496
|
+
"left",
|
|
497
|
+
"center",
|
|
498
|
+
"right",
|
|
499
|
+
"justify"
|
|
500
|
+
];
|
|
501
|
+
var VALID_CELL_VERTICAL_ALIGNS = ["top", "middle", "bottom"];
|
|
495
502
|
var CELL_KEY_RE = /^(\d+):(\d+)$/;
|
|
496
503
|
function parseCellKey(key) {
|
|
497
504
|
const match = CELL_KEY_RE.exec(key);
|
|
@@ -512,7 +519,22 @@ function getGridDimensions(cells) {
|
|
|
512
519
|
return [maxRow + 1, maxCol + 1];
|
|
513
520
|
}
|
|
514
521
|
function isValidCellData(cell) {
|
|
515
|
-
|
|
522
|
+
if (typeof cell !== "object" || cell === null || !Array.isArray(cell.ops) || cell.ops.length === 0) {
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
if (cell.colspan !== void 0 && (!Number.isInteger(cell.colspan) || cell.colspan < 1)) {
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
if (cell.rowspan !== void 0 && (!Number.isInteger(cell.rowspan) || cell.rowspan < 1)) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
if (cell.align !== void 0 && !VALID_CELL_HORIZONTAL_ALIGNS.includes(cell.align)) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
if (cell.vAlign !== void 0 && !VALID_CELL_VERTICAL_ALIGNS.includes(cell.vAlign)) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
return true;
|
|
516
538
|
}
|
|
517
539
|
function validateMergedCells(cells, rows, cols) {
|
|
518
540
|
const covered = /* @__PURE__ */ new Set();
|
|
@@ -542,6 +564,38 @@ function validateMergedCells(cells, rows, cols) {
|
|
|
542
564
|
}
|
|
543
565
|
return true;
|
|
544
566
|
}
|
|
567
|
+
function parseHorizontalAlign(value) {
|
|
568
|
+
const normalized = value?.trim().toLowerCase();
|
|
569
|
+
if (normalized === "left" || normalized === "center" || normalized === "right") {
|
|
570
|
+
return normalized;
|
|
571
|
+
}
|
|
572
|
+
if (normalized === "justify") return "justify";
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
function resolveCellHorizontalAlign(cell, col, colAligns) {
|
|
576
|
+
if (cell.align !== void 0) return cell.align;
|
|
577
|
+
const colAlign = colAligns?.[col];
|
|
578
|
+
if (colAlign) return colAlign;
|
|
579
|
+
return "left";
|
|
580
|
+
}
|
|
581
|
+
function promoteAlignFromCellOps(cell) {
|
|
582
|
+
if (cell.align !== void 0) return cell;
|
|
583
|
+
for (let i = cell.ops.length - 1; i >= 0; i--) {
|
|
584
|
+
const op = cell.ops[i];
|
|
585
|
+
if (!op || !(0, import_delta2.isInsert)(op) || !(0, import_delta2.isTextInsert)(op) || !op.insert.includes("\n")) continue;
|
|
586
|
+
const align = op.attributes?.align;
|
|
587
|
+
const parsed = typeof align === "string" ? parseHorizontalAlign(align) : null;
|
|
588
|
+
if (!parsed) continue;
|
|
589
|
+
const ops = cell.ops.map((item, idx) => {
|
|
590
|
+
if (idx !== i || !(0, import_delta2.isInsert)(item) || item.attributes == null) return item;
|
|
591
|
+
const rest = { ...item.attributes };
|
|
592
|
+
delete rest.align;
|
|
593
|
+
return Object.keys(rest).length > 0 ? { insert: item.insert, attributes: rest } : { insert: item.insert };
|
|
594
|
+
});
|
|
595
|
+
return { ...cell, ops, align: parsed };
|
|
596
|
+
}
|
|
597
|
+
return cell;
|
|
598
|
+
}
|
|
545
599
|
function renderExtendedRow(data, row, cols, defaultCellTag, context, pretty) {
|
|
546
600
|
const nl = pretty ? "\n" : "";
|
|
547
601
|
const ind = (level) => pretty ? " ".repeat(level) : "";
|
|
@@ -559,11 +613,16 @@ function renderExtendedRow(data, row, cols, defaultCellTag, context, pretty) {
|
|
|
559
613
|
if (cell.rowspan && cell.rowspan > 1) {
|
|
560
614
|
attrs.push(`rowspan="${cell.rowspan}"`);
|
|
561
615
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
616
|
+
const colDefault = data.colAligns?.[c] ?? "left";
|
|
617
|
+
const effectiveAlign = resolveCellHorizontalAlign(cell, c, data.colAligns);
|
|
618
|
+
let alignStyle = null;
|
|
619
|
+
if (effectiveAlign !== "left") {
|
|
620
|
+
alignStyle = `text-align: ${effectiveAlign}`;
|
|
621
|
+
} else if (cell.align === "left" && colDefault !== "left") {
|
|
622
|
+
alignStyle = "text-align: left";
|
|
623
|
+
}
|
|
624
|
+
if (alignStyle) {
|
|
625
|
+
attrs.push(`style="${alignStyle}"`);
|
|
567
626
|
}
|
|
568
627
|
const attrStr = attrs.length > 0 ? " " + attrs.join(" ") : "";
|
|
569
628
|
let content = "";
|
|
@@ -579,6 +638,9 @@ function isGfmCompatible(data) {
|
|
|
579
638
|
if (data.colWidths && data.colWidths.some((w) => w > 0)) {
|
|
580
639
|
return false;
|
|
581
640
|
}
|
|
641
|
+
for (const cell of Object.values(data.cells)) {
|
|
642
|
+
if (cell !== null && cell.align !== void 0) return false;
|
|
643
|
+
}
|
|
582
644
|
for (const cell of Object.values(data.cells)) {
|
|
583
645
|
if (cell === null) return false;
|
|
584
646
|
if (cell.colspan && cell.colspan > 1) return false;
|
|
@@ -689,14 +751,28 @@ function extractColWidths(table) {
|
|
|
689
751
|
return void 0;
|
|
690
752
|
}
|
|
691
753
|
function extractCellAlign(cell) {
|
|
692
|
-
const
|
|
693
|
-
if (
|
|
694
|
-
|
|
754
|
+
const direct = extractInlineHorizontalAlign(cell);
|
|
755
|
+
if (direct) return direct;
|
|
756
|
+
const children = cell.childNodes;
|
|
757
|
+
for (let i = 0; i < children.length; i++) {
|
|
758
|
+
const child = children[i];
|
|
759
|
+
if (!child || !isElement(child)) continue;
|
|
760
|
+
const tag = child.tagName.toLowerCase();
|
|
761
|
+
if (tag === "p" || tag === "div") {
|
|
762
|
+
const align = extractInlineHorizontalAlign(child);
|
|
763
|
+
if (align) return align;
|
|
764
|
+
}
|
|
695
765
|
}
|
|
696
|
-
|
|
697
|
-
|
|
766
|
+
return null;
|
|
767
|
+
}
|
|
768
|
+
function extractInlineHorizontalAlign(element) {
|
|
769
|
+
const textAlign = element.style?.textAlign || element.style?.getPropertyValue?.("text-align");
|
|
770
|
+
const fromStyle = parseHorizontalAlign(textAlign);
|
|
771
|
+
if (fromStyle) return fromStyle;
|
|
772
|
+
const style = element.getAttribute("style") || "";
|
|
773
|
+
const match = style.match(/text-align:\s*(left|center|right|justify)/i);
|
|
698
774
|
if (match?.[1]) {
|
|
699
|
-
return match[1];
|
|
775
|
+
return parseHorizontalAlign(match[1]);
|
|
700
776
|
}
|
|
701
777
|
return null;
|
|
702
778
|
}
|
|
@@ -705,6 +781,7 @@ function parseTableElement(table, context) {
|
|
|
705
781
|
if (rows.length === 0) return null;
|
|
706
782
|
const cells = {};
|
|
707
783
|
const colAligns = [];
|
|
784
|
+
const rawAligns = {};
|
|
708
785
|
let maxCol = 0;
|
|
709
786
|
let firstRowProcessed = false;
|
|
710
787
|
const occupied = /* @__PURE__ */ new Set();
|
|
@@ -733,10 +810,20 @@ function parseTableElement(table, context) {
|
|
|
733
810
|
} else {
|
|
734
811
|
ops = [{ insert: "\n" }];
|
|
735
812
|
}
|
|
736
|
-
|
|
813
|
+
let cellData = { ops };
|
|
737
814
|
if (colspan > 1) cellData.colspan = colspan;
|
|
738
815
|
if (rowspan > 1) cellData.rowspan = rowspan;
|
|
739
|
-
|
|
816
|
+
cellData = promoteAlignFromCellOps(cellData);
|
|
817
|
+
const htmlAlign = extractCellAlign(cell);
|
|
818
|
+
const effectiveAlign = htmlAlign ?? cellData.align ?? "left";
|
|
819
|
+
if (cellData.align !== void 0) {
|
|
820
|
+
const withoutAlign = { ...cellData };
|
|
821
|
+
delete withoutAlign.align;
|
|
822
|
+
cellData = withoutAlign;
|
|
823
|
+
}
|
|
824
|
+
const cellKey = `${rowIdx}:${colIdx}`;
|
|
825
|
+
cells[cellKey] = cellData;
|
|
826
|
+
rawAligns[cellKey] = effectiveAlign;
|
|
740
827
|
for (let dr = 0; dr < rowspan; dr++) {
|
|
741
828
|
for (let dc = 0; dc < colspan; dc++) {
|
|
742
829
|
if (dr === 0 && dc === 0) continue;
|
|
@@ -750,8 +837,9 @@ function parseTableElement(table, context) {
|
|
|
750
837
|
}
|
|
751
838
|
if (!firstRowProcessed) {
|
|
752
839
|
const align = extractCellAlign(cell);
|
|
840
|
+
const colAlign = align === "center" || align === "right" ? align : null;
|
|
753
841
|
for (let dc = 0; dc < colspan; dc++) {
|
|
754
|
-
colAligns.push(
|
|
842
|
+
colAligns.push(colAlign);
|
|
755
843
|
}
|
|
756
844
|
}
|
|
757
845
|
const cellEndCol = colIdx + colspan - 1;
|
|
@@ -792,6 +880,18 @@ function parseTableElement(table, context) {
|
|
|
792
880
|
if (colAligns.length > totalCols) colAligns.length = totalCols;
|
|
793
881
|
result.colAligns = colAligns;
|
|
794
882
|
}
|
|
883
|
+
for (let r = 0; r < totalRows; r++) {
|
|
884
|
+
for (let c = 0; c < totalCols; c++) {
|
|
885
|
+
const key = `${r}:${c}`;
|
|
886
|
+
const cell = result.cells[key];
|
|
887
|
+
if (cell == null) continue;
|
|
888
|
+
const colDefault = result.colAligns?.[c] ?? "left";
|
|
889
|
+
const effective = rawAligns[key] ?? "left";
|
|
890
|
+
if (effective !== colDefault) {
|
|
891
|
+
result.cells[key] = { ...cell, align: effective };
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
795
895
|
return result;
|
|
796
896
|
}
|
|
797
897
|
var tableBlockHandler = {
|
|
@@ -903,8 +1003,11 @@ var tableBlockHandler = {
|
|
|
903
1003
|
for (const [key, cell] of Object.entries(data.cells)) {
|
|
904
1004
|
if (cell !== null) {
|
|
905
1005
|
const normalized = normalizeDelta(new import_delta2.Delta(cell.ops), registry);
|
|
906
|
-
|
|
907
|
-
|
|
1006
|
+
const promoted = promoteAlignFromCellOps(
|
|
1007
|
+
normalized.ops !== cell.ops ? { ...cell, ops: normalized.ops } : cell
|
|
1008
|
+
);
|
|
1009
|
+
if (promoted.ops !== cell.ops || promoted.align !== cell.align) {
|
|
1010
|
+
newCells[key] = promoted;
|
|
908
1011
|
changed = true;
|
|
909
1012
|
} else {
|
|
910
1013
|
newCells[key] = cell;
|