diff --git a/app/src/plugin/loader.ts b/app/src/plugin/loader.ts
index 81a87ca7ad6..5d7904742de 100644
--- a/app/src/plugin/loader.ts
+++ b/app/src/plugin/loader.ts
@@ -104,7 +104,7 @@ const updateDock = (dockItem: Config.IUILayoutDockTab[], index: number, plugin:
plugin.docks[tabItem.type].config.show = tabItem.show;
plugin.docks[tabItem.type].config.size = tabItem.size;
if (!window.siyuan.storage[Constants.LOCAL_PLUGIN_DOCKS][plugin.name]) {
- window.siyuan.storage[Constants.LOCAL_PLUGIN_DOCKS][plugin.name] = {}
+ window.siyuan.storage[Constants.LOCAL_PLUGIN_DOCKS][plugin.name] = {};
}
window.siyuan.storage[Constants.LOCAL_PLUGIN_DOCKS][plugin.name][tabItem.type] = plugin.docks[tabItem.type].config;
setStorageVal(Constants.LOCAL_PLUGIN_DOCKS, window.siyuan.storage[Constants.LOCAL_PLUGIN_DOCKS]);
diff --git a/app/src/protyle/render/av/render.ts b/app/src/protyle/render/av/render.ts
index 21d7d31b695..534a32ef33d 100644
--- a/app/src/protyle/render/av/render.ts
+++ b/app/src/protyle/render/av/render.ts
@@ -70,6 +70,10 @@ export const avRender = (element: Element, protyle: IProtyle, cb?: () => void, v
const snapshot = protyle.options.history?.snapshot;
let newViewID = e.getAttribute(Constants.CUSTOM_SY_AV_VIEW) || "";
if (typeof viewID === "string") {
+ const viewTabElement = e.querySelector(`.av__views > .layout-tab-bar > .item[data-id="${viewID}"]`) as HTMLElement;
+ if (viewTabElement) {
+ e.dataset.pageSize = viewTabElement.dataset.page;
+ }
newViewID = viewID;
fetchPost("/api/av/setDatabaseBlockView", {id: e.dataset.nodeId, viewID});
e.setAttribute(Constants.CUSTOM_SY_AV_VIEW, newViewID);
@@ -195,7 +199,7 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex)}
let tabHTML = "";
let viewData: IAVView;
response.data.views.forEach((item: IAVView) => {
- tabHTML += `
+ tabHTML += `
${item.icon ? unicode2Emoji(item.icon, "item__graphic", true) : ''}
${item.name}
`;
diff --git a/app/src/protyle/render/av/view.ts b/app/src/protyle/render/av/view.ts
index aa3c1a43552..d5235cd0b95 100644
--- a/app/src/protyle/render/av/view.ts
+++ b/app/src/protyle/render/av/view.ts
@@ -187,7 +187,7 @@ export const getViewHTML = (data: IAV) => {
diff --git a/app/src/protyle/toolbar/Link.ts b/app/src/protyle/toolbar/Link.ts
index 47b6019e8a6..003f6e8fd97 100644
--- a/app/src/protyle/toolbar/Link.ts
+++ b/app/src/protyle/toolbar/Link.ts
@@ -45,6 +45,10 @@ export class Link extends ToolbarItem {
}
}
}
+ // https://github.com/siyuan-note/siyuan/issues/12867
+ if (!dataHref && clipText.startsWith("assets/")) {
+ dataHref = clipText;
+ }
} catch (e) {
console.log(e);
}
diff --git a/app/src/protyle/util/editorCommonEvent.ts b/app/src/protyle/util/editorCommonEvent.ts
index 9dbf18c29e3..6605877f2f6 100644
--- a/app/src/protyle/util/editorCommonEvent.ts
+++ b/app/src/protyle/util/editorCommonEvent.ts
@@ -781,7 +781,7 @@ const dragSame = async (protyle: IProtyle, sourceElements: Element[], targetElem
hasFoldHeading = true;
return true;
}
- })
+ });
if (!isCopy && (sourceElements.length > 1 || hasFoldHeading) &&
sourceElements[0].parentElement.classList.contains("sb") &&
sourceElements[0].parentElement.getAttribute("data-sb-layout") === "col") {
diff --git a/app/src/protyle/util/reload.ts b/app/src/protyle/util/reload.ts
index 47b699a610c..b39fd91a4ac 100644
--- a/app/src/protyle/util/reload.ts
+++ b/app/src/protyle/util/reload.ts
@@ -44,7 +44,6 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
defID: protyle.element.getAttribute("data-defid"),
refTreeID: protyle.block.rootID,
keyword: isMention ? inputsElement[1].value : inputsElement[0].value,
- containChildren: false
}, response => {
protyle.options.backlinkData = isMention ? response.data.backmentions : response.data.backlinks;
renderBacklink(protyle, protyle.options.backlinkData);
diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts
index ba9f85a33c4..3740c1b6389 100644
--- a/app/src/protyle/wysiwyg/keydown.ts
+++ b/app/src/protyle/wysiwyg/keydown.ts
@@ -696,7 +696,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
// 页面按向下/右箭头丢失焦点 https://ld246.com/article/1629954026096
const lastEditElement = getContenteditableElement(nodeElement);
// 代码块需替换最后一个 /n https://github.com/siyuan-note/siyuan/issues/3221
- if (lastEditElement && lastEditElement.textContent.replace(/\n$/, "").length <= getSelectionOffset(lastEditElement, undefined, range).end) {
+ if (lastEditElement && !lastEditElement.querySelector(".emoji") && lastEditElement.textContent.replace(/\n$/, "").length <= getSelectionOffset(lastEditElement, undefined, range).end) {
event.stopPropagation();
event.preventDefault();
focusByRange(range);
@@ -860,7 +860,9 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
const currentNode = range.startContainer.childNodes[range.startOffset - 1] as HTMLElement;
if (position.start === 0 && (
range.startOffset === 0 ||
- (currentNode && currentNode.nodeType === 3 && !hasPreviousSibling(currentNode) && currentNode.innerText === "") // https://ld246.com/article/1649251218696
+ (currentNode && currentNode.nodeType === 3 && !hasPreviousSibling(currentNode) &&
+ // 需使用 textContent,文本元素没有 innerText
+ currentNode.textContent === "") // https://ld246.com/article/1649251218696
)) {
removeBlock(protyle, nodeElement, range, "Backspace");
event.stopPropagation();
diff --git a/app/src/protyle/wysiwyg/remove.ts b/app/src/protyle/wysiwyg/remove.ts
index 1869605f191..e50e8a4c6e6 100644
--- a/app/src/protyle/wysiwyg/remove.ts
+++ b/app/src/protyle/wysiwyg/remove.ts
@@ -389,7 +389,7 @@ export const removeBlock = (protyle: IProtyle, blockElement: Element, range: Ran
focusBlock(previousLastElement, undefined, false);
} else {
const previousLastEditElement = getContenteditableElement(previousLastElement);
- if (editableElement && editableElement.textContent !== "") {
+ if (editableElement && (editableElement.textContent !== "" || editableElement.querySelector(".emoji"))) {
// 非空块
range.setEndAfter(editableElement.lastChild);
// 数学公式回车后再删除 https://github.com/siyuan-note/siyuan/issues/3850
diff --git a/app/src/protyle/wysiwyg/renderBacklink.ts b/app/src/protyle/wysiwyg/renderBacklink.ts
index 190e9d65c71..ff7c6cbaeba 100644
--- a/app/src/protyle/wysiwyg/renderBacklink.ts
+++ b/app/src/protyle/wysiwyg/renderBacklink.ts
@@ -16,7 +16,7 @@ export const renderBacklink = (protyle: IProtyle, backlinkData: {
protyle.block.showAll = true;
let html = "";
backlinkData.forEach(item => {
- html += genBreadcrumb(item.blockPaths) + setBacklinkFold(item.dom, item.expand);
+ html += genBreadcrumb(item.blockPaths, false, backlinkData.length) + setBacklinkFold(item.dom, item.expand);
});
protyle.wysiwyg.element.innerHTML = html;
processRender(protyle.wysiwyg.element);
@@ -99,9 +99,9 @@ export const getBacklinkHeadingMore = (moreElement: HTMLElement) => {
moreElement.remove();
};
-export const genBreadcrumb = (blockPaths: IBreadcrumb[], renderFirst = false) => {
+export const genBreadcrumb = (blockPaths: IBreadcrumb[], renderFirst: boolean, parentLength?: number) => {
if (1 > blockPaths.length) {
- return "";
+ return `
`;
}
let html = "";
diff --git a/app/src/types/config.d.ts b/app/src/types/config.d.ts
index 14c34d48bb1..9bebba93fc6 100644
--- a/app/src/types/config.d.ts
+++ b/app/src/types/config.d.ts
@@ -341,6 +341,10 @@ declare namespace Config {
* The default number of backlinks to mention
*/
backmentionExpandCount: number;
+ /**
+ * Whether the backlink contains children
+ */
+ backlinkContainChildren: boolean;
/**
* The maximum length of the dynamic anchor text for block references
*/
diff --git a/app/src/types/index.d.ts b/app/src/types/index.d.ts
index 8e27a41f9c4..b098d8817ce 100644
--- a/app/src/types/index.d.ts
+++ b/app/src/types/index.d.ts
@@ -760,6 +760,7 @@ interface IAVView {
type: string
icon: string
hideAttrViewName: boolean
+ pageSize: number
}
interface IAVTable extends IAVView {
diff --git a/kernel/api/av.go b/kernel/api/av.go
index 190aab12035..de1ae7f35d5 100644
--- a/kernel/api/av.go
+++ b/kernel/api/av.go
@@ -560,12 +560,18 @@ func renderAttributeView(c *gin.Context) {
var views []map[string]interface{}
for _, v := range attrView.Views {
+ pSize := 10
+ if nil != v.Table && av.LayoutTypeTable == v.LayoutType {
+ pSize = v.Table.PageSize
+ }
+
view := map[string]interface{}{
"id": v.ID,
"icon": v.Icon,
"name": v.Name,
"hideAttrViewName": v.HideAttrViewName,
"type": v.LayoutType,
+ "pageSize": pSize,
}
views = append(views, view)
diff --git a/kernel/api/ref.go b/kernel/api/ref.go
index 075a75c5c46..a912ce561ca 100644
--- a/kernel/api/ref.go
+++ b/kernel/api/ref.go
@@ -51,7 +51,7 @@ func getBackmentionDoc(c *gin.Context) {
defID := arg["defID"].(string)
refTreeID := arg["refTreeID"].(string)
keyword := arg["keyword"].(string)
- containChildren := true
+ containChildren := model.Conf.Editor.BacklinkContainChildren
if val, ok := arg["containChildren"]; ok {
containChildren = val.(bool)
}
@@ -73,7 +73,7 @@ func getBacklinkDoc(c *gin.Context) {
defID := arg["defID"].(string)
refTreeID := arg["refTreeID"].(string)
keyword := arg["keyword"].(string)
- containChildren := true
+ containChildren := model.Conf.Editor.BacklinkContainChildren
if val, ok := arg["containChildren"]; ok {
containChildren = val.(bool)
}
@@ -109,7 +109,11 @@ func getBacklink2(c *gin.Context) {
if nil != mentionSortArg {
mentionSort, _ = strconv.Atoi(mentionSortArg.(string))
}
- boxID, backlinks, backmentions, linkRefsCount, mentionsCount := model.GetBacklink2(id, keyword, mentionKeyword, sort, mentionSort)
+ containChildren := model.Conf.Editor.BacklinkContainChildren
+ if val, ok := arg["containChildren"]; ok {
+ containChildren = val.(bool)
+ }
+ boxID, backlinks, backmentions, linkRefsCount, mentionsCount := model.GetBacklink2(id, keyword, mentionKeyword, sort, mentionSort, containChildren)
ret.Data = map[string]interface{}{
"backlinks": backlinks,
"linkRefsCount": linkRefsCount,
@@ -141,7 +145,11 @@ func getBacklink(c *gin.Context) {
if nil != arg["beforeLen"] {
beforeLen = int(arg["beforeLen"].(float64))
}
- boxID, backlinks, backmentions, linkRefsCount, mentionsCount := model.GetBacklink(id, keyword, mentionKeyword, beforeLen)
+ containChildren := model.Conf.Editor.BacklinkContainChildren
+ if val, ok := arg["containChildren"]; ok {
+ containChildren = val.(bool)
+ }
+ boxID, backlinks, backmentions, linkRefsCount, mentionsCount := model.GetBacklink(id, keyword, mentionKeyword, beforeLen, containChildren)
ret.Data = map[string]interface{}{
"backlinks": backlinks,
"linkRefsCount": linkRefsCount,
diff --git a/kernel/conf/editor.go b/kernel/conf/editor.go
index 71a5679660f..607a0e912c4 100644
--- a/kernel/conf/editor.go
+++ b/kernel/conf/editor.go
@@ -51,6 +51,7 @@ type Editor struct {
OnlySearchForDoc bool `json:"onlySearchForDoc"` // 是否启用 [[ 仅搜索文档块
BacklinkExpandCount int `json:"backlinkExpandCount"` // 反向链接默认展开数量
BackmentionExpandCount int `json:"backmentionExpandCount"` // 反链提及默认展开数量
+ BacklinkContainChildren bool `json:"backlinkContainChildren"` // 反向链接是否包含子块进行计算
Markdown *util.Markdown `json:"markdown"` // Markdown 配置
}
@@ -86,6 +87,7 @@ func NewEditor() *Editor {
RTL: false,
BacklinkExpandCount: 8,
BackmentionExpandCount: -1,
+ BacklinkContainChildren: false,
Markdown: util.MarkdownSettings,
}
}
diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go
index efe5536326b..46129471651 100644
--- a/kernel/model/backlink.go
+++ b/kernel/model/backlink.go
@@ -96,7 +96,9 @@ func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren bool) (
trees := filesys.LoadTrees(mentionBlockIDs)
for id, tree := range trees {
backlink := buildBacklink(id, tree, mentionKeywords, luteEngine)
- ret = append(ret, backlink)
+ if nil != backlink {
+ ret = append(ret, backlink)
+ }
}
return
}
@@ -133,7 +135,9 @@ func GetBacklinkDoc(defID, refTreeID, keyword string, containChildren bool) (ret
keywords = append(keywords, keyword)
}
backlink := buildBacklink(linkRef.ID, refTree, keywords, luteEngine)
- ret = append(ret, backlink)
+ if nil != backlink {
+ ret = append(ret, backlink)
+ }
}
return
}
@@ -171,10 +175,10 @@ func buildBacklink(refID string, refTree *parse.Tree, keywords []string, luteEng
dom := renderBlockDOMByNodes(renderNodes, luteEngine)
blockPaths := []*BlockPath{}
- if nil != n.Parent && nil != n.Parent.Parent {
+ if nil != n.Parent && ast.NodeDocument != n.Parent.Type && nil != n.Parent.Parent && ast.NodeDocument != n.Parent.Parent.Type {
// 仅在多余一层时才显示面包屑,这样界面展示更加简洁
// The backlink panel no longer displays breadcrumbs of the first-level blocks https://github.com/siyuan-note/siyuan/issues/12862
- blockPaths = buildBlockBreadcrumb(n, nil)
+ blockPaths = buildBlockBreadcrumb(n, nil, false)
}
ret = &Backlink{DOM: dom, BlockPaths: blockPaths, Expand: expand}
return
@@ -230,7 +234,7 @@ func getBacklinkRenderNodes(n *ast.Node) (ret []*ast.Node, expand bool) {
return
}
-func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode int) (boxID string, backlinks, backmentions []*Path, linkRefsCount, mentionsCount int) {
+func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode int, containChildren bool) (boxID string, backlinks, backmentions []*Path, linkRefsCount, mentionsCount int) {
keyword = strings.TrimSpace(keyword)
mentionKeyword = strings.TrimSpace(mentionKeyword)
backlinks, backmentions = []*Path{}, []*Path{}
@@ -242,7 +246,7 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode
rootID := sqlBlock.RootID
boxID = sqlBlock.Box
- refs := sql.QueryRefsByDefID(id, false)
+ refs := sql.QueryRefsByDefID(id, containChildren)
refs = removeDuplicatedRefs(refs)
linkRefs, linkRefsCount, excludeBacklinkIDs := buildLinkRefs(rootID, refs, keyword)
@@ -328,7 +332,7 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode
return
}
-func GetBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID string, linkPaths, mentionPaths []*Path, linkRefsCount, mentionsCount int) {
+func GetBacklink(id, keyword, mentionKeyword string, beforeLen int, containChildren bool) (boxID string, linkPaths, mentionPaths []*Path, linkRefsCount, mentionsCount int) {
linkPaths = []*Path{}
mentionPaths = []*Path{}
@@ -340,7 +344,7 @@ func GetBacklink(id, keyword, mentionKeyword string, beforeLen int) (boxID strin
boxID = sqlBlock.Box
var links []*Block
- refs := sql.QueryRefsByDefID(id, false)
+ refs := sql.QueryRefsByDefID(id, containChildren)
refs = removeDuplicatedRefs(refs)
// 为了减少查询,组装好 IDs 后一次查出
diff --git a/kernel/model/block.go b/kernel/model/block.go
index 69e643a5772..d6009de122e 100644
--- a/kernel/model/block.go
+++ b/kernel/model/block.go
@@ -887,7 +887,7 @@ func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, heading
}
if breadcrumb {
- blockPaths = buildBlockBreadcrumb(def, nil)
+ blockPaths = buildBlockBreadcrumb(def, nil, true)
}
if 1 > len(blockPaths) {
blockPaths = []*BlockPath{}
diff --git a/kernel/model/blockinfo.go b/kernel/model/blockinfo.go
index ccfbcdba3ec..79d0ef89767 100644
--- a/kernel/model/blockinfo.go
+++ b/kernel/model/blockinfo.go
@@ -416,11 +416,11 @@ func BuildBlockBreadcrumb(id string, excludeTypes []string) (ret []*BlockPath, e
return
}
- ret = buildBlockBreadcrumb(node, excludeTypes)
+ ret = buildBlockBreadcrumb(node, excludeTypes, true)
return
}
-func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string) (ret []*BlockPath) {
+func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string, displayCurrentNodeContent bool) (ret []*BlockPath) {
ret = []*BlockPath{}
if nil == node {
return
@@ -480,6 +480,12 @@ func buildBlockBreadcrumb(node *ast.Node, excludeTypes []string) (ret []*BlockPa
name = strings.ReplaceAll(name, editor.Caret, "")
name = util.EscapeHTML(name)
+
+ if parent == node && !displayCurrentNodeContent {
+ // 反链中不显示当前块内容 https://github.com/siyuan-note/siyuan/issues/12862#issuecomment-2426406327
+ name = ""
+ }
+
if add {
ret = append([]*BlockPath{{
ID: id,
diff --git a/kernel/util/working.go b/kernel/util/working.go
index c79278c1cfd..60c57d8fbd9 100644
--- a/kernel/util/working.go
+++ b/kernel/util/working.go
@@ -44,7 +44,7 @@ import (
var Mode = "prod"
const (
- Ver = "3.1.9"
+ Ver = "3.1.10"
IsInsider = false
)