Explorar el Código

:art: 行级元素支持嵌套和交叉 https://github.com/siyuan-note/siyuan/issues/2911

Liang Ding hace 2 años
padre
commit
a8bc7a0575
Se han modificado 3 ficheros con 94 adiciones y 1 borrados
  1. 3 1
      kernel/model/file.go
  2. 2 0
      kernel/model/import.go
  3. 89 0
      kernel/treenode/node.go

+ 3 - 1
kernel/model/file.go

@@ -614,7 +614,7 @@ func GetDoc(startID, endID, id string, index int, keyword string, mode int, size
 		}
 	}
 
-	subTree := &parse.Tree{Root: &ast.Node{Type: ast.NodeDocument}, Marks: tree.Marks}
+	subTree := &parse.Tree{ID: rootID, Root: &ast.Node{Type: ast.NodeDocument}, Marks: tree.Marks}
 	keyword = strings.Join(strings.Split(keyword, " "), search.TermSep)
 	keywords := search.SplitKeyword(keyword)
 
@@ -728,6 +728,8 @@ func GetDoc(startID, endID, id string, index int, keyword string, mode int, size
 		subTree.Root.AppendChild(n)
 	}
 
+	treenode.NestedInlines2FlattedSpans(subTree)
+
 	luteEngine.RenderOptions.NodeIndexStart = index
 	dom = luteEngine.Tree2BlockDOM(subTree, luteEngine.RenderOptions)
 	return

+ 2 - 0
kernel/model/import.go

@@ -451,6 +451,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 			tree.Path = targetPath
 			targetPaths[curRelPath] = targetPath
 			tree.HPath = hPath
+			treenode.NestedInlines2FlattedSpans(tree)
 
 			docDirLocalPath := filepath.Dir(filepath.Join(boxLocalPath, targetPath))
 			assetDirPath := getAssetsDir(boxLocalPath, docDirLocalPath)
@@ -538,6 +539,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 		tree.Box = boxID
 		tree.Path = targetPath
 		tree.HPath = path.Join(baseHPath, title)
+		treenode.NestedInlines2FlattedSpans(tree)
 
 		docDirLocalPath := filepath.Dir(filepath.Join(boxLocalPath, targetPath))
 		assetDirPath := getAssetsDir(boxLocalPath, docDirLocalPath)

+ 89 - 0
kernel/treenode/node.go

@@ -31,6 +31,95 @@ import (
 	"github.com/siyuan-note/logging"
 )
 
+// NestedInlines2FlattedSpans 将嵌套的行级节点转换为平铺的文本标记节点。
+func NestedInlines2FlattedSpans(tree *parse.Tree) {
+	var tags []string
+	var unlinks []*ast.Node
+	var span *ast.Node
+	ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
+		switch n.Type {
+		case ast.NodeCodeSpan:
+			processNestedNode(n, "code", &tags, &unlinks, entering)
+		case ast.NodeTag:
+			processNestedNode(n, "tag", &tags, &unlinks, entering)
+		case ast.NodeInlineMath:
+			processNestedNode(n, "inline-math", &tags, &unlinks, entering)
+		case ast.NodeEmphasis:
+			processNestedNode(n, "em", &tags, &unlinks, entering)
+		case ast.NodeStrong:
+			processNestedNode(n, "strong", &tags, &unlinks, entering)
+		case ast.NodeStrikethrough:
+			processNestedNode(n, "s", &tags, &unlinks, entering)
+		case ast.NodeMark:
+			processNestedNode(n, "mark", &tags, &unlinks, entering)
+		case ast.NodeUnderline:
+			processNestedNode(n, "u", &tags, &unlinks, entering)
+		case ast.NodeSub:
+			processNestedNode(n, "sub", &tags, &unlinks, entering)
+		case ast.NodeSup:
+			processNestedNode(n, "sup", &tags, &unlinks, entering)
+		case ast.NodeKbd:
+			processNestedNode(n, "kbd", &tags, &unlinks, entering)
+		case ast.NodeLink:
+			processNestedNode(n, "a", &tags, &unlinks, entering)
+		case ast.NodeText, ast.NodeCodeSpanContent, ast.NodeInlineMathContent, ast.NodeLinkText:
+			if 1 > len(tags) {
+				return ast.WalkContinue
+			}
+
+			if entering {
+				span = &ast.Node{Type: ast.NodeTextMark, TextMarkType: strings.Join(tags, " "), TextMarkTextContent: string(n.Tokens)}
+				if ast.NodeInlineMathContent == n.Type {
+					span.TextMarkTextContent = ""
+					span.TextMarkInlineMathContent = string(n.Tokens)
+				}
+				if ast.NodeLinkText == n.Type && !n.ParentIs(ast.NodeImage) {
+					var link *ast.Node
+					for p := n.Parent; nil != p; p = p.Parent {
+						if ast.NodeLink == p.Type {
+							link = p
+							break
+						}
+					}
+					if nil != link {
+						dest := link.ChildByType(ast.NodeLinkDest)
+						if nil != dest {
+							span.TextMarkAHref = string(dest.Tokens)
+						}
+						title := link.ChildByType(ast.NodeLinkTitle)
+						if nil != title {
+							span.TextMarkATitle = string(title.Tokens)
+						}
+					}
+				}
+			} else {
+				n.Parent.InsertBefore(span)
+			}
+		}
+		return ast.WalkContinue
+	})
+
+	for _, n := range unlinks {
+		n.Unlink()
+	}
+}
+
+func processNestedNode(n *ast.Node, tag string, tags *[]string, unlinks *[]*ast.Node, entering bool) {
+	if entering {
+		*tags = append(*tags, tag)
+	} else {
+		*tags = (*tags)[:len(*tags)-1]
+		*unlinks = append(*unlinks, n)
+		for c := n.FirstChild; nil != c; {
+			next := c.Next
+			if ast.NodeTextMark == c.Type {
+				n.InsertBefore(c)
+			}
+			c = next
+		}
+	}
+}
+
 func NodeStaticMdContent(node *ast.Node, luteEngine *lute.Lute) (md, content string) {
 	md = FormatNode(node, luteEngine)
 	content = NodeStaticContent(node)