🎨 The embed block of a heading supports hiding the heading itself

This commit is contained in:
Achuan-2 2025-09-25 16:54:01 +08:00 committed by GitHub
parent a6e4baee99
commit ee5eb01c52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 208 additions and 45 deletions

View file

@ -69,6 +69,18 @@ export const editor = {
<span class="fn__space"></span>
<input class="b3-switch fn__flex-center" id="embedBlockBreadcrumb" type="checkbox"${window.siyuan.config.editor.embedBlockBreadcrumb ? " checked" : ""}/>
</label>
<div class="fn__flex b3-label config__item">
<div class="fn__flex-1">
${window.siyuan.languages.headingEmbedMode}
<div class="b3-label__text">${window.siyuan.languages.headingEmbedModeTip}</div>
</div>
<span class="fn__space"></span>
<select class="b3-select fn__flex-center fn__size200" id="headingEmbedMode">
<option value="0" ${window.siyuan.config.editor.headingEmbedMode === 0 ? "selected" : ""}>${window.siyuan.languages.showHeadingWithBlocks}</option>
<option value="1" ${window.siyuan.config.editor.headingEmbedMode === 1 ? "selected" : ""}>${window.siyuan.languages.showHeadingOnlyTitle}</option>
<option value="2" ${window.siyuan.config.editor.headingEmbedMode === 2 ? "selected" : ""}>${window.siyuan.languages.showHeadingOnlyBlocks}</option>
</select>
</div>
<label class="fn__flex b3-label">
<div class="fn__flex-1">
${window.siyuan.languages.outlineOutdent}
@ -428,6 +440,7 @@ export const editor = {
displayNetImgMark: (editor.element.querySelector("#displayNetImgMark") as HTMLInputElement).checked,
codeSyntaxHighlightLineNum: (editor.element.querySelector("#codeSyntaxHighlightLineNum") as HTMLInputElement).checked,
embedBlockBreadcrumb: (editor.element.querySelector("#embedBlockBreadcrumb") as HTMLInputElement).checked,
headingEmbedMode: parseInt((editor.element.querySelector("#headingEmbedMode") as HTMLSelectElement).value),
listLogicalOutdent: (editor.element.querySelector("#listLogicalOutdent") as HTMLInputElement).checked,
listItemDotNumberClickFocus: (editor.element.querySelector("#listItemDotNumberClickFocus") as HTMLInputElement).checked,
spellcheck: (editor.element.querySelector("#spellcheck") as HTMLInputElement).checked,

View file

@ -33,6 +33,7 @@ const setEditor = (modelMainElement: Element) => {
window.siyuan.config.editor.displayNetImgMark = (modelMainElement.querySelector("#displayNetImgMark") as HTMLInputElement).checked;
window.siyuan.config.editor.codeSyntaxHighlightLineNum = (modelMainElement.querySelector("#codeSyntaxHighlightLineNum") as HTMLInputElement).checked;
window.siyuan.config.editor.embedBlockBreadcrumb = (modelMainElement.querySelector("#embedBlockBreadcrumb") as HTMLInputElement).checked;
window.siyuan.config.editor.headingEmbedMode = parseInt((modelMainElement.querySelector("#headingEmbedMode") as HTMLSelectElement).value);
window.siyuan.config.editor.listLogicalOutdent = (modelMainElement.querySelector("#listLogicalOutdent") as HTMLInputElement).checked;
window.siyuan.config.editor.listItemDotNumberClickFocus = (modelMainElement.querySelector("#listItemDotNumberClickFocus") as HTMLInputElement).checked;
window.siyuan.config.editor.spellcheck = (modelMainElement.querySelector("#spellcheck") as HTMLInputElement).checked;
@ -115,6 +116,16 @@ export const initEditor = () => {
<span class="fn__space"></span>
<input class="b3-switch fn__flex-center" id="embedBlockBreadcrumb" type="checkbox"${window.siyuan.config.editor.embedBlockBreadcrumb ? " checked" : ""}/>
</label>
<div class="b3-label">
${window.siyuan.languages.headingEmbedMode}
<span class="fn__hr"></span>
<select class="b3-select fn__block" id="headingEmbedMode">
<option value="0" ${window.siyuan.config.editor.headingEmbedMode === 0 ? "selected" : ""}>${window.siyuan.languages.showHeadingWithBlocks}</option>
<option value="1" ${window.siyuan.config.editor.headingEmbedMode === 1 ? "selected" : ""}>${window.siyuan.languages.showHeadingOnlyTitle}</option>
<option value="2" ${window.siyuan.config.editor.headingEmbedMode === 2 ? "selected" : ""}>${window.siyuan.languages.showHeadingOnlyBlocks}</option>
</select>
<div class="b3-label__text">${window.siyuan.languages.headingEmbedModeTip}</div>
</div>
<label class="fn__flex b3-label">
<div class="fn__flex-1">
${window.siyuan.languages.outlineOutdent}

View file

@ -1628,20 +1628,35 @@ export class Gutter {
});
}
}, {
id: "hideHeadingBelowBlocks",
label: `<div class="fn__flex" style="margin-bottom: 4px"><span>${window.siyuan.languages.hideHeadingBelowBlocks}</span><span class="fn__space fn__flex-1"></span>
<input type="checkbox" class="b3-switch fn__flex-center"${nodeElement.getAttribute("custom-heading-mode") === "1" ? " checked" : ""}></div>`,
id: "headingEmbedMode",
label: `<div class="fn__flex" style="margin-bottom: 4px">
<span>${window.siyuan.languages.headingEmbedMode}</span>
<span class="fn__space fn__flex-1"></span>
<select class="b3-select fn__flex-center" style="margin-left: 8px;">
<option value="0"${nodeElement.getAttribute("custom-heading-mode") === "0" ? " selected" : ""}>${window.siyuan.languages.showHeadingWithBlocks}</option>
<option value="1"${nodeElement.getAttribute("custom-heading-mode") === "1" ? " selected" : ""}>${window.siyuan.languages.showHeadingOnlyTitle}</option>
<option value="2"${nodeElement.getAttribute("custom-heading-mode") === "2" ? " selected" : ""}>${window.siyuan.languages.showHeadingOnlyBlocks}</option>
<option value=""${!nodeElement.getAttribute("custom-heading-mode") ? " selected" : ""}>${window.siyuan.languages.default}</option>
</select>
</div>`,
bind(element) {
element.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
const inputElement = element.querySelector("input");
if (event.target.tagName !== "INPUT") {
inputElement.checked = !inputElement.checked;
element.addEventListener("change", () => {
const selectElement = element.querySelector("select") as HTMLSelectElement;
const value = selectElement.value;
if (value === "") {
// 默认设置,清空 custom-heading-mode 属性
nodeElement.removeAttribute("custom-heading-mode");
fetchPost("/api/attr/setBlockAttrs", {
id,
attrs: {"custom-heading-mode": ""}
});
} else {
nodeElement.setAttribute("custom-heading-mode", value);
fetchPost("/api/attr/setBlockAttrs", {
id,
attrs: {"custom-heading-mode": value}
});
}
nodeElement.setAttribute("custom-heading-mode", inputElement.checked ? "1" : "0");
fetchPost("/api/attr/setBlockAttrs", {
id,
attrs: {"custom-heading-mode": inputElement.checked ? "1" : "0"}
});
nodeElement.removeAttribute("data-render");
blockRender(protyle, nodeElement);
window.siyuan.menus.menu.remove();

View file

@ -59,7 +59,7 @@ export const blockRender = (protyle: IProtyle, element: Element, top?: number) =
fetchPost("/api/search/getEmbedBlock", {
embedBlockID: item.getAttribute("data-node-id"),
includeIDs: promiseIds,
headingMode: item.getAttribute("custom-heading-mode") === "1" ? 1 : 0,
headingMode: ["0", "1", "2"].includes(item.getAttribute("custom-heading-mode")) ? parseInt(item.getAttribute("custom-heading-mode")) : window.siyuan.config.editor.headingEmbedMode,
breadcrumb
}, (response) => {
renderEmbed(response.data.blocks || [], protyle, item, top);
@ -74,7 +74,7 @@ export const blockRender = (protyle: IProtyle, element: Element, top?: number) =
fetchPost("/api/search/getEmbedBlock", {
embedBlockID: item.getAttribute("data-node-id"),
includeIDs,
headingMode: item.getAttribute("custom-heading-mode") === "1" ? 1 : 0,
headingMode: ["0", "1", "2"].includes(item.getAttribute("custom-heading-mode")) ? parseInt(item.getAttribute("custom-heading-mode")) : window.siyuan.config.editor.headingEmbedMode,
breadcrumb
}, (response) => {
renderEmbed(response.data.blocks || [], protyle, item, top);
@ -89,7 +89,7 @@ export const blockRender = (protyle: IProtyle, element: Element, top?: number) =
fetchPost("/api/search/searchEmbedBlock", {
embedBlockID: item.getAttribute("data-node-id"),
stmt: content,
headingMode: item.getAttribute("custom-heading-mode") === "1" ? 1 : 0,
headingMode: ["0", "1", "2"].includes(item.getAttribute("custom-heading-mode")) ? parseInt(item.getAttribute("custom-heading-mode")) : window.siyuan.config.editor.headingEmbedMode,
excludeIDs: [item.getAttribute("data-node-id"), protyle.block.rootID],
breadcrumb
}, (response) => {

View file

@ -399,6 +399,13 @@ declare namespace Config {
* Whether the embedded block displays breadcrumbs
*/
embedBlockBreadcrumb: boolean;
/**
* Heading embed mode for embedded blocks
* - `0`: Show title with blocks below (default)
* - `1`: Show only title
* - `2`: Show only blocks below title
*/
headingEmbedMode: number;
/**
* Common emoji icons
*/