From c30a6dd711bb294a7cb06ac5e89a5c8862cc853b Mon Sep 17 00:00:00 2001
From: Daniel <845765@qq.com>
Date: Mon, 4 Nov 2024 09:12:42 +0800
Subject: [PATCH 1/3] :art: Dynamically loading graph nodes and edges
https://github.com/siyuan-note/siyuan/issues/13014
---
app/src/layout/dock/Graph.ts | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/app/src/layout/dock/Graph.ts b/app/src/layout/dock/Graph.ts
index 84729af24..8ce394454 100644
--- a/app/src/layout/dock/Graph.ts
+++ b/app/src/layout/dock/Graph.ts
@@ -619,37 +619,43 @@ export class Graph extends Model {
iterations: 256,
updateInterval: 64,
onlyDynamicEdges: false,
- fit: true
+ fit: false
},
timestep: 0.5,
adaptiveTimestep: true,
wind: {x: 0, y: 0}
},
};
- let j = Math.max(Math.ceil(this.graphData.nodes.length * 0.1), 128);
- const nodes = new vis.DataSet(this.graphData.nodes.slice(0, j));
+ let i = Math.max(Math.ceil(this.graphData.nodes.length * 0.1), 128);
+ const nodes = new vis.DataSet(this.graphData.nodes.slice(0, i));
const edges = new vis.DataSet();
const network = new vis.Network(this.graphElement, {nodes, edges}, options);
const time = 256;
+ let intervalNodeTime = Math.max(Math.ceil(time / 8), 32);
let batch = this.graphData.nodes.length / time / 2;
- if (batch < 64) {
- batch = 64;
+ if (batch < 32) {
+ batch = 32;
}
- if (batch > 256) {
- batch = 256;
+ if (batch > 128) {
+ batch = 128;
}
- let i = 0;
+ let count = 0;
const intervalNode = setInterval(() => {
- const nodes = this.graphData.nodes.slice(j, j + batch);
+ const nodes = this.graphData.nodes.slice(i, i + batch);
if (nodes.length === 0) {
clearInterval(intervalNode);
return;
}
network.body.data.nodes.add(nodes);
- j += batch;
- }, time / 8);
+ i += batch;
+ count++;
+ if (0 === count % (batch / 8)) {
+ network.fit({animation: false});
+ }
+ }, intervalNodeTime);
+ let j = 0;
const intervalId = setInterval(() => {
- const edges = this.graphData.links.slice(i, i + batch);
+ const edges = this.graphData.links.slice(j, j + batch);
if (edges.length === 0) {
clearInterval(intervalId);
network.fit({
@@ -658,7 +664,7 @@ export class Graph extends Model {
return;
}
network.body.data.edges.add(edges);
- i += batch;
+ j += batch;
}, time);
this.network = network;
network.on("stabilizationIterationsDone", () => {
@@ -670,7 +676,7 @@ export class Graph extends Model {
network.on("dragEnd", () => {
setTimeout(() => {
network.physics.stopSimulation();
- }, 5000);
+ }, 3000);
});
network.on("click", (params: any) => {
if (params.nodes.length !== 1) {
From 9c5a61016062193d19d95f44d9b0c6d797a70d0a Mon Sep 17 00:00:00 2001
From: Daniel <845765@qq.com>
Date: Mon, 4 Nov 2024 09:36:56 +0800
Subject: [PATCH 2/3] :bug: Fix inline underscore element paste as plain text
https://github.com/siyuan-note/siyuan/issues/13015
---
app/src/protyle/util/paste.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/src/protyle/util/paste.ts b/app/src/protyle/util/paste.ts
index 689a59410..0b0669633 100644
--- a/app/src/protyle/util/paste.ts
+++ b/app/src/protyle/util/paste.ts
@@ -182,7 +182,7 @@ export const pasteAsPlainText = async (protyle: IProtyle) => {
textPlain = textPlain.replace(/__@sub@__/g, "").replace(/__@\/sub@__/g, "");
textPlain = textPlain.replace(/__@sup@__/g, "").replace(/__@\/sup@__/g, "");
textPlain = textPlain.replace(/__@kbd@__/g, "").replace(/__@\/kbd@__/g, "");
- textPlain = textPlain.replace(/__@u@__/g, "").replace(/__@\/u@__/g, "").replace(/__@\/u@__/g, "");
const content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
// insertHTML 会进行内部反转义
From 8b35367eb5fc1003768b04245feac50b4368a291 Mon Sep 17 00:00:00 2001
From: Daniel <845765@qq.com>
Date: Mon, 4 Nov 2024 10:04:45 +0800
Subject: [PATCH 3/3] :bug: Fix find-replace for spaces
https://github.com/siyuan-note/siyuan/issues/13010 Regexp compile error
https://ld246.com/article/1730678393331
---
kernel/model/search.go | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/kernel/model/search.go b/kernel/model/search.go
index c78cc0515..05a0d37e1 100644
--- a/kernel/model/search.go
+++ b/kernel/model/search.go
@@ -830,17 +830,19 @@ func replaceTextNode(text *ast.Node, method int, keyword string, replacement str
newContent = bytes.ReplaceAll(text.Tokens, []byte(keyword), []byte(replacement))
}
} else {
- // 当搜索结果中的文本元素包含大小写混合时替换失败
- // Replace fails when search results contain mixed case in text elements https://github.com/siyuan-note/siyuan/issues/9171
- keywords := strings.Split(keyword, " ")
- // keyword 可能是 "foo Foo" 使用空格分隔的大小写命中情况,这里统一转换小写后去重
- if 0 < len(keywords) {
- var lowerKeywords []string
- for _, k := range keywords {
- lowerKeywords = append(lowerKeywords, strings.ToLower(k))
+ if "" != strings.TrimSpace(keyword) {
+ // 当搜索结果中的文本元素包含大小写混合时替换失败
+ // Replace fails when search results contain mixed case in text elements https://github.com/siyuan-note/siyuan/issues/9171
+ keywords := strings.Split(keyword, " ")
+ // keyword 可能是 "foo Foo" 使用空格分隔的大小写命中情况,这里统一转换小写后去重
+ if 0 < len(keywords) {
+ var lowerKeywords []string
+ for _, k := range keywords {
+ lowerKeywords = append(lowerKeywords, strings.ToLower(k))
+ }
+ lowerKeywords = gulu.Str.RemoveDuplicatedElem(lowerKeywords)
+ keyword = strings.Join(lowerKeywords, " ")
}
- lowerKeywords = gulu.Str.RemoveDuplicatedElem(lowerKeywords)
- keyword = strings.Join(lowerKeywords, " ")
}
if bytes.Contains(bytes.ToLower(text.Tokens), []byte(keyword)) {
@@ -945,7 +947,7 @@ func FullTextSearchBlock(query string, boxes, paths []string, types map[string]b
typeFilter := buildTypeFilter(types)
boxFilter := buildBoxesFilter(boxes)
pathFilter := buildPathsFilter(paths)
- if 2 > len(strings.Split(query, " ")) {
+ if 2 > len(strings.Split(strings.TrimSpace(query), " ")) {
blocks, matchedBlockCount, matchedRootCount = fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderByClause, beforeLen, page, pageSize)
} else {
docMode = true // 文档全文搜索模式 https://github.com/siyuan-note/siyuan/issues/10584
@@ -1304,7 +1306,12 @@ func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, ignoreFilter
fieldFilter := fieldRegexp(exp)
stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter
stmt += boxFilter + pathFilter + ignoreFilter + " " + orderBy
- regex := regexp.MustCompile(exp)
+ regex, err := regexp.Compile(exp)
+ if nil != err {
+ util.PushErrMsg(err.Error(), 5000)
+ return
+ }
+
blocks := sql.SelectBlocksRegex(stmt, regex, Conf.Search.Name, Conf.Search.Alias, Conf.Search.Memo, Conf.Search.IAL, page, pageSize)
ret = fromSQLBlocks(&blocks, "", beforeLen)
if 1 > len(ret) {
@@ -1458,7 +1465,10 @@ func highlightByRegexp(query, typeFilter, id string) (ret []string) {
fieldFilter := fieldRegexp(query)
stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter
stmt += " AND root_id = '" + id + "'"
- regex := regexp.MustCompile(query)
+ regex, _ := regexp.Compile(query)
+ if nil == regex {
+ return
+ }
sqlBlocks := sql.SelectBlocksRegex(stmt, regex, Conf.Search.Name, Conf.Search.Alias, Conf.Search.Memo, Conf.Search.IAL, 1, 256)
for _, block := range sqlBlocks {
keyword := gulu.Str.SubstringsBetween(block.Content, search.SearchMarkLeft, search.SearchMarkRight)