mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-21 00:50:13 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
b9e62d2b7a
3 changed files with 44 additions and 28 deletions
|
|
@ -632,37 +632,43 @@ export class Graph extends Model {
|
||||||
iterations: 256,
|
iterations: 256,
|
||||||
updateInterval: 64,
|
updateInterval: 64,
|
||||||
onlyDynamicEdges: false,
|
onlyDynamicEdges: false,
|
||||||
fit: true
|
fit: false
|
||||||
},
|
},
|
||||||
timestep: 0.5,
|
timestep: 0.5,
|
||||||
adaptiveTimestep: true,
|
adaptiveTimestep: true,
|
||||||
wind: {x: 0, y: 0}
|
wind: {x: 0, y: 0}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let j = Math.max(Math.ceil(this.graphData.nodes.length * 0.1), 128);
|
let i = Math.max(Math.ceil(this.graphData.nodes.length * 0.1), 128);
|
||||||
const nodes = new vis.DataSet(this.graphData.nodes.slice(0, j));
|
const nodes = new vis.DataSet(this.graphData.nodes.slice(0, i));
|
||||||
const edges = new vis.DataSet();
|
const edges = new vis.DataSet();
|
||||||
const network = new vis.Network(this.graphElement, {nodes, edges}, options);
|
const network = new vis.Network(this.graphElement, {nodes, edges}, options);
|
||||||
const time = 256;
|
const time = 256;
|
||||||
|
let intervalNodeTime = Math.max(Math.ceil(time / 8), 32);
|
||||||
let batch = this.graphData.nodes.length / time / 2;
|
let batch = this.graphData.nodes.length / time / 2;
|
||||||
if (batch < 64) {
|
if (batch < 32) {
|
||||||
batch = 64;
|
batch = 32;
|
||||||
}
|
}
|
||||||
if (batch > 256) {
|
if (batch > 128) {
|
||||||
batch = 256;
|
batch = 128;
|
||||||
}
|
}
|
||||||
let i = 0;
|
let count = 0;
|
||||||
const intervalNode = setInterval(() => {
|
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) {
|
if (nodes.length === 0) {
|
||||||
clearInterval(intervalNode);
|
clearInterval(intervalNode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
network.body.data.nodes.add(nodes);
|
network.body.data.nodes.add(nodes);
|
||||||
j += batch;
|
i += batch;
|
||||||
}, time / 8);
|
count++;
|
||||||
|
if (0 === count % (batch / 8)) {
|
||||||
|
network.fit({animation: false});
|
||||||
|
}
|
||||||
|
}, intervalNodeTime);
|
||||||
|
let j = 0;
|
||||||
const intervalId = setInterval(() => {
|
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) {
|
if (edges.length === 0) {
|
||||||
clearInterval(intervalId);
|
clearInterval(intervalId);
|
||||||
network.fit({
|
network.fit({
|
||||||
|
|
@ -671,7 +677,7 @@ export class Graph extends Model {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
network.body.data.edges.add(edges);
|
network.body.data.edges.add(edges);
|
||||||
i += batch;
|
j += batch;
|
||||||
}, time);
|
}, time);
|
||||||
this.network = network;
|
this.network = network;
|
||||||
network.on("stabilizationIterationsDone", () => {
|
network.on("stabilizationIterationsDone", () => {
|
||||||
|
|
@ -683,7 +689,7 @@ export class Graph extends Model {
|
||||||
network.on("dragEnd", () => {
|
network.on("dragEnd", () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
network.physics.stopSimulation();
|
network.physics.stopSimulation();
|
||||||
}, 5000);
|
}, 3000);
|
||||||
});
|
});
|
||||||
network.on("click", (params: any) => {
|
network.on("click", (params: any) => {
|
||||||
if (params.nodes.length !== 1) {
|
if (params.nodes.length !== 1) {
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ export const pasteAsPlainText = async (protyle: IProtyle) => {
|
||||||
textPlain = textPlain.replace(/__@sub@__/g, "<sub>").replace(/__@\/sub@__/g, "</sub>");
|
textPlain = textPlain.replace(/__@sub@__/g, "<sub>").replace(/__@\/sub@__/g, "</sub>");
|
||||||
textPlain = textPlain.replace(/__@sup@__/g, "<sup>").replace(/__@\/sup@__/g, "</sup>");
|
textPlain = textPlain.replace(/__@sup@__/g, "<sup>").replace(/__@\/sup@__/g, "</sup>");
|
||||||
textPlain = textPlain.replace(/__@kbd@__/g, "<kbd>").replace(/__@\/kbd@__/g, "</kbd>");
|
textPlain = textPlain.replace(/__@kbd@__/g, "<kbd>").replace(/__@\/kbd@__/g, "</kbd>");
|
||||||
textPlain = textPlain.replace(/__@u@__/g, "<u>").replace(/__@\/u@__/g, "</u");
|
textPlain = textPlain.replace(/__@u@__/g, "<u>").replace(/__@\/u@__/g, "</u>");
|
||||||
|
|
||||||
const content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
|
const content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
|
||||||
// insertHTML 会进行内部反转义
|
// insertHTML 会进行内部反转义
|
||||||
|
|
|
||||||
|
|
@ -830,17 +830,19 @@ func replaceTextNode(text *ast.Node, method int, keyword string, replacement str
|
||||||
newContent = bytes.ReplaceAll(text.Tokens, []byte(keyword), []byte(replacement))
|
newContent = bytes.ReplaceAll(text.Tokens, []byte(keyword), []byte(replacement))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 当搜索结果中的文本元素包含大小写混合时替换失败
|
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, " ")
|
// Replace fails when search results contain mixed case in text elements https://github.com/siyuan-note/siyuan/issues/9171
|
||||||
// keyword 可能是 "foo Foo" 使用空格分隔的大小写命中情况,这里统一转换小写后去重
|
keywords := strings.Split(keyword, " ")
|
||||||
if 0 < len(keywords) {
|
// keyword 可能是 "foo Foo" 使用空格分隔的大小写命中情况,这里统一转换小写后去重
|
||||||
var lowerKeywords []string
|
if 0 < len(keywords) {
|
||||||
for _, k := range keywords {
|
var lowerKeywords []string
|
||||||
lowerKeywords = append(lowerKeywords, strings.ToLower(k))
|
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)) {
|
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)
|
typeFilter := buildTypeFilter(types)
|
||||||
boxFilter := buildBoxesFilter(boxes)
|
boxFilter := buildBoxesFilter(boxes)
|
||||||
pathFilter := buildPathsFilter(paths)
|
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)
|
blocks, matchedBlockCount, matchedRootCount = fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, ignoreFilter, orderByClause, beforeLen, page, pageSize)
|
||||||
} else {
|
} else {
|
||||||
docMode = true // 文档全文搜索模式 https://github.com/siyuan-note/siyuan/issues/10584
|
docMode = true // 文档全文搜索模式 https://github.com/siyuan-note/siyuan/issues/10584
|
||||||
|
|
@ -1304,7 +1306,12 @@ func fullTextSearchByRegexp(exp, boxFilter, pathFilter, typeFilter, ignoreFilter
|
||||||
fieldFilter := fieldRegexp(exp)
|
fieldFilter := fieldRegexp(exp)
|
||||||
stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter
|
stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter
|
||||||
stmt += boxFilter + pathFilter + ignoreFilter + " " + orderBy
|
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)
|
blocks := sql.SelectBlocksRegex(stmt, regex, Conf.Search.Name, Conf.Search.Alias, Conf.Search.Memo, Conf.Search.IAL, page, pageSize)
|
||||||
ret = fromSQLBlocks(&blocks, "", beforeLen)
|
ret = fromSQLBlocks(&blocks, "", beforeLen)
|
||||||
if 1 > len(ret) {
|
if 1 > len(ret) {
|
||||||
|
|
@ -1458,7 +1465,10 @@ func highlightByRegexp(query, typeFilter, id string) (ret []string) {
|
||||||
fieldFilter := fieldRegexp(query)
|
fieldFilter := fieldRegexp(query)
|
||||||
stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter
|
stmt := "SELECT * FROM `blocks` WHERE " + fieldFilter + " AND type IN " + typeFilter
|
||||||
stmt += " AND root_id = '" + id + "'"
|
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)
|
sqlBlocks := sql.SelectBlocksRegex(stmt, regex, Conf.Search.Name, Conf.Search.Alias, Conf.Search.Memo, Conf.Search.IAL, 1, 256)
|
||||||
for _, block := range sqlBlocks {
|
for _, block := range sqlBlocks {
|
||||||
keyword := gulu.Str.SubstringsBetween(block.Content, search.SearchMarkLeft, search.SearchMarkRight)
|
keyword := gulu.Str.SubstringsBetween(block.Content, search.SearchMarkLeft, search.SearchMarkRight)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue