mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-19 16:10:12 +01:00
🎨 Improve embed blocks exporting https://github.com/siyuan-note/siyuan/issues/11725
This commit is contained in:
parent
011fcbf1c2
commit
2589b009eb
2 changed files with 78 additions and 68 deletions
|
|
@ -1932,62 +1932,9 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold bool,
|
||||||
luteEngine := NewLute()
|
luteEngine := NewLute()
|
||||||
ret = tree
|
ret = tree
|
||||||
id := tree.Root.ID
|
id := tree.Root.ID
|
||||||
var unlinks []*ast.Node
|
|
||||||
|
|
||||||
// 解析查询嵌入节点
|
// 解析查询嵌入节点
|
||||||
ast.Walk(ret.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
resolveEmbedR(ret.Root, blockEmbedMode, luteEngine, &[]string{})
|
||||||
if !entering || ast.NodeBlockQueryEmbed != n.Type {
|
|
||||||
return ast.WalkContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
var defMd string
|
|
||||||
stmt := n.ChildByType(ast.NodeBlockQueryEmbedScript).TokensStr()
|
|
||||||
stmt = html.UnescapeString(stmt)
|
|
||||||
stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
|
|
||||||
embedBlocks := searchEmbedBlock(n.ID, stmt, nil, 0, false)
|
|
||||||
if 1 > len(embedBlocks) {
|
|
||||||
return ast.WalkContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
defMdBuf := bytes.Buffer{}
|
|
||||||
for _, def := range embedBlocks {
|
|
||||||
defMdBuf.WriteString(renderBlockMarkdownR(def.Block.ID))
|
|
||||||
defMdBuf.WriteString("\n\n")
|
|
||||||
}
|
|
||||||
defMd = defMdBuf.String()
|
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
|
||||||
lines := strings.Split(defMd, "\n")
|
|
||||||
for i, line := range lines {
|
|
||||||
if 0 == blockEmbedMode { // 原始文本
|
|
||||||
buf.WriteString(line)
|
|
||||||
} else { // Blockquote
|
|
||||||
buf.WriteString("> " + line)
|
|
||||||
}
|
|
||||||
if i < len(lines)-1 {
|
|
||||||
buf.WriteString("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf.WriteString("\n\n")
|
|
||||||
|
|
||||||
refTree := parse.Parse("", buf.Bytes(), luteEngine.ParseOptions)
|
|
||||||
var children []*ast.Node
|
|
||||||
for c := refTree.Root.FirstChild; nil != c; c = c.Next {
|
|
||||||
children = append(children, c)
|
|
||||||
}
|
|
||||||
for _, c := range children {
|
|
||||||
if ast.NodeDocument == c.Type {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
n.InsertBefore(c)
|
|
||||||
}
|
|
||||||
unlinks = append(unlinks, n)
|
|
||||||
return ast.WalkSkipChildren
|
|
||||||
})
|
|
||||||
for _, n := range unlinks {
|
|
||||||
n.Unlink()
|
|
||||||
}
|
|
||||||
unlinks = nil
|
|
||||||
|
|
||||||
// 收集引用转脚注
|
// 收集引用转脚注
|
||||||
var refFootnotes []*refAsFootnotes
|
var refFootnotes []*refAsFootnotes
|
||||||
|
|
@ -1998,6 +1945,7 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold bool,
|
||||||
collectFootnotesDefs(ret.ID, &refFootnotes, &treeCache, &depth)
|
collectFootnotesDefs(ret.ID, &refFootnotes, &treeCache, &depth)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var unlinks []*ast.Node
|
||||||
ast.Walk(ret.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
ast.Walk(ret.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||||
if !entering {
|
if !entering {
|
||||||
return ast.WalkContinue
|
return ast.WalkContinue
|
||||||
|
|
@ -2393,7 +2341,7 @@ func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, rootID string, blockR
|
||||||
stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
|
stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
|
||||||
sqlBlocks := sql.SelectBlocksRawStmt(stmt, 1, Conf.Search.Limit)
|
sqlBlocks := sql.SelectBlocksRawStmt(stmt, 1, Conf.Search.Limit)
|
||||||
for _, b := range sqlBlocks {
|
for _, b := range sqlBlocks {
|
||||||
subNodes := renderBlockMarkdownR0(b.ID, &rendered)
|
subNodes := renderBlockMarkdownR(b.ID, &rendered)
|
||||||
for _, subNode := range subNodes {
|
for _, subNode := range subNodes {
|
||||||
if ast.NodeListItem == subNode.Type {
|
if ast.NodeListItem == subNode.Type {
|
||||||
parentList := &ast.Node{Type: ast.NodeList, ListData: &ast.ListData{Typ: subNode.ListData.Typ}}
|
parentList := &ast.Node{Type: ast.NodeList, ListData: &ast.ListData{Typ: subNode.ListData.Typ}}
|
||||||
|
|
|
||||||
|
|
@ -165,21 +165,83 @@ func renderBlockContentByNodes(nodes []*ast.Node) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderBlockMarkdownR(id string) string {
|
func resolveEmbedR(n *ast.Node, blockEmbedMode int, luteEngine *lute.Lute, resolved *[]string) {
|
||||||
var rendered []string
|
var children []*ast.Node
|
||||||
nodes := renderBlockMarkdownR0(id, &rendered)
|
if ast.NodeHeading == n.Type {
|
||||||
buf := bytes.Buffer{}
|
children = append(children, n)
|
||||||
buf.Grow(4096)
|
children = append(children, treenode.HeadingChildren(n)...)
|
||||||
luteEngine := NewLute()
|
} else if ast.NodeDocument == n.Type {
|
||||||
for _, n := range nodes {
|
for c := n.FirstChild; nil != c; c = c.Next {
|
||||||
md := treenode.FormatNode(n, luteEngine)
|
children = append(children, c)
|
||||||
buf.WriteString(md)
|
|
||||||
buf.WriteString("\n\n")
|
|
||||||
}
|
}
|
||||||
return buf.String()
|
} else {
|
||||||
|
children = append(children, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderBlockMarkdownR0(id string, rendered *[]string) (ret []*ast.Node) {
|
for _, child := range children {
|
||||||
|
var unlinks []*ast.Node
|
||||||
|
ast.Walk(child, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||||
|
if !entering || !n.IsBlock() {
|
||||||
|
return ast.WalkContinue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ast.NodeBlockQueryEmbed == n.Type {
|
||||||
|
if gulu.Str.Contains(n.ID, *resolved) {
|
||||||
|
return ast.WalkContinue
|
||||||
|
}
|
||||||
|
*resolved = append(*resolved, n.ID)
|
||||||
|
|
||||||
|
stmt := n.ChildByType(ast.NodeBlockQueryEmbedScript).TokensStr()
|
||||||
|
stmt = html.UnescapeString(stmt)
|
||||||
|
stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
|
||||||
|
sqlBlocks := sql.SelectBlocksRawStmt(stmt, 1, Conf.Search.Limit)
|
||||||
|
for _, sqlBlock := range sqlBlocks {
|
||||||
|
md := sqlBlock.Markdown
|
||||||
|
|
||||||
|
if "d" == sqlBlock.Type {
|
||||||
|
subTree, _ := LoadTreeByBlockID(sqlBlock.ID)
|
||||||
|
md, _ = lute.FormatNodeSync(subTree.Root, luteEngine.ParseOptions, luteEngine.RenderOptions)
|
||||||
|
} // 标题块不需要再单独解析,直接使用 Markdown,函数开头处会处理
|
||||||
|
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
lines := strings.Split(md, "\n")
|
||||||
|
for i, line := range lines {
|
||||||
|
if 0 == blockEmbedMode { // 使用原始文本
|
||||||
|
buf.WriteString(line)
|
||||||
|
} else { // 使用引述块
|
||||||
|
buf.WriteString("> " + line)
|
||||||
|
}
|
||||||
|
if i < len(lines)-1 {
|
||||||
|
buf.WriteString("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.WriteString("\n\n")
|
||||||
|
|
||||||
|
subTree := parse.Parse("", buf.Bytes(), luteEngine.ParseOptions)
|
||||||
|
var inserts []*ast.Node
|
||||||
|
for subNode := subTree.Root.FirstChild; nil != subNode; subNode = subNode.Next {
|
||||||
|
if ast.NodeKramdownBlockIAL != subNode.Type {
|
||||||
|
inserts = append(inserts, subNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, insert := range inserts {
|
||||||
|
n.InsertBefore(insert)
|
||||||
|
resolveEmbedR(insert, blockEmbedMode, luteEngine, resolved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlinks = append(unlinks, n)
|
||||||
|
return ast.WalkSkipChildren
|
||||||
|
}
|
||||||
|
return ast.WalkContinue
|
||||||
|
})
|
||||||
|
for _, unlink := range unlinks {
|
||||||
|
unlink.Unlink()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderBlockMarkdownR(id string, rendered *[]string) (ret []*ast.Node) {
|
||||||
if gulu.Str.Contains(id, *rendered) {
|
if gulu.Str.Contains(id, *rendered) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +287,7 @@ func renderBlockMarkdownR0(id string, rendered *[]string) (ret []*ast.Node) {
|
||||||
stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
|
stmt = strings.ReplaceAll(stmt, editor.IALValEscNewLine, "\n")
|
||||||
sqlBlocks := sql.SelectBlocksRawStmt(stmt, 1, Conf.Search.Limit)
|
sqlBlocks := sql.SelectBlocksRawStmt(stmt, 1, Conf.Search.Limit)
|
||||||
for _, sqlBlock := range sqlBlocks {
|
for _, sqlBlock := range sqlBlocks {
|
||||||
subNodes := renderBlockMarkdownR0(sqlBlock.ID, rendered)
|
subNodes := renderBlockMarkdownR(sqlBlock.ID, rendered)
|
||||||
for _, subNode := range subNodes {
|
for _, subNode := range subNodes {
|
||||||
inserts = append(inserts, subNode)
|
inserts = append(inserts, subNode)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue