Vanessa 2026-02-22 13:37:31 +08:00
parent 27c6b51e9d
commit e9f350a707
3 changed files with 71 additions and 60 deletions

View file

@ -19,7 +19,7 @@ import {
moveColumnToRight,
moveRowToDown,
moveRowToUp,
setTableAlign
setTableAlign, updateTableTitle
} from "../protyle/util/table";
import {mathRender} from "../protyle/render/mathRender";
import {transaction, updateTransaction} from "../protyle/wysiwyg/transaction";
@ -2222,64 +2222,7 @@ export const tableMenu = (protyle: IProtyle, nodeElement: Element, cellElement:
icon: "iconHeadings",
label: window.siyuan.languages.title,
click: () => {
const captionElement = nodeElement.querySelector("caption");
window.siyuan.menus.menu.remove();
const dialog = new Dialog({
title: window.siyuan.languages.table,
width: isMobile() ? "92vw" : "520px",
content: `<div class="b3-dialog__content">
<label>
<div>${window.siyuan.languages.title}</div>
<div class="fn__hr"></div>
<input class="b3-text-field fn__block">
</label>
<div class="fn__hr--b"></div>
<label>
<div>${window.siyuan.languages.position}</div>
<div class="fn__hr"></div>
<select class="b3-select fn__block">
<option value="top">${window.siyuan.languages.up}</option>
<option value="bottom" ${captionElement?.style.captionSide === "bottom" ? "selected" : ""}>${window.siyuan.languages.down}</option>
</select>
</label>
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
</div>
<div>`,
});
const html = nodeElement.outerHTML;
const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement;
const btnsElement = dialog.element.querySelectorAll(".b3-button");
dialog.bindInput(inputElement, () => {
(btnsElement[1] as HTMLButtonElement).click();
});
inputElement.focus();
inputElement.value = captionElement?.textContent || "";
btnsElement[0].addEventListener("click", () => {
dialog.destroy();
});
btnsElement[1].addEventListener("click", () => {
const title = inputElement.value.trim();
const location = (dialog.element.querySelector("select") as HTMLSelectElement).value;
if (title) {
const html = `<caption contenteditable="false" ${location === "bottom" ? 'style="caption-side: bottom;"' : ""}>${Lute.EscapeHTMLStr(title)}</caption>`;
if (captionElement) {
captionElement.outerHTML = html;
} else {
nodeElement.querySelector("table").insertAdjacentHTML("afterbegin", html);
}
nodeElement.setAttribute("caption", Lute.EscapeHTMLStr(html));
} else {
if (captionElement) {
captionElement.remove();
}
nodeElement.removeAttribute("caption");
}
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
dialog.destroy();
});
updateTableTitle(protyle, nodeElement);
}
});
otherMenus.push({id: "separator_1", type: "separator"});

View file

@ -14,6 +14,8 @@ import {insertEmptyBlock} from "../../block/util";
import {removeBlock} from "../wysiwyg/remove";
import {hasNextSibling, hasPreviousSibling} from "../wysiwyg/getBlock";
import * as dayjs from "dayjs";
import {Dialog} from "../../dialog";
import {isMobile} from "../../util/functions";
const scrollToView = (nodeElement: Element, rowElement: HTMLElement, protyle: IProtyle) => {
if (nodeElement.getAttribute("custom-pinthead") === "true") {
@ -795,3 +797,64 @@ export const clearTableCell = (protyle: IProtyle, tableBlockElement: HTMLElement
});
updateTransaction(protyle, tableBlockElement.getAttribute("data-node-id"), tableBlockElement.outerHTML, oldHTML);
};
export const updateTableTitle = (protyle: IProtyle, nodeElement: Element) => {
const captionElement = nodeElement.querySelector("caption");
window.siyuan.menus.menu.remove();
const dialog = new Dialog({
title: window.siyuan.languages.table,
width: isMobile() ? "92vw" : "520px",
content: `<div class="b3-dialog__content">
<label>
<div>${window.siyuan.languages.title}</div>
<div class="fn__hr"></div>
<input class="b3-text-field fn__block">
</label>
<div class="fn__hr--b"></div>
<label>
<div>${window.siyuan.languages.position}</div>
<div class="fn__hr"></div>
<select class="b3-select fn__block">
<option value="top">${window.siyuan.languages.up}</option>
<option value="bottom" ${captionElement?.style.captionSide === "bottom" ? "selected" : ""}>${window.siyuan.languages.down}</option>
</select>
</label>
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
</div>
<div>`,
});
const html = nodeElement.outerHTML;
const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement;
const btnsElement = dialog.element.querySelectorAll(".b3-button");
dialog.bindInput(inputElement, () => {
(btnsElement[1] as HTMLButtonElement).click();
});
inputElement.focus();
inputElement.value = captionElement?.textContent || "";
btnsElement[0].addEventListener("click", () => {
dialog.destroy();
});
btnsElement[1].addEventListener("click", () => {
const title = inputElement.value.trim();
const location = (dialog.element.querySelector("select") as HTMLSelectElement).value;
if (title) {
const html = `<caption contenteditable="false" ${location === "bottom" ? 'style="caption-side: bottom;"' : ""}>${Lute.EscapeHTMLStr(title)}</caption>`;
if (captionElement) {
captionElement.outerHTML = html;
} else {
nodeElement.querySelector("table").insertAdjacentHTML("afterbegin", html);
}
nodeElement.setAttribute("caption", Lute.EscapeHTMLStr(html));
} else {
if (captionElement) {
captionElement.remove();
}
nodeElement.removeAttribute("caption");
}
updateTransaction(protyle, nodeElement.getAttribute("data-node-id"), nodeElement.outerHTML, html);
dialog.destroy();
});
};

View file

@ -70,7 +70,7 @@ import {copyPlainText, encodeBase64, isInIOS, isMac, isOnlyMeta, readClipboard}
import {MenuItem} from "../../menus/Menu";
import {fetchPost, fetchSyncPost} from "../../util/fetch";
import {onGet} from "../util/onGet";
import {clearTableCell, isIncludeCell, setTableAlign} from "../util/table";
import {clearTableCell, isIncludeCell, setTableAlign, updateTableTitle} from "../util/table";
import {countBlockWord, countSelectWord} from "../../layout/status";
import {showMessage} from "../../dialog/message";
import {getBacklinkHeadingMore, loadBreadcrumb} from "./renderBacklink";
@ -2663,6 +2663,11 @@ export class WYSIWYG {
event.stopPropagation();
}
});
if (tableElement) {
if (hasClosestByTag(event.target, "CAPTION")) {
updateTableTitle(protyle, tableElement);
}
}
// 面包屑定位,需至于前,否则 return 的元素就无法进行面包屑定位
if (protyle.options.render.breadcrumb) {
protyle.breadcrumb.render(protyle, false, hasClosestBlock(event.target));