export_merge.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SiYuan - Refactor your thinking
  2. // Copyright (c) 2020-present, b3log.org
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. package model
  17. import (
  18. "github.com/88250/lute/ast"
  19. "github.com/88250/lute/parse"
  20. "github.com/siyuan-note/siyuan/kernel/filesys"
  21. "github.com/siyuan-note/siyuan/kernel/treenode"
  22. "github.com/siyuan-note/siyuan/kernel/util"
  23. )
  24. func mergeSubDocs(rootTree *parse.Tree) (ret *parse.Tree, err error) {
  25. ret = rootTree
  26. rootBlock := &Block{Box: rootTree.Box, ID: rootTree.ID, Path: rootTree.Path, HPath: rootTree.HPath}
  27. if err = buildBlockChildren(rootBlock); nil != err {
  28. return
  29. }
  30. insertPoint := rootTree.Root.LastChild
  31. // 跳过空段落插入点,向上寻找非空段落
  32. for ; nil != insertPoint && ast.NodeParagraph == insertPoint.Type; insertPoint = insertPoint.Previous {
  33. if nil != insertPoint.FirstChild {
  34. break
  35. }
  36. }
  37. // 导出空文档 Word 和 PDF 时合并子文档失败 https://github.com/siyuan-note/siyuan/issues/7429
  38. if nil == insertPoint {
  39. // 如果找不到非空段落,则使用第一个段落作为插入点
  40. insertPoint = rootTree.Root.FirstChild
  41. if nil == insertPoint {
  42. // 如果文档为空,则创建一个空段落作为插入点
  43. insertPoint = treenode.NewParagraph()
  44. rootTree.Root.AppendChild(insertPoint)
  45. }
  46. }
  47. for {
  48. i := 0
  49. if err = walkBlock(insertPoint, rootBlock, i); nil != err {
  50. return
  51. }
  52. if nil == rootBlock.Children {
  53. break
  54. }
  55. }
  56. return
  57. }
  58. func walkBlock(insertPoint *ast.Node, block *Block, level int) (err error) {
  59. level++
  60. for i := len(block.Children) - 1; i >= 0; i-- {
  61. c := block.Children[i]
  62. if err = walkBlock(insertPoint, c, level); nil != err {
  63. return
  64. }
  65. nodes, loadErr := loadTreeNodes(c.Box, c.Path, level)
  66. if nil != loadErr {
  67. return
  68. }
  69. for j := len(nodes) - 1; -1 < j; j-- {
  70. insertPoint.InsertAfter(nodes[j])
  71. }
  72. }
  73. block.Children = nil
  74. return
  75. }
  76. func loadTreeNodes(box string, p string, level int) (ret []*ast.Node, err error) {
  77. luteEngine := NewLute()
  78. tree, err := filesys.LoadTree(box, p, luteEngine)
  79. if nil != err {
  80. return
  81. }
  82. hLevel := level
  83. if 6 < level {
  84. hLevel = 6
  85. }
  86. heading := &ast.Node{ID: tree.Root.ID, Type: ast.NodeHeading, HeadingLevel: hLevel}
  87. heading.AppendChild(&ast.Node{Type: ast.NodeText, Tokens: []byte(tree.Root.IALAttr("title"))})
  88. tree.Root.PrependChild(heading)
  89. for c := tree.Root.FirstChild; nil != c; c = c.Next {
  90. if ast.NodeParagraph == c.Type && nil == c.FirstChild {
  91. // 剔除空段落
  92. continue
  93. }
  94. ret = append(ret, c)
  95. }
  96. return
  97. }
  98. func buildBlockChildren(block *Block) (err error) {
  99. files, _, err := ListDocTree(block.Box, block.Path, util.SortModeUnassigned, false, false, Conf.FileTree.MaxListCount)
  100. if nil != err {
  101. return
  102. }
  103. for _, f := range files {
  104. childBlock := &Block{Box: block.Box, ID: f.ID, Path: f.Path}
  105. block.Children = append(block.Children, childBlock)
  106. }
  107. for _, c := range block.Children {
  108. if err = buildBlockChildren(c); nil != err {
  109. return
  110. }
  111. }
  112. return
  113. }