mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-21 17:10:12 +01:00
🎨 嵌入块纳入引用计数和反链 https://github.com/siyuan-note/siyuan/issues/7096
This commit is contained in:
parent
6afa767f01
commit
492aabcf22
8 changed files with 117 additions and 50 deletions
|
|
@ -105,7 +105,7 @@ func ListNotebooks() (ret []*Box, err error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !util.IsIDPattern(dir.Name()) {
|
if !ast.IsNodeIDPattern(dir.Name()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ func (box *Box) Move(oldPath, newPath string) error {
|
||||||
return errors.New(msg)
|
return errors.New(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldDir := path.Dir(oldPath); util.IsIDPattern(path.Base(oldDir)) {
|
if oldDir := path.Dir(oldPath); ast.IsNodeIDPattern(path.Base(oldDir)) {
|
||||||
fromDir := filepath.Join(boxLocalPath, oldDir)
|
fromDir := filepath.Join(boxLocalPath, oldDir)
|
||||||
if util.IsEmptyDir(fromDir) {
|
if util.IsEmptyDir(fromDir) {
|
||||||
filelock.Remove(fromDir)
|
filelock.Remove(fromDir)
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
|
||||||
var docs []*File
|
var docs []*File
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if file.isdir {
|
if file.isdir {
|
||||||
if !util.IsIDPattern(file.name) {
|
if !ast.IsNodeIDPattern(file.name) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,6 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"github.com/88250/lute/parse"
|
|
||||||
"github.com/siyuan-note/siyuan/kernel/util"
|
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
@ -27,6 +25,7 @@ import (
|
||||||
"github.com/88250/gulu"
|
"github.com/88250/gulu"
|
||||||
"github.com/88250/lute/ast"
|
"github.com/88250/lute/ast"
|
||||||
"github.com/88250/lute/html"
|
"github.com/88250/lute/html"
|
||||||
|
"github.com/88250/lute/parse"
|
||||||
"github.com/siyuan-note/logging"
|
"github.com/siyuan-note/logging"
|
||||||
"github.com/siyuan-note/siyuan/kernel/sql"
|
"github.com/siyuan-note/siyuan/kernel/sql"
|
||||||
"github.com/siyuan-note/siyuan/kernel/treenode"
|
"github.com/siyuan-note/siyuan/kernel/treenode"
|
||||||
|
|
@ -690,7 +689,7 @@ func nodeTitleLabel(node *GraphNode, blockContent string) {
|
||||||
|
|
||||||
func query2Stmt(queryStr string) (ret string) {
|
func query2Stmt(queryStr string) (ret string) {
|
||||||
buf := bytes.Buffer{}
|
buf := bytes.Buffer{}
|
||||||
if util.IsIDPattern(queryStr) {
|
if ast.IsNodeIDPattern(queryStr) {
|
||||||
buf.WriteString("id = '" + queryStr + "'")
|
buf.WriteString("id = '" + queryStr + "'")
|
||||||
} else {
|
} else {
|
||||||
var tags []string
|
var tags []string
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.IsDir() && util.IsIDPattern(info.Name()) {
|
if info.IsDir() && ast.IsNodeIDPattern(info.Name()) {
|
||||||
renamePaths[path] = path
|
renamePaths[path] = path
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -534,7 +534,7 @@ func searchBySQL(stmt string, beforeLen int) (ret []*Block, matchedBlockCount, m
|
||||||
func fullTextSearchRefBlock(keyword string, beforeLen int) (ret []*Block) {
|
func fullTextSearchRefBlock(keyword string, beforeLen int) (ret []*Block) {
|
||||||
keyword = gulu.Str.RemoveInvisible(keyword)
|
keyword = gulu.Str.RemoveInvisible(keyword)
|
||||||
|
|
||||||
if util.IsIDPattern(keyword) {
|
if ast.IsNodeIDPattern(keyword) {
|
||||||
ret, _, _ = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+keyword+"'", 36)
|
ret, _, _ = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+keyword+"'", 36)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -581,7 +581,7 @@ func fullTextSearchRefBlock(keyword string, beforeLen int) (ret []*Block) {
|
||||||
|
|
||||||
func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
|
func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, orderBy string, beforeLen int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
|
||||||
query = gulu.Str.RemoveInvisible(query)
|
query = gulu.Str.RemoveInvisible(query)
|
||||||
if util.IsIDPattern(query) {
|
if ast.IsNodeIDPattern(query) {
|
||||||
ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen)
|
ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -590,7 +590,7 @@ func fullTextSearchByQuerySyntax(query, boxFilter, pathFilter, typeFilter, order
|
||||||
|
|
||||||
func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter string, orderBy string, beforeLen int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
|
func fullTextSearchByKeyword(query, boxFilter, pathFilter, typeFilter string, orderBy string, beforeLen int) (ret []*Block, matchedBlockCount, matchedRootCount int) {
|
||||||
query = gulu.Str.RemoveInvisible(query)
|
query = gulu.Str.RemoveInvisible(query)
|
||||||
if util.IsIDPattern(query) {
|
if ast.IsNodeIDPattern(query) {
|
||||||
ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen)
|
ret, matchedBlockCount, matchedRootCount = searchBySQL("SELECT * FROM `blocks` WHERE `id` = '"+query+"'", beforeLen)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -660,7 +660,7 @@ func fullTextSearchByFTS(query, boxFilter, pathFilter, typeFilter, orderBy strin
|
||||||
|
|
||||||
func fullTextSearchCount(query, boxFilter, pathFilter, typeFilter string) (matchedBlockCount, matchedRootCount int) {
|
func fullTextSearchCount(query, boxFilter, pathFilter, typeFilter string) (matchedBlockCount, matchedRootCount int) {
|
||||||
query = gulu.Str.RemoveInvisible(query)
|
query = gulu.Str.RemoveInvisible(query)
|
||||||
if util.IsIDPattern(query) {
|
if ast.IsNodeIDPattern(query) {
|
||||||
ret, _ := sql.Query("SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE `id` = '" + query + "'")
|
ret, _ := sql.Query("SELECT COUNT(id) AS `matches`, COUNT(DISTINCT(root_id)) AS `docs` FROM `blocks` WHERE `id` = '" + query + "'")
|
||||||
if 1 > len(ret) {
|
if 1 > len(ret) {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,7 @@ func refsFromTree(tree *parse.Tree) (refs []*Ref, fileAnnotationRefs []*FileAnno
|
||||||
if treenode.IsBlockRef(n) {
|
if treenode.IsBlockRef(n) {
|
||||||
ref := buildRef(tree, n)
|
ref := buildRef(tree, n)
|
||||||
refs = append(refs, ref)
|
refs = append(refs, ref)
|
||||||
} else if ast.NodeTextMark == n.Type && n.IsTextMarkType("file-annotation-ref") {
|
} else if treenode.IsFileAnnotationRef(n) {
|
||||||
pathID := n.TextMarkFileAnnotationRefID
|
pathID := n.TextMarkFileAnnotationRefID
|
||||||
idx := strings.LastIndex(pathID, "/")
|
idx := strings.LastIndex(pathID, "/")
|
||||||
if -1 == idx {
|
if -1 == idx {
|
||||||
|
|
@ -305,6 +305,9 @@ func refsFromTree(tree *parse.Tree) (refs []*Ref, fileAnnotationRefs []*FileAnno
|
||||||
Type: treenode.TypeAbbr(n.Type.String()),
|
Type: treenode.TypeAbbr(n.Type.String()),
|
||||||
}
|
}
|
||||||
fileAnnotationRefs = append(fileAnnotationRefs, ref)
|
fileAnnotationRefs = append(fileAnnotationRefs, ref)
|
||||||
|
} else if treenode.IsEmbedBlockRef(n) {
|
||||||
|
ref := buildEmbedRef(tree, n)
|
||||||
|
refs = append(refs, ref)
|
||||||
}
|
}
|
||||||
return ast.WalkContinue
|
return ast.WalkContinue
|
||||||
})
|
})
|
||||||
|
|
@ -338,6 +341,43 @@ func buildRef(tree *parse.Tree, refNode *ast.Node) *Ref {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildEmbedRef(tree *parse.Tree, embedNode *ast.Node) *Ref {
|
||||||
|
markdown := treenode.ExportNodeStdMd(embedNode, luteEngine)
|
||||||
|
defBlockID, text := getEmbedRef(embedNode)
|
||||||
|
var defBlockParentID, defBlockRootID, defBlockPath string
|
||||||
|
defBlock := treenode.GetBlockTree(defBlockID)
|
||||||
|
if nil != defBlock {
|
||||||
|
defBlockParentID = defBlock.ParentID
|
||||||
|
defBlockRootID = defBlock.RootID
|
||||||
|
defBlockPath = defBlock.Path
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Ref{
|
||||||
|
ID: ast.NewNodeID(),
|
||||||
|
DefBlockID: defBlockID,
|
||||||
|
DefBlockParentID: defBlockParentID,
|
||||||
|
DefBlockRootID: defBlockRootID,
|
||||||
|
DefBlockPath: defBlockPath,
|
||||||
|
BlockID: embedNode.ID,
|
||||||
|
RootID: tree.ID,
|
||||||
|
Box: tree.Box,
|
||||||
|
Path: tree.Path,
|
||||||
|
Content: text,
|
||||||
|
Markdown: markdown,
|
||||||
|
Type: treenode.TypeAbbr(embedNode.Type.String()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEmbedRef(embedNode *ast.Node) (queryBlockID, refText string) {
|
||||||
|
queryBlockID = treenode.GetEmbedBlockRef(embedNode)
|
||||||
|
if "" == queryBlockID {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
refText = getRefText(queryBlockID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func fromTree(node *ast.Node, tree *parse.Tree) (blocks []*Block, spans []*Span, assets []*Asset, attributes []*Attribute) {
|
func fromTree(node *ast.Node, tree *parse.Tree) (blocks []*Block, spans []*Span, assets []*Asset, attributes []*Attribute) {
|
||||||
rootID := tree.Root.ID
|
rootID := tree.Root.ID
|
||||||
boxID := tree.Box
|
boxID := tree.Box
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ package treenode
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
util2 "github.com/siyuan-note/siyuan/kernel/util"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
|
@ -30,10 +29,62 @@ import (
|
||||||
"github.com/88250/lute/lex"
|
"github.com/88250/lute/lex"
|
||||||
"github.com/88250/lute/parse"
|
"github.com/88250/lute/parse"
|
||||||
"github.com/88250/lute/render"
|
"github.com/88250/lute/render"
|
||||||
"github.com/88250/lute/util"
|
"github.com/88250/vitess-sqlparser/sqlparser"
|
||||||
"github.com/siyuan-note/logging"
|
"github.com/siyuan-note/logging"
|
||||||
|
"github.com/siyuan-note/siyuan/kernel/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func GetEmbedBlockRef(embedNode *ast.Node) (blockRefID string) {
|
||||||
|
if nil == embedNode || ast.NodeBlockQueryEmbed != embedNode.Type {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
scriptNode := embedNode.ChildByType(ast.NodeBlockQueryEmbedScript)
|
||||||
|
if nil == scriptNode {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt := scriptNode.TokensStr()
|
||||||
|
parsedStmt, err := sqlparser.Parse(stmt)
|
||||||
|
if nil != err {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch parsedStmt.(type) {
|
||||||
|
case *sqlparser.Select:
|
||||||
|
slct := parsedStmt.(*sqlparser.Select)
|
||||||
|
if nil == slct.Where || nil == slct.Where.Expr {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch slct.Where.Expr.(type) {
|
||||||
|
case *sqlparser.ComparisonExpr: // WHERE id = '20060102150405-1a2b3c4'
|
||||||
|
comp := slct.Where.Expr.(*sqlparser.ComparisonExpr)
|
||||||
|
switch comp.Left.(type) {
|
||||||
|
case *sqlparser.ColName:
|
||||||
|
col := comp.Left.(*sqlparser.ColName)
|
||||||
|
if nil == col || "id" != col.Name.Lowered() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch comp.Right.(type) {
|
||||||
|
case *sqlparser.SQLVal:
|
||||||
|
val := comp.Right.(*sqlparser.SQLVal)
|
||||||
|
if nil == val || sqlparser.StrVal != val.Type {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
idVal := string(val.Val)
|
||||||
|
if !ast.IsNodeIDPattern(idVal) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
blockRefID = idVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func GetBlockRef(n *ast.Node) (blockRefID, blockRefText, blockRefSubtype string) {
|
func GetBlockRef(n *ast.Node) (blockRefID, blockRefText, blockRefSubtype string) {
|
||||||
if !IsBlockRef(n) {
|
if !IsBlockRef(n) {
|
||||||
return
|
return
|
||||||
|
|
@ -52,6 +103,17 @@ func IsBlockRef(n *ast.Node) bool {
|
||||||
return ast.NodeTextMark == n.Type && n.IsTextMarkType("block-ref")
|
return ast.NodeTextMark == n.Type && n.IsTextMarkType("block-ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsFileAnnotationRef(n *ast.Node) bool {
|
||||||
|
if nil == n {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return ast.NodeTextMark == n.Type && n.IsTextMarkType("file-annotation-ref")
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsEmbedBlockRef(n *ast.Node) bool {
|
||||||
|
return "" != GetEmbedBlockRef(n)
|
||||||
|
}
|
||||||
|
|
||||||
func NodeStaticMdContent(node *ast.Node, luteEngine *lute.Lute) (md, content string) {
|
func NodeStaticMdContent(node *ast.Node, luteEngine *lute.Lute) (md, content string) {
|
||||||
md = ExportNodeStdMd(node, luteEngine)
|
md = ExportNodeStdMd(node, luteEngine)
|
||||||
content = NodeStaticContent(node, nil)
|
content = NodeStaticContent(node, nil)
|
||||||
|
|
@ -111,7 +173,7 @@ func NodeStaticContent(node *ast.Node, excludeTypes []string) string {
|
||||||
var linkDestStr, ocrText string
|
var linkDestStr, ocrText string
|
||||||
if nil != linkDest {
|
if nil != linkDest {
|
||||||
linkDestStr = linkDest.TokensStr()
|
linkDestStr = linkDest.TokensStr()
|
||||||
ocrText = util2.GetAssetText(linkDestStr)
|
ocrText = util.GetAssetText(linkDestStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
linkText := n.ChildByType(ast.NodeLinkText)
|
linkText := n.ChildByType(ast.NodeLinkText)
|
||||||
|
|
@ -370,7 +432,7 @@ func IsChartCodeBlockCode(code *ast.Node) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
language := util.BytesToStr(code.Previous.CodeBlockInfo)
|
language := gulu.Str.FromBytes(code.Previous.CodeBlockInfo)
|
||||||
language = strings.ReplaceAll(language, editor.Caret, "")
|
language = strings.ReplaceAll(language, editor.Caret, "")
|
||||||
return render.NoHighlight(language)
|
return render.NoHighlight(language)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,40 +52,6 @@ func ShortPathForBootingDisplay(p string) string {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsIDPattern(str string) bool {
|
|
||||||
if len("20060102150405-1a2b3c4") != len(str) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if 1 != strings.Count(str, "-") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
parts := strings.Split(str, "-")
|
|
||||||
idPart := parts[0]
|
|
||||||
if 14 != len(idPart) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range idPart {
|
|
||||||
if !('0' <= c && '9' >= c) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
randPart := parts[1]
|
|
||||||
if 7 != len(randPart) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range randPart {
|
|
||||||
if !('a' <= c && 'z' >= c) && !('0' <= c && '9' >= c) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var LocalIPs []string
|
var LocalIPs []string
|
||||||
|
|
||||||
func GetLocalIPs() (ret []string) {
|
func GetLocalIPs() (ret []string) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue