Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2025-09-25 20:22:04 +08:00
commit 15d651713c
26 changed files with 246 additions and 130 deletions

View file

@ -674,7 +674,11 @@
"turnToDynamic": "نص المرساة الديناميكي",
"sizeLimit": "الحد الأقصى",
"trafficStat": "إحصاءات حركة المرور",
"hideHeadingBelowBlocks": "إخفاء الكتل تحت العنوان",
"headingEmbedMode": "إعدادات تضمين كتلة العنوان",
"headingEmbedModeTip": "تعيين نمط عرض كتلة العنوان في الكتلة المضمنة",
"showHeadingWithBlocks": "إظهار العنوان مع الكتل أدناه",
"showHeadingOnlyTitle": "إظهار العنوان فقط",
"showHeadingOnlyBlocks": "إظهار الكتل تحت العنوان فقط",
"matchDiacritics": "مطابقة علامات التشكيل",
"copyHPath": "نسخ المسار المقروء",
"justify": "محاذاة من الجانبين",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Dynamischer Ankertext",
"sizeLimit": "Limit",
"trafficStat": "Verkehrsstatistiken",
"hideHeadingBelowBlocks": "Blöcke unter der Überschrift ausblenden",
"headingEmbedMode": "Überschrift-Block-Einbettungseinstellungen",
"headingEmbedModeTip": "Stellen Sie den Anzeigestil von Überschrift-Blöcken in eingebetteten Blöcken ein",
"showHeadingWithBlocks": "Überschrift mit Blöcken darunter anzeigen",
"showHeadingOnlyTitle": "Nur Überschrift anzeigen",
"showHeadingOnlyBlocks": "Nur Blöcke unter der Überschrift anzeigen",
"matchDiacritics": "Diakritika abgleichen",
"copyHPath": "Lesbaren Pfad kopieren",
"justify": "Rechtsfertigen",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Dynamic anchor text",
"sizeLimit": "Limit",
"trafficStat": "Traffic statistics",
"hideHeadingBelowBlocks": "Hide blocks below heading",
"headingEmbedMode": "Heading block embed settings",
"showHeadingWithBlocks": "Show heading with blocks below",
"showHeadingOnlyTitle": "Show heading only",
"showHeadingOnlyBlocks": "Show only blocks below heading",
"headingEmbedModeTip": "Set the display style of heading blocks in embed blocks",
"matchDiacritics": "Match Diacritics",
"copyHPath": "Copy readable path",
"justify": "Justify",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Texto de anclaje dinámico",
"sizeLimit": "Límite",
"trafficStat": "Estadísticas de tráfico",
"hideHeadingBelowBlocks": "Ocultar bloques por debajo del encabezamiento",
"headingEmbedMode": "Configuración de incrustación de bloque de encabezado",
"headingEmbedModeTip": "Establecer el estilo de visualización de los bloques de encabezado en los bloques incrustados",
"showHeadingWithBlocks": "Mostrar encabezado con bloques debajo",
"showHeadingOnlyTitle": "Mostrar solo el encabezado",
"showHeadingOnlyBlocks": "Mostrar solo bloques debajo del encabezado",
"matchDiacritics": " Hacer coincidir los diacríticos",
"copyHPath": "Copiar ruta legible",
"justify": "Justificar",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Texte d'ancrage dynamique",
"sizeLimit": "Limite",
"trafficStat": "Statistiques de trafic",
"hideHeadingBelowBlocks": "Masquer les blocs sous l'en-tête",
"headingEmbedMode": "Paramètres d'intégration de bloc de titre",
"showHeadingWithBlocks": "Afficher l'en-tête avec les blocs en dessous",
"showHeadingOnlyTitle": "Afficher uniquement l'en-tête",
"showHeadingOnlyBlocks": "Afficher uniquement les blocs sous l'en-tête",
"headingEmbedModeTip": "Définir le style d'affichage des blocs de titre dans les blocs intégrés",
"matchDiacritics": "Respecter les accents et diacritiques",
"copyHPath": "Copier le chemin lisible",
"justify": "Justifier",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "טקסט עוגן דינמי",
"sizeLimit": "מגבלה",
"trafficStat": "סטטיסטיקות תעבורה",
"hideHeadingBelowBlocks": "החבא בלוקים מתחת לכותרת",
"headingEmbedMode": "הגדרות הטמעת בלוק כותרת",
"headingEmbedModeTip": "הגדר את סגנון התצוגה של בלוקי כותרת בבלוקים מוטמעים",
"showHeadingWithBlocks": "הצג כותרת עם בלוקים מתחתיה",
"showHeadingOnlyTitle": "הצג כותרת בלבד",
"showHeadingOnlyBlocks": "הצג רק בלוקים מתחת לכותרת",
"matchDiacritics": "התאם טעמים",
"copyHPath": "העתק נתיב קריא",
"justify": "התאם",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Testo ancora dinamico",
"sizeLimit": "Limite",
"trafficStat": "Statistiche traffico",
"hideHeadingBelowBlocks": "Nascondi blocchi sotto l'intestazione",
"headingEmbedMode": "Impostazioni incorporamento blocco intestazione",
"headingEmbedModeTip": "Imposta lo stile di visualizzazione dei blocchi di intestazione nei blocchi incorporati",
"showHeadingWithBlocks": "Mostra intestazione con blocchi sottostanti",
"showHeadingOnlyTitle": "Mostra solo intestazione",
"showHeadingOnlyBlocks": "Mostra solo blocchi sotto l'intestazione",
"matchDiacritics": "Corrispondenza con diacritici",
"copyHPath": "Copia percorso leggibile",
"justify": "Giustifica",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "動的アンカーテキスト",
"sizeLimit": "制限",
"trafficStat": "トラフィック統計",
"hideHeadingBelowBlocks": "見出し以下のブロックを非表示にする",
"headingEmbedMode": "見出しブロック埋め込み設定",
"headingEmbedModeTip": "見出しブロックの埋め込みブロック内での表示スタイルを設定",
"showHeadingWithBlocks": "見出しと下のブロックを表示",
"showHeadingOnlyTitle": "見出しのみ表示",
"showHeadingOnlyBlocks": "見出し下のブロックのみ表示",
"matchDiacritics": "ダイアクリティカルマークを一致させる",
"copyHPath": "パスをコピー",
"justify": "両端揃え",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Dynamiczny tekst zakotwiczenia",
"sizeLimit": "Limit",
"trafficStat": "Statystyki ruchu",
"hideHeadingBelowBlocks": "Ukryj bloki poniżej nagłówka",
"headingEmbedMode": "Ustawienia osadzania bloku nagłówka",
"headingEmbedModeTip": "Ustaw styl wyświetlania bloków nagłówkowych w blokach osadzonych",
"showHeadingWithBlocks": "Pokaż nagłówek z blokami poniżej",
"showHeadingOnlyTitle": "Pokaż tylko nagłówek",
"showHeadingOnlyBlocks": "Pokaż tylko bloki poniżej nagłówka",
"matchDiacritics": "Dopasuj diakrytyki",
"copyHPath": "Kopiuj czytelną ścieżkę",
"justify": "Wyrównanie",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Texto âncora dinâmico",
"sizeLimit": "Limite",
"trafficStat": "Estatísticas de tráfego",
"hideHeadingBelowBlocks": "Ocultar blocos abaixo do título",
"headingEmbedMode": "Configurações de incorporação de bloco de cabeçalho",
"headingEmbedModeTip": "Definir o estilo de exibição dos blocos de cabeçalho nos blocos incorporados",
"showHeadingWithBlocks": "Mostrar título com blocos abaixo",
"showHeadingOnlyTitle": "Mostrar apenas o título",
"showHeadingOnlyBlocks": "Mostrar apenas blocos abaixo do título",
"matchDiacritics": "Corresponder Diacríticos",
"copyHPath": "Copiar caminho legível",
"justify": "Justificar",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "Динамический анкорный текст",
"sizeLimit": "Лимит",
"trafficStat": "Статистика трафика",
"hideHeadingBelowBlocks": "Скрыть блоки ниже заголовка",
"headingEmbedMode": "Настройки встраивания блока заголовка",
"headingEmbedModeTip": "Установить стиль отображения блока заголовка во встроенном блоке",
"showHeadingWithBlocks": "Показать заголовок с блоками ниже",
"showHeadingOnlyTitle": "Показать только заголовок",
"showHeadingOnlyBlocks": "Показать только блоки ниже заголовка",
"matchDiacritics": "Совпадение диакритики",
"copyHPath": "Скопировать читаемый путь",
"justify": "Выровнять",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "動態錨文字",
"sizeLimit": "上限",
"trafficStat": "流量統計",
"hideHeadingBelowBlocks": "隱藏標題下方的塊",
"headingEmbedMode": "標題塊嵌入設定",
"headingEmbedModeTip": "設定標題塊在嵌入塊中的顯示樣式",
"showHeadingWithBlocks": "顯示標題與下方的塊",
"showHeadingOnlyTitle": "僅顯示標題",
"showHeadingOnlyBlocks": "僅顯示標題下方的塊",
"matchDiacritics": "符合變音符號",
"copyHPath": "複製可讀路徑",
"justify": "兩側對齊",
@ -1288,8 +1292,8 @@
"indent": "列表縮進",
"info": "關於",
"inline-code": "行內代碼",
"insert-after": "下方插入塊",
"insert-before": "上方插入塊",
"insert-after": "下方插入塊",
"insert-before": "上方插入塊",
"insertColumnLeft": "在左邊插入一行",
"insertColumnRight": "在右邊插入一行",
"insertRowAbove": "在上方插入一列",

