export_merge.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // SiYuan - Build Your Eternal Digital Garden
  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. )
  21. func mergeSubDocs(rootTree *parse.Tree) (ret *parse.Tree, err error) {
  22. ret = rootTree
  23. rootBlock := &Block{Box: rootTree.Box, ID: rootTree.ID, Path: rootTree.Path}
  24. if err = buildBlockChildren(rootBlock); nil != err {
  25. return
  26. }
  27. insertPoint := rootTree.Root.LastChild
  28. for {
  29. i := 0
  30. if err = walkBlock(insertPoint, rootBlock, i); nil != err {
  31. return
  32. }
  33. if nil == rootBlock.Children {
  34. break
  35. }
  36. }
  37. return
  38. }
  39. func walkBlock(insertPoint *ast.Node, block *Block, level int) (err error) {
  40. level++
  41. for _, c := range block.Children {
  42. if err = walkBlock(insertPoint, c, level); nil != err {
  43. return
  44. }
  45. }
  46. for _, c := range block.Children {
  47. nodes, loadErr := loadTreeNodes(c.Box, c.Path, level)
  48. if nil != loadErr {
  49. return
  50. }
  51. for j := len(nodes) - 1; -1 < j; j-- {
  52. insertPoint.InsertAfter(nodes[j])
  53. }
  54. }
  55. block.Children = nil
  56. return
  57. }
  58. func loadTreeNodes(box string, p string, level int) (ret []*ast.Node, err error) {
  59. tree, err := LoadTree(box, p)
  60. if nil != err {
  61. return
  62. }
  63. hLevel := level
  64. if 6 < level {
  65. hLevel = 6
  66. }
  67. heading := &ast.Node{Type: ast.NodeHeading, HeadingLevel: hLevel}
  68. heading.AppendChild(&ast.Node{Type: ast.NodeText, Tokens: []byte(tree.Root.IALAttr("title"))})
  69. tree.Root.PrependChild(heading)
  70. for c := tree.Root.FirstChild; nil != c; c = c.Next {
  71. ret = append(ret, c)
  72. }
  73. return
  74. }
  75. func buildBlockChildren(block *Block) (err error) {
  76. files, _, err := ListDocTree(block.Box, block.Path, Conf.FileTree.Sort)
  77. if nil != err {
  78. return
  79. }
  80. for _, f := range files {
  81. childBlock := &Block{Box: block.Box, ID: f.ID, Path: f.Path}
  82. block.Children = append(block.Children, childBlock)
  83. }
  84. for _, c := range block.Children {
  85. if err = buildBlockChildren(c); nil != err {
  86. return
  87. }
  88. }
  89. return
  90. }