import {
Align,
BorderLineStyle,
BorderType,
Border,
Cell,
Style,
VerticalAlign,
xy2expr,
Range,
} from '@wolf-table/table-renderer';
import Table from '.';
import { pt2px } from './helper';
/**
* the table content to html
* @param t Table
* @param from the range reference, like A1:H22
*/
export function toHtml(t: Table, from: string) {
let htmlStr =
'
';
const fromRange = Range.with(from);
// merges
const merges = t._data.merges
.map((it) => Range.with(it))
.filter((it) => it.intersects(fromRange));
// borders
// const borders = t._data.borders.filter((it) => Range.with(it[0]).intersects(fromRange));
const border2css = (lineStyle: BorderLineStyle, color: string) => {
if (lineStyle === 'dashed' || lineStyle === 'dotted') {
return `1px ${lineStyle} ${color}`;
} else {
return `${
lineStyle === 'thick' ? 3 : lineStyle === 'medium' ? 2 : 1
}px solid ${color}`;
}
};
const cellIndexes = new Map();
for (let border of t._data.borders) {
const [ref, borderType, lineStyle, color] = border;
// console.log('border:', border);
const it = Range.with(ref);
if (it.intersects(fromRange)) {
const { startRow, startCol, endRow, endCol } = it;
it.each((r, c) => {
const borderValue = border2css(lineStyle, color);
let borderNames = [];
if (borderType === 'all') {
borderNames.push('border');
}
if (borderType === 'outside' || borderType === 'left') {
if (c === startCol) borderNames.push('border-left');
}
if (borderType === 'outside' || borderType === 'right') {
if (c === endCol) borderNames.push('border-right');
}
if (borderType === 'outside' || borderType === 'top') {
if (r === startRow) borderNames.push('border-top');
}
if (borderType === 'outside' || borderType === 'bottom') {
if (r === endRow) borderNames.push('border-bottom');
}
if (borderType === 'inside' || borderType === 'vertical') {
if (c >= startCol && c < endCol) borderNames.push('border-right');
}
if (borderType === 'inside' || borderType === 'horizontal') {
if (r >= startRow && r < endRow) borderNames.push('border-bottom');
}
if (borderNames.length > 0) {
cellIndexes.set(
`${r}_${c}`,
borderNames.map((it) => `${it}:${borderValue};`).join('')
);
}
});
}
}
// colgroup
htmlStr += '';
fromRange.eachCol((c) => {
htmlStr += ``;
});
htmlStr += '';
// tr
htmlStr += '';
fromRange.eachRow((r) => {
htmlStr += ``;
fromRange.eachCol((c) => {
const cell = t.cell(r, c);
const cellRange = Range.create(r, c);
let isMerged = false;
let [rowspan, colspan] = [1, 1];
for (let merge of merges) {
if (merge.startRow === r && merge.startCol === c) {
rowspan = merge.rows + 1;
colspan = merge.cols + 1;
break;
}
if (merge.intersects(cellRange)) {
isMerged = true;
break;
}
}
if (!isMerged) {
htmlStr += `| 1) htmlStr += ` rowspan="${rowspan}"`;
if (colspan > 1) htmlStr += ` colspan="${colspan}"`;
let cssStyleStr = ''; // border2css(borders, cellRange);
const key = `${r}_${c}`;
if (cellIndexes.has(key)) {
cssStyleStr += cellIndexes.get(key);
}
if (cell && cell instanceof Object && cell.style !== undefined) {
cssStyleStr += style2css(t.style(cell.style, true));
}
if (cssStyleStr !== '') htmlStr += ` style="${cssStyleStr}"`;
htmlStr += `>${t.cellValueString(r, c)} | `;
}
});
htmlStr += '
';
});
return htmlStr + '
';
}
/**
* fill the table content from html
* @param t Table
* @param html content:
* @param to [row, col]
*/
export function fromHtml(
t: Table,
html: string,
[toStartRow, toStartCol]: [number, number]
): [number, number] {
const toEnd: [number, number] = [0, 0];
if (html && html.includes('')) {
const { _data } = t;
const dstyle = _data.style;
const template = document.createElement('template');
template.innerHTML = html;
const skips: Range[] = [];
const trs = template.content.querySelectorAll('tr');
toEnd[0] = toStartRow + trs.length - 1;
const borderss: Border[][] = [];
trs.forEach((tr, rowIndex) => {
const tds = tr.querySelectorAll('td');
if (rowIndex === 0) toEnd[1] = toStartCol + tds.length - 1;
// is border the same in tr
let prevBorder: Border | null = null;
const borders: Border[] = [];
for (let colIndex = 0; colIndex < tds.length; colIndex += 1) {
const td = tds[colIndex];
let [r, c] = [rowIndex + toStartRow, colIndex + toStartCol];
if (skips.length > 0) {
skips.forEach((it) => {
if (it.containsRow(r) && it.startCol <= c) {
c += it.cols;
if (it.startRow !== r) c += 1;
}
});
}
const ref = xy2expr(c, r);
// merge cell
let [rowspan, colspan] = [1, 1];
elementAttrValue(td, 'rowspan', (v) => (rowspan = parseInt(v)));
elementAttrValue(td, 'colspan', (v) => (colspan = parseInt(v)));
if (rowspan > 1 || colspan > 1) {
const range = Range.create(r, c, r + rowspan - 1, c + colspan - 1);
t.merge(range.toString());
skips.push(range);
}
if (rowIndex === 0) toEnd[1] += colspan - 1;
// style
const nstyle: Partial