PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.5
Tableberg – Simple Gutenberg Table Block v1.1.5
1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 trunk 0.0.2 0.2.1 0.3.2 0.3.3 0.4.1 0.5.0 0.5.1 0.5.2 0.5.3 0.5.4 0.5.5 0.5.6 0.5.7 All 42 releases
tableberg / src / transforms.ts

transforms.ts in Tableberg – Simple Gutenberg Table Block 1.1.5, at src/transforms.ts

151 lines 4.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { createBlock } from "@wordpress/blocks";
2 import {
3 attrDefaults,
4 attrVersion,
5 Cell,
6 CellKey,
7 getCellKey,
8 TablebergBlockAttrs,
9 } from "./attributes";
10 import { textAttributeDefaults } from "./elements";
11 import { buildRowBlocksFromV3, toV4Attrs } from "./migrate/v3-to-v4";
12
13 interface CoreTableCell {
14 content?: string;
15 align?: string;
16 colspan?: string;
17 rowspan?: string;
18 }
19
20 interface CoreTableRow {
21 cells?: CoreTableCell[];
22 }
23
24 interface CoreTableAttrs {
25 caption?: string;
26 hasFixedLayout?: boolean;
27 head?: CoreTableRow[];
28 body?: CoreTableRow[];
29 foot?: CoreTableRow[];
30 }
31
32 function normalizeSpan(value?: string): number {
33 const parsed = Number.parseInt(value || "", 10);
34
35 if (Number.isNaN(parsed) || parsed < 1) {
36 return 1;
37 }
38
39 return parsed;
40 }
41
42 function normalizeAlign(value?: string) {
43 if (value === "left" || value === "center" || value === "right") {
44 return value;
45 }
46
47 return textAttributeDefaults.align;
48 }
49
50 function buildTablebergAttrs(attributes: CoreTableAttrs): TablebergBlockAttrs {
51 const head = attributes.head || [];
52 const body = attributes.body || [];
53 const foot = attributes.foot || [];
54 const rows = [...head, ...body, ...foot];
55
56 const cells: Record<CellKey, Cell> = {};
57 const occupied = new Set<CellKey>();
58
59 rows.forEach((row, rowIndex) => {
60 let colIndex = 0;
61
62 (row.cells || []).forEach(cell => {
63 while (occupied.has(getCellKey(rowIndex, colIndex))) {
64 colIndex += 1;
65 }
66
67 const rowSpan = normalizeSpan(cell.rowspan);
68 const colSpan = normalizeSpan(cell.colspan);
69 const key = getCellKey(rowIndex, colIndex);
70
71 cells[key] = {
72 elements: [
73 {
74 name: "text",
75 attributes: {
76 ...textAttributeDefaults,
77 content: cell.content || "",
78 align: normalizeAlign(cell.align),
79 },
80 },
81 ],
82 ...(rowSpan > 1 || colSpan > 1
83 ? {
84 span: {
85 rowSpan,
86 colSpan,
87 },
88 }
89 : {}),
90 };
91
92 for (let rowOffset = 0; rowOffset < rowSpan; rowOffset++) {
93 for (let colOffset = 0; colOffset < colSpan; colOffset++) {
94 if (rowOffset === 0 && colOffset === 0) {
95 continue;
96 }
97
98 occupied.add(
99 getCellKey(rowIndex + rowOffset, colIndex + colOffset)
100 );
101 }
102 }
103
104 colIndex += colSpan;
105 });
106 });
107
108 const totalCols = Object.entries(cells).reduce((max, [key, cell]) => {
109 const [, colIndex] = key
110 .split(",")
111 .map(value => Number.parseInt(value, 10));
112 const colSpan = cell.span?.colSpan || 1;
113 return Math.max(max, colIndex + colSpan);
114 }, 0);
115
116 return {
117 ...attrDefaults,
118 version: attrVersion,
119 table: {
120 ...attrDefaults.table,
121 rows: rows.length,
122 cols: totalCols,
123 headerEnabled: head.length > 0,
124 footerEnabled: foot.length > 0,
125 caption: attributes.caption || "",
126 fixedColumnWidths: attributes.hasFixedLayout ?? true,
127 },
128 cells,
129 };
130 }
131
132 const transforms = {
133 from: [
134 {
135 type: "block" as const,
136 blocks: ["core/table"],
137 transform: (attributes: CoreTableAttrs) => {
138 const v3Attrs = buildTablebergAttrs(attributes);
139
140 return createBlock(
141 "tableberg/table",
142 toV4Attrs(v3Attrs),
143 buildRowBlocksFromV3(v3Attrs)
144 );
145 },
146 },
147 ],
148 } as any;
149
150 export default transforms;
151