chore: update version to 1.1.0 in manifest, package.json, and package-lock.json; refactor table rendering logic to improve column header functionality

This commit is contained in:
JayBridge 2025-06-30 11:26:39 +08:00
parent a1676d20f6
commit b8c675228d
4 changed files with 106 additions and 139 deletions

View file

@ -1,7 +1,7 @@
{
"id": "csv-lite",
"name": "CSV Lite",
"version": "1.0.6",
"version": "1.1.0",
"minAppVersion": "1.8.0",
"description": "Just open and edit CSV files directly, no more. Keep it simple.",
"author": "Jay Bridge",

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "obsidian-csv",
"version": "1.0.6",
"version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "obsidian-csv",
"version": "1.0.6",
"version": "1.1.0",
"description": "CSV viewer and editor for Obsidian",
"main": "main.js",
"scripts": {

View file

@ -74,18 +74,117 @@ export function renderTable(options: TableRenderOptions) {
if (type === 'col') tableEl.classList.add('csv-dragging-col');
}
// 创建表头行(包含列号)
const headerRow = tableEl.createEl("thead").createEl("tr");
// 计算初始列宽(如果未设置)
if (columnWidths.length === 0 && tableData[0]) {
const widths = TableUtils.calculateColumnWidths(tableData);
columnWidths.splice(0, columnWidths.length, ...widths);
}
// 创建表格主体 - 所有行都作为普通数据行处理
const tableBody = tableEl.createEl("tbody");
// 从索引0开始包括第一行
for (let i = 0; i < tableData.length; i++) {
const row = tableData[i];
const tableRow = tableBody.createEl("tr");
const rowNumberCell = tableRow.createEl("td", { cls: "csv-row-number", attr: { draggable: "true" } });
rowNumberCell.textContent = i.toString();
rowNumberCell.onclick = (e) => {
e.stopPropagation();
selectRow(i);
};
// 拖拽排序事件
rowNumberCell.ondragstart = (e) => {
e.dataTransfer?.setData("text/row-index", String(i));
rowNumberCell.classList.add("dragging");
setDragState('row', i);
if (typeof requestSave === 'function') requestSave();
};
rowNumberCell.ondragend = () => {
rowNumberCell.classList.remove("dragging");
setDragState(null, null);
if (typeof requestSave === 'function') requestSave();
};
rowNumberCell.ondragover = (e) => {
e.preventDefault();
rowNumberCell.classList.add("drag-over");
};
rowNumberCell.ondragleave = () => {
rowNumberCell.classList.remove("drag-over");
};
rowNumberCell.ondrop = (e) => {
e.preventDefault();
rowNumberCell.classList.remove("drag-over");
setDragState(null, null);
const from = Number(e.dataTransfer?.getData("text/row-index"));
const to = i;
if (onRowReorder && from !== to) {
onRowReorder(from, to);
}
};
// 插入行操作按钮(拖拽时隐藏)
if (!(dragState.type === 'row')) {
const insertAbove = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn above" });
insertAbove.innerText = "+";
insertAbove.title = i18n.t("buttons.insertRowBefore") || "Insert row before";
insertAbove.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, false); };
const insertBelow = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn below" });
insertBelow.innerText = "+";
insertBelow.title = i18n.t("buttons.insertRowAfter") || "Insert row after";
insertBelow.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, true); };
const delRow = rowNumberCell.createEl("button", { cls: "csv-del-row-btn" });
delRow.innerText = "-";
delRow.title = i18n.t("buttons.deleteRow") || "Delete row";
delRow.onclick = (e) => { e.stopPropagation(); options.deleteRowAt(i); };
}
// 拖拽高亮整行及相邻行
if (dragState.type === 'row' && dragState.index !== null) {
const rowStart = Math.max(0, dragState.index - 2);
const rowEnd = Math.min(tableData.length - 1, dragState.index + 2);
if (i >= rowStart && i <= rowEnd) {
rowNumberCell.classList.add('csv-dragging-highlight');
Array.from(tableRow.children).forEach(td => {
(td as HTMLElement).classList.add('csv-dragging-highlight');
});
}
}
row.forEach((cell, j) => {
const td = tableRow.createEl("td", {
attr: { style: `width: ${columnWidths[j] || 100}px` },
});
const input = td.createEl("input", {
cls: "csv-cell-input",
attr: { value: cell },
});
setupAutoResize(input);
input.oninput = (ev) => {
if (ev.currentTarget instanceof HTMLInputElement) {
saveSnapshot();
tableData[i][j] = ev.currentTarget.value;
if (activeCellEl === ev.currentTarget && editInput) {
editInput.value = ev.currentTarget.value;
}
// 新增:表格单元格编辑时同步编辑栏
if (renderEditBar) {
renderEditBar(i, j, ev.currentTarget);
}
requestSave();
if (autoResize) {
adjustInputHeight(ev.currentTarget);
}
}
};
input.onfocus = (ev) => {
setActiveCell(i, j, ev.currentTarget as HTMLInputElement);
};
});
}
// 创建列号行(在表格顶部)
const headerRow = tableEl.createEl("thead").createEl("tr");
// 添加左上角单元格
const cornerTh = headerRow.createEl("th", { cls: "csv-corner-cell" });
// 可选:在左上角添加插入列/行按钮
// 创建列号行
if (tableData[0]) {
@ -161,138 +260,6 @@ export function renderTable(options: TableRenderOptions) {
});
}
// 创建表头数据行
const dataHeaderRow = tableEl.createEl("thead").createEl("tr");
const headerRowNumber = dataHeaderRow.createEl("th", { cls: "csv-row-number" });
headerRowNumber.textContent = "0";
if (tableData[0]) {
tableData[0].forEach((headerCell, index) => {
const th = dataHeaderRow.createEl("th", {
cls: "csv-th",
attr: {
style: `width: ${columnWidths[index] || 100}px`,
},
});
const headerInput = th.createEl("input", {
cls: "csv-cell-input",
attr: { value: headerCell },
});
headerInput.oninput = (ev) => {
if (ev.currentTarget instanceof HTMLInputElement) {
saveSnapshot();
tableData[0][index] = ev.currentTarget.value;
requestSave();
}
};
headerInput.onfocus = (ev) => {
setActiveCell(0, index, ev.currentTarget as HTMLInputElement);
};
// 在列号单元格中添加拖拽事件处理逻辑
const resizeHandle = th.createEl("div", { cls: "resize-handle" });
setupColumnResize(resizeHandle, index);
});
}
// 创建表格主体
const tableBody = tableEl.createEl("tbody");
const startRowIndex = tableData.length > 1 ? 1 : 0;
for (let i = startRowIndex; i < tableData.length; i++) {
const row = tableData[i];
const tableRow = tableBody.createEl("tr");
const rowNumberCell = tableRow.createEl("td", { cls: "csv-row-number", attr: { draggable: "true" } });
rowNumberCell.textContent = i.toString();
rowNumberCell.onclick = (e) => {
e.stopPropagation();
selectRow(i);
};
// 拖拽排序事件
rowNumberCell.ondragstart = (e) => {
e.dataTransfer?.setData("text/row-index", String(i));
rowNumberCell.classList.add("dragging");
setDragState('row', i);
if (typeof requestSave === 'function') requestSave();
};
rowNumberCell.ondragend = () => {
rowNumberCell.classList.remove("dragging");
setDragState(null, null);
if (typeof requestSave === 'function') requestSave();
};
rowNumberCell.ondragover = (e) => {
e.preventDefault();
rowNumberCell.classList.add("drag-over");
};
rowNumberCell.ondragleave = () => {
rowNumberCell.classList.remove("drag-over");
};
rowNumberCell.ondrop = (e) => {
e.preventDefault();
rowNumberCell.classList.remove("drag-over");
setDragState(null, null);
const from = Number(e.dataTransfer?.getData("text/row-index"));
const to = i;
if (onRowReorder && from !== to) {
onRowReorder(from, to);
}
};
// 插入行操作按钮(拖拽时隐藏)
if (!(dragState.type === 'row')) {
const insertAbove = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn above" });
insertAbove.innerText = "+";
insertAbove.title = i18n.t("buttons.insertRowBefore") || "Insert row before";
insertAbove.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, false); };
const insertBelow = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn below" });
insertBelow.innerText = "+";
insertBelow.title = i18n.t("buttons.insertRowAfter") || "Insert row after";
insertBelow.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, true); };
const delRow = rowNumberCell.createEl("button", { cls: "csv-del-row-btn" });
delRow.innerText = "-";
delRow.title = i18n.t("buttons.deleteRow") || "Delete row";
delRow.onclick = (e) => { e.stopPropagation(); options.deleteRowAt(i); };
}
// 拖拽高亮整行及相邻行
if (dragState.type === 'row' && dragState.index !== null) {
const rowStart = Math.max(startRowIndex, dragState.index - 2);
const rowEnd = Math.min(tableData.length - 1, dragState.index + 2);
if (i >= rowStart && i <= rowEnd) {
rowNumberCell.classList.add('csv-dragging-highlight');
Array.from(tableRow.children).forEach(td => {
(td as HTMLElement).classList.add('csv-dragging-highlight');
});
}
}
row.forEach((cell, j) => {
const td = tableRow.createEl("td", {
attr: { style: `width: ${columnWidths[j] || 100}px` },
});
const input = td.createEl("input", {
cls: "csv-cell-input",
attr: { value: cell },
});
setupAutoResize(input);
input.oninput = (ev) => {
if (ev.currentTarget instanceof HTMLInputElement) {
saveSnapshot();
tableData[i][j] = ev.currentTarget.value;
if (activeCellEl === ev.currentTarget && editInput) {
editInput.value = ev.currentTarget.value;
}
// 新增:表格单元格编辑时同步编辑栏
if (renderEditBar) {
renderEditBar(i, j, ev.currentTarget);
}
requestSave();
if (autoResize) {
adjustInputHeight(ev.currentTarget);
}
}
};
input.onfocus = (ev) => {
setActiveCell(i, j, ev.currentTarget as HTMLInputElement);
};
});
}
// 滚动条容器宽度同步逻辑建议由主类处理
// Add event listener to deselect active row or column when clicking outside