@scrider/formatter 1.3.3 → 1.3.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/README.md +17 -0
- package/dist/index.cjs +93 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +91 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -77,6 +77,23 @@ deltaToHtml(delta, { registry }) // Delta → HTML string
|
|
|
77
77
|
htmlToDelta(html, { registry }) // HTML string → Delta
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
+
**Simple Table presentation (v1.3.4+)** — inline borders/shades for clipboard and Office paste (Delta structure unchanged):
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { deltaToHtml, type TablePresentation } from '@scrider/formatter';
|
|
84
|
+
|
|
85
|
+
const tablePresentation: TablePresentation = {
|
|
86
|
+
grid: true,
|
|
87
|
+
borderColor: '#e7e7e7',
|
|
88
|
+
headerBold: true,
|
|
89
|
+
headerCenter: true,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
deltaToHtml(delta, { tablePresentation });
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
See scrider-editor `docs/simple-tables.md` §8 for the full contract (`grid` / `line`, `headerShade`, `zebraRows`, `defaultCellAlign`, …).
|
|
96
|
+
|
|
80
97
|
### Markdown Conversion
|
|
81
98
|
|
|
82
99
|
```typescript
|
package/dist/index.cjs
CHANGED
|
@@ -82,6 +82,7 @@ __export(index_exports, {
|
|
|
82
82
|
isTextNode: () => isTextNode,
|
|
83
83
|
isValidColor: () => isValidColor,
|
|
84
84
|
isValidHexColor: () => isValidHexColor,
|
|
85
|
+
isZebraBodyRow: () => isZebraBodyRow,
|
|
85
86
|
italicFormat: () => italicFormat,
|
|
86
87
|
kbdFormat: () => kbdFormat,
|
|
87
88
|
linkFormat: () => linkFormat,
|
|
@@ -92,6 +93,7 @@ __export(index_exports, {
|
|
|
92
93
|
nodeAdapter: () => nodeAdapter,
|
|
93
94
|
normalizeDelta: () => normalizeDelta,
|
|
94
95
|
preloadRemark: () => preloadRemark,
|
|
96
|
+
resolveTablePresentation: () => resolveTablePresentation,
|
|
95
97
|
sanitizeDelta: () => sanitizeDelta,
|
|
96
98
|
sizeFormat: () => sizeFormat,
|
|
97
99
|
slugify: () => slugify,
|
|
@@ -2599,6 +2601,68 @@ function slugifyWithDedup(text, usedSlugs) {
|
|
|
2599
2601
|
return `${base}-${count}`;
|
|
2600
2602
|
}
|
|
2601
2603
|
|
|
2604
|
+
// src/conversion/html/table-presentation.ts
|
|
2605
|
+
var DEFAULT_BORDER_COLOR = "#e7e7e7";
|
|
2606
|
+
var DEFAULT_HEADER_BG = "#f5f5f5";
|
|
2607
|
+
var DEFAULT_ZEBRA_BG = "#fafafa";
|
|
2608
|
+
var CELL_PADDING = "6px 13px";
|
|
2609
|
+
function resolveTablePresentation(presentation) {
|
|
2610
|
+
return {
|
|
2611
|
+
grid: presentation?.grid === true,
|
|
2612
|
+
line: presentation?.line === true && presentation?.grid !== true,
|
|
2613
|
+
borderColor: presentation?.borderColor ?? DEFAULT_BORDER_COLOR,
|
|
2614
|
+
headerShade: presentation?.headerShade === true,
|
|
2615
|
+
zebraRows: presentation?.zebraRows === true,
|
|
2616
|
+
headerBold: presentation?.headerBold === true,
|
|
2617
|
+
headerCenter: presentation?.headerCenter === true,
|
|
2618
|
+
defaultCellAlign: presentation?.defaultCellAlign ?? "left"
|
|
2619
|
+
};
|
|
2620
|
+
}
|
|
2621
|
+
function isZebraBodyRow(headerRowCount, bodyRowIndex) {
|
|
2622
|
+
return (headerRowCount + bodyRowIndex + 1) % 2 === 0;
|
|
2623
|
+
}
|
|
2624
|
+
function isTableCellAlign(value) {
|
|
2625
|
+
return value === "left" || value === "center" || value === "right";
|
|
2626
|
+
}
|
|
2627
|
+
function tableOpenTag(presentation) {
|
|
2628
|
+
if (!presentation.grid && !presentation.line) {
|
|
2629
|
+
return "<table>";
|
|
2630
|
+
}
|
|
2631
|
+
return `<table style="border-collapse: collapse">`;
|
|
2632
|
+
}
|
|
2633
|
+
function buildTableCellStyleAttr(params) {
|
|
2634
|
+
const { presentation, cellTag, colAlign, headerRowCount, bodyRowIndex } = params;
|
|
2635
|
+
const parts = [];
|
|
2636
|
+
parts.push(`padding: ${CELL_PADDING}`);
|
|
2637
|
+
const color = presentation.borderColor;
|
|
2638
|
+
if (presentation.grid) {
|
|
2639
|
+
parts.push(`border: 1px solid ${color}`);
|
|
2640
|
+
} else if (presentation.line) {
|
|
2641
|
+
const width = cellTag === "th" ? "1px" : "0.5px";
|
|
2642
|
+
parts.push(`border-bottom: ${width} solid ${color}`);
|
|
2643
|
+
}
|
|
2644
|
+
let textAlign;
|
|
2645
|
+
if (cellTag === "th" && presentation.headerCenter) {
|
|
2646
|
+
textAlign = "center";
|
|
2647
|
+
} else if (isTableCellAlign(colAlign)) {
|
|
2648
|
+
textAlign = colAlign;
|
|
2649
|
+
} else if (colAlign == null || colAlign === "left") {
|
|
2650
|
+
textAlign = presentation.defaultCellAlign;
|
|
2651
|
+
}
|
|
2652
|
+
if (textAlign && textAlign !== "left") {
|
|
2653
|
+
parts.push(`text-align: ${textAlign}`);
|
|
2654
|
+
}
|
|
2655
|
+
if (cellTag === "th" && presentation.headerBold) {
|
|
2656
|
+
parts.push("font-weight: bold");
|
|
2657
|
+
}
|
|
2658
|
+
if (cellTag === "th" && presentation.headerShade) {
|
|
2659
|
+
parts.push(`background-color: ${DEFAULT_HEADER_BG}`);
|
|
2660
|
+
} else if (cellTag === "td" && presentation.zebraRows && bodyRowIndex !== void 0 && isZebraBodyRow(headerRowCount, bodyRowIndex)) {
|
|
2661
|
+
parts.push(`background-color: ${DEFAULT_ZEBRA_BG}`);
|
|
2662
|
+
}
|
|
2663
|
+
return ` style="${parts.join("; ")}"`;
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2602
2666
|
// src/conversion/html/delta-to-html.ts
|
|
2603
2667
|
function deltaToHtml(delta, options = {}) {
|
|
2604
2668
|
const lines = splitIntoLines(delta);
|
|
@@ -2782,7 +2846,10 @@ function renderTable(tableLines, embedRenderers, pretty, blockHandlers, options)
|
|
|
2782
2846
|
const bodyRows = sortedRows.filter(([, r]) => !r.isHeader);
|
|
2783
2847
|
const indent = pretty ? " " : "";
|
|
2784
2848
|
const nl = pretty ? "\n" : "";
|
|
2785
|
-
|
|
2849
|
+
const usePresentation = options?.tablePresentation !== void 0;
|
|
2850
|
+
const presentation = usePresentation ? resolveTablePresentation(options.tablePresentation) : null;
|
|
2851
|
+
const headerRowCount = headerRows.length;
|
|
2852
|
+
let html = usePresentation && presentation ? `${tableOpenTag(presentation)}${nl}` : `<table>${nl}`;
|
|
2786
2853
|
if (headerRows.length > 0) {
|
|
2787
2854
|
html += `${indent}<thead>${nl}`;
|
|
2788
2855
|
for (const [, row] of headerRows) {
|
|
@@ -2794,13 +2861,16 @@ function renderTable(tableLines, embedRenderers, pretty, blockHandlers, options)
|
|
|
2794
2861
|
pretty,
|
|
2795
2862
|
2,
|
|
2796
2863
|
blockHandlers,
|
|
2797
|
-
options
|
|
2864
|
+
options,
|
|
2865
|
+
presentation,
|
|
2866
|
+
headerRowCount
|
|
2798
2867
|
);
|
|
2799
2868
|
}
|
|
2800
2869
|
html += `${indent}</thead>${nl}`;
|
|
2801
2870
|
}
|
|
2802
2871
|
if (bodyRows.length > 0) {
|
|
2803
2872
|
html += `${indent}<tbody>${nl}`;
|
|
2873
|
+
let bodyRowIndex = 0;
|
|
2804
2874
|
for (const [, row] of bodyRows) {
|
|
2805
2875
|
html += renderTableRow(
|
|
2806
2876
|
row.cells,
|
|
@@ -2810,8 +2880,12 @@ function renderTable(tableLines, embedRenderers, pretty, blockHandlers, options)
|
|
|
2810
2880
|
pretty,
|
|
2811
2881
|
2,
|
|
2812
2882
|
blockHandlers,
|
|
2813
|
-
options
|
|
2883
|
+
options,
|
|
2884
|
+
presentation,
|
|
2885
|
+
headerRowCount,
|
|
2886
|
+
bodyRowIndex
|
|
2814
2887
|
);
|
|
2888
|
+
bodyRowIndex += 1;
|
|
2815
2889
|
}
|
|
2816
2890
|
html += `${indent}</tbody>${nl}`;
|
|
2817
2891
|
}
|
|
@@ -2819,7 +2893,7 @@ function renderTable(tableLines, embedRenderers, pretty, blockHandlers, options)
|
|
|
2819
2893
|
if (pretty) html += "\n";
|
|
2820
2894
|
return html;
|
|
2821
2895
|
}
|
|
2822
|
-
function renderTableRow(cells, maxCol, cellTag, embedRenderers, pretty, depth, blockHandlers, options) {
|
|
2896
|
+
function renderTableRow(cells, maxCol, cellTag, embedRenderers, pretty, depth, blockHandlers, options, presentation, headerRowCount = 0, bodyRowIndex) {
|
|
2823
2897
|
const indent = pretty ? " ".repeat(depth) : "";
|
|
2824
2898
|
const cellIndent = pretty ? " ".repeat(depth + 1) : "";
|
|
2825
2899
|
const nl = pretty ? "\n" : "";
|
|
@@ -2827,8 +2901,19 @@ function renderTableRow(cells, maxCol, cellTag, embedRenderers, pretty, depth, b
|
|
|
2827
2901
|
for (let col = 0; col <= maxCol; col++) {
|
|
2828
2902
|
const cell = cells.get(col);
|
|
2829
2903
|
const content = cell ? renderLineContent(cell.ops, embedRenderers, blockHandlers, options) : "";
|
|
2830
|
-
|
|
2831
|
-
|
|
2904
|
+
let styleAttr = "";
|
|
2905
|
+
if (presentation) {
|
|
2906
|
+
styleAttr = buildTableCellStyleAttr({
|
|
2907
|
+
presentation,
|
|
2908
|
+
cellTag,
|
|
2909
|
+
colAlign: cell?.colAlign,
|
|
2910
|
+
headerRowCount,
|
|
2911
|
+
bodyRowIndex: cellTag === "td" ? bodyRowIndex : void 0
|
|
2912
|
+
});
|
|
2913
|
+
} else {
|
|
2914
|
+
styleAttr = cell?.colAlign && cell.colAlign !== "left" ? ` style="text-align: ${cell.colAlign}"` : "";
|
|
2915
|
+
}
|
|
2916
|
+
html += `${cellIndent}<${cellTag}${styleAttr}>${content}</${cellTag}>${nl}`;
|
|
2832
2917
|
}
|
|
2833
2918
|
html += `${indent}</tr>${nl}`;
|
|
2834
2919
|
return html;
|
|
@@ -5155,6 +5240,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5155
5240
|
isTextNode,
|
|
5156
5241
|
isValidColor,
|
|
5157
5242
|
isValidHexColor,
|
|
5243
|
+
isZebraBodyRow,
|
|
5158
5244
|
italicFormat,
|
|
5159
5245
|
kbdFormat,
|
|
5160
5246
|
linkFormat,
|
|
@@ -5165,6 +5251,7 @@ function extractTableRegion(ops, hintOpIdx) {
|
|
|
5165
5251
|
nodeAdapter,
|
|
5166
5252
|
normalizeDelta,
|
|
5167
5253
|
preloadRemark,
|
|
5254
|
+
resolveTablePresentation,
|
|
5168
5255
|
sanitizeDelta,
|
|
5169
5256
|
sizeFormat,
|
|
5170
5257
|
slugify,
|