View file

@ -674,7 +674,11 @@
"turnToDynamic": "动态锚文本",
"sizeLimit": "上限",
"trafficStat": "流量统计",
"hideHeadingBelowBlocks": "隐藏标题下方的块",
"headingEmbedMode": "标题块嵌入设置",
"showHeadingWithBlocks": "显示标题与下方的块",
"showHeadingOnlyTitle": "仅显示标题",
"showHeadingOnlyBlocks": "仅显示标题下方的块",
"headingEmbedModeTip": "设置标题块在嵌入块中的显示样式",
"matchDiacritics": "匹配变音符号",
"copyHPath": "复制可读路径",
"justify": "两侧对齐",

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

@ -1627,20 +1627,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
*/

File diff suppressed because one or more lines are too long

View file

@ -251,7 +251,7 @@ func getEmbedBlock(c *gin.Context) {
for _, includeID := range includeIDsArg {
includeIDs = append(includeIDs, includeID.(string))
}
headingMode := 0 // 0带标题下方
headingMode := 0 // 0显示标题与下方的块1仅显示标题2仅显示标题下方的
headingModeArg := arg["headingMode"]
if nil != headingModeArg {
headingMode = int(headingModeArg.(float64))
@ -304,7 +304,7 @@ func searchEmbedBlock(c *gin.Context) {
for _, excludeID := range excludeIDsArg {
excludeIDs = append(excludeIDs, excludeID.(string))
}
headingMode := 0 // 0带标题下方
headingMode := 0 // 0显示标题与下方的块1仅显示标题2仅显示标题下方的
headingModeArg := arg["headingMode"]
if nil != headingModeArg {
headingMode = int(headingModeArg.(float64))

View file

@ -52,6 +52,7 @@ type Editor struct {
BacklinkExpandCount int `json:"backlinkExpandCount"` // 反向链接默认展开数量
BackmentionExpandCount int `json:"backmentionExpandCount"` // 反链提及默认展开数量
BacklinkContainChildren bool `json:"backlinkContainChildren"` // 反向链接是否包含子块进行计算
HeadingEmbedMode int `json:"headingEmbedMode"` // 标题嵌入块模式0显示标题与下方的块1仅显示标题2仅显示标题下方的块
Markdown *util.Markdown `json:"markdown"` // Markdown 配置
}
@ -88,6 +89,7 @@ func NewEditor() *Editor {
BacklinkExpandCount: 8,
BackmentionExpandCount: -1,
BacklinkContainChildren: true,
HeadingEmbedMode: 0,
Markdown: util.MarkdownSettings,
}
}

View file

@ -8,7 +8,7 @@ require (
github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48
github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7
github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689
github.com/88250/lute v1.7.7-0.20250923083503-869fd6b9556d
github.com/88250/lute v1.7.7-0.20250925120349-484d09ce03de
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4
github.com/ConradIrwin/font v0.2.1

View file

@ -14,8 +14,8 @@ github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950 h1:Pa5hMiBceT
github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689 h1:39y5g7vnFAIcXhTN3IXPk7h2xBhC4a9hBTykDhHJqRY=
github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689/go.mod h1:c8uVw25vW2W4dhJ/j4iYsX5H1hc19spim266jO5x2hU=
github.com/88250/lute v1.7.7-0.20250923083503-869fd6b9556d h1:R46nlSVY8WMHh2MZQiFGpN48jS2uV8Fm47d1tNS+NAo=
github.com/88250/lute v1.7.7-0.20250923083503-869fd6b9556d/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o=
github.com/88250/lute v1.7.7-0.20250925120349-484d09ce03de h1:7Wk2GiRu5IO/KcZEARlgR3c6ja1T+FugO55xCkaa3io=
github.com/88250/lute v1.7.7-0.20250925120349-484d09ce03de/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o=
github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46 h1:Bq1JsDfVbHKUxNL/B2JXd8cC/1h6aFjrlXpGycnh0Hk=
github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI=
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=

View file

@ -196,103 +196,56 @@ func GetBlockSiblingID(id string) (parent, previous, next string) {
return
}
node := treenode.GetNodeInTree(tree, id)
if nil == node {
current := treenode.GetNodeInTree(tree, id)
if nil == current || !current.IsBlock() {
return
}
parentBlock := treenode.ParentBlock(current)
if nil == parentBlock {
return
}
if !node.IsBlock() {
return
parent = parentBlock.ID
if flb := treenode.FirstChildBlock(parentBlock); nil != flb {
parent = flb.ID
}
parentListCount := 0
var parentListItem, current *ast.Node
for p := node.Parent; nil != p; p = p.Parent {
if ast.NodeListItem == p.Type {
parentListCount++
if 1 < parentListCount {
parentListItem = p
break
}
current = p.Parent
}
}
if ast.NodeDocument == parentBlock.Type {
parent = parentBlock.ID
if nil != parentListItem {
parent = parentListItem.ID
if parentListItem.Previous != nil {
previous = parentListItem.Previous.ID
if flb := treenode.FirstChildBlock(parentListItem.Previous); nil != flb {
if nil != current.Previous && current.Previous.IsBlock() {
previous = current.Previous.ID
if flb := treenode.FirstChildBlock(current.Previous); nil != flb {
previous = flb.ID
}
}
if parentListItem.Next != nil {
next = parentListItem.Next.ID
if flb := treenode.FirstChildBlock(parentListItem.Next); nil != flb {
if nil != current.Next && current.Next.IsBlock() {
next = current.Next.ID
if flb := treenode.FirstChildBlock(current.Next); nil != flb {
next = flb.ID
}
}
if "" == previous && "" == next && nil != current {
parent = current.ID
if nil != current.Previous {
previous = current.Previous.ID
if flb := treenode.FirstChildBlock(current.Previous); nil != flb {
previous = flb.ID
}
}
if nil != current.Next {
next = current.Next.ID
if flb := treenode.FirstChildBlock(current.Next); nil != flb {
next = flb.ID
}
}
}
return
}
if nil == current {
current = node
}
if nil != current.Parent && current.Parent.IsBlock() {
parent = current.Parent.ID
if flb := treenode.FirstChildBlock(current.Parent); nil != flb {
parent = flb.ID
for ; nil != parentBlock; parentBlock = treenode.ParentBlock(parentBlock) {
if nil != parentBlock.Previous && parentBlock.Previous.IsBlock() {
previous = parentBlock.Previous.ID
if flb := treenode.FirstChildBlock(parentBlock.Previous); nil != flb {
previous = flb.ID
}
break
}
if ast.NodeDocument == current.Parent.Type {
parent = current.Parent.ID
if nil != current.Previous && current.Previous.IsBlock() {
previous = current.Previous.ID
if flb := treenode.FirstChildBlock(current.Previous); nil != flb {
previous = flb.ID
}
}
if nil != current.Next && current.Next.IsBlock() {
next = current.Next.ID
if flb := treenode.FirstChildBlock(current.Next); nil != flb {
next = flb.ID
}
}
} else {
if nil != current.Parent.Previous && current.Parent.Previous.IsBlock() {
previous = current.Parent.Previous.ID
if flb := treenode.FirstChildBlock(current.Parent.Previous); nil != flb {
previous = flb.ID
}
}
if nil != current.Parent.Next && current.Parent.Next.IsBlock() {
next = current.Parent.Next.ID
if flb := treenode.FirstChildBlock(current.Parent.Next); nil != flb {
next = flb.ID
}
}
parentBlock = treenode.ParentBlock(current)
for ; nil != parentBlock; parentBlock = treenode.ParentBlock(parentBlock) {
if nil != parentBlock.Next && parentBlock.Next.IsBlock() {
next = parentBlock.Next.ID
if flb := treenode.FirstChildBlock(parentBlock.Next); nil != flb {
next = flb.ID
}
break
}
}
return
@ -1058,16 +1011,40 @@ func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, heading
for _, n := range unlinks {
n.Unlink()
}
nodes = append(nodes, def)
if 0 == headingMode && ast.NodeHeading == def.Type && "1" != def.IALAttr("fold") {
children := treenode.HeadingChildren(def)
for _, c := range children {
if "1" == c.IALAttr("heading-fold") {
// 嵌入块包含折叠标题时不应该显示其下方块 https://github.com/siyuan-note/siyuan/issues/4765
continue
// headingMode: 0=显示标题与下方的块1=仅显示标题2=仅显示标题下方的块
if ast.NodeHeading == def.Type {
if 1 == headingMode {
// 仅显示标题
nodes = append(nodes, def)
} else if 2 == headingMode {
// 仅显示标题下方的块(去除标题)
if "1" != def.IALAttr("fold") {
children := treenode.HeadingChildren(def)
for _, c := range children {
if "1" == c.IALAttr("heading-fold") {
// 嵌入块包含折叠标题时不应该显示其下方块 https://github.com/siyuan-note/siyuan/issues/4765
continue
}
nodes = append(nodes, c)
}
}
} else {
// 0: 显示标题与下方的块
nodes = append(nodes, def)
if "1" != def.IALAttr("fold") {
children := treenode.HeadingChildren(def)
for _, c := range children {
if "1" == c.IALAttr("heading-fold") {
// 嵌入块包含折叠标题时不应该显示其下方块 https://github.com/siyuan-note/siyuan/issues/4765
continue
}
nodes = append(nodes, c)
}
}
nodes = append(nodes, c)
}
} else {
// 非标题块,直接添加
nodes = append(nodes, def)
}
b := treenode.GetBlockTree(def.ID)
@ -1095,7 +1072,7 @@ func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, heading
}
if breadcrumb {
blockPaths = buildBlockBreadcrumb(def, nil, true)
blockPaths = buildBlockBreadcrumb(def, nil, true, headingMode)
}
if 1 > len(blockPaths) {
blockPaths = []*BlockPath{}

View file

@ -495,7 +495,7 @@ func BuildBlockBreadcrumb(id string, excludeTypes []string) (ret []*BlockPath, e
return
}
func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string, isEmbedBlock bool) (ret []*BlockPath) {
func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string, isEmbedBlock bool, headingMode ...int) (ret []*BlockPath) {
ret = []*BlockPath{}
if nil == node {
return
@ -505,6 +505,12 @@ func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string, isEmbedBlock bo
return
}
// 默认 headingMode 为 0
mode := 0
if len(headingMode) > 0 {
mode = headingMode[0]
}
headingLevel := 16
maxNameLen := 1024
var hPath string
@ -564,8 +570,13 @@ func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string, isEmbedBlock bo
}
} else {
if ast.NodeDocument != parent.Type {
// 在嵌入块中隐藏最后一个非文档路径的面包屑中的文本 Hide text in breadcrumb of last non-document path in embed block https://github.com/siyuan-note/siyuan/issues/13866
name = ""
// 当headingMode=2仅显示标题下方的块且当前节点是标题时保留标题名称
if 2 == mode && ast.NodeHeading == parent.Type && parent == node {
// 保留标题名称,不清空
} else {
// 在嵌入块中隐藏最后一个非文档路径的面包屑中的文本 Hide text in breadcrumb of last non-document path in embed block https://github.com/siyuan-note/siyuan/issues/13866
name = ""
}
}
}

View file

@ -302,9 +302,37 @@ func resolveEmbedR(n *ast.Node, blockEmbedMode int, luteEngine *lute.Lute, resol
} else if "h" == sqlBlock.Type {
h := treenode.GetNodeInTree(subTree, sqlBlock.ID)
var hChildren []*ast.Node
hChildren = append(hChildren, h)
hChildren = append(hChildren, treenode.HeadingChildren(h)...)
// 从嵌入块的 IAL 属性中解析 custom-heading-mode默认值为 0
blockHeadingMode := 0 // 默认值
if customHeadingMode := n.IALAttr("custom-heading-mode"); "" != customHeadingMode {
if mode, err := strconv.Atoi(customHeadingMode); nil == err && (mode == 0 || mode == 1 || mode == 2) {
blockHeadingMode = mode
}
}
// 根据 blockHeadingMode 处理标题块的显示
// blockHeadingMode: 0=显示标题与下方的块1=仅显示标题2=仅显示标题下方的块
if 1 == blockHeadingMode {
// 仅显示标题
hChildren = append(hChildren, h)
} else if 2 == blockHeadingMode {
// 仅显示标题下方的块(默认行为)
if "1" != h.IALAttr("fold") {
children := treenode.HeadingChildren(h)
for _, c := range children {
if "1" == c.IALAttr("heading-fold") {
// 嵌入块包含折叠标题时不应该显示其下方块 https://github.com/siyuan-note/siyuan/issues/4765
continue
}
hChildren = append(hChildren, c)
}
}
} else {
// 0: 显示标题与下方的块
hChildren = append(hChildren, h)
hChildren = append(hChildren, treenode.HeadingChildren(h)...)
}
if 0 == blockEmbedMode {
embedTopLevel := 0
for _, hChild := range hChildren {