tree.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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 treenode
  17. import (
  18. "crypto/sha256"
  19. "fmt"
  20. "io/fs"
  21. "path"
  22. "path/filepath"
  23. "sort"
  24. "strings"
  25. "github.com/88250/gulu"
  26. "github.com/88250/lute"
  27. "github.com/88250/lute/ast"
  28. "github.com/88250/lute/parse"
  29. "github.com/siyuan-note/filelock"
  30. "github.com/siyuan-note/siyuan/kernel/util"
  31. )
  32. func NodeHash(node *ast.Node, tree *parse.Tree, luteEngine *lute.Lute) string {
  33. ialArray := node.KramdownIAL
  34. sort.Slice(ialArray, func(i, j int) bool {
  35. return ialArray[i][0] < ialArray[j][0]
  36. })
  37. ial := parse.IAL2Tokens(ialArray)
  38. var md string
  39. if ast.NodeDocument != node.Type {
  40. md = FormatNode(node, luteEngine)
  41. }
  42. hpath := tree.HPath
  43. data := tree.Box + tree.Path + hpath + string(ial) + md
  44. return fmt.Sprintf("%x", sha256.Sum256(gulu.Str.ToBytes(data)))[:7]
  45. }
  46. func TreeRoot(node *ast.Node) *ast.Node {
  47. for p := node; nil != p; p = p.Parent {
  48. if ast.NodeDocument == p.Type {
  49. return p
  50. }
  51. }
  52. return &ast.Node{Type: ast.NodeDocument}
  53. }
  54. func NewTree(boxID, p, hp, title string) *parse.Tree {
  55. id := strings.TrimSuffix(path.Base(p), ".sy")
  56. root := &ast.Node{Type: ast.NodeDocument, ID: id, Spec: "1", Box: boxID, Path: p}
  57. root.SetIALAttr("title", title)
  58. root.SetIALAttr("id", id)
  59. root.SetIALAttr("updated", util.TimeFromID(id))
  60. ret := &parse.Tree{Root: root, ID: id, Box: boxID, Path: p, HPath: hp}
  61. ret.Root.Spec = "1"
  62. newPara := &ast.Node{Type: ast.NodeParagraph, ID: ast.NewNodeID(), Box: boxID, Path: p}
  63. newPara.SetIALAttr("id", newPara.ID)
  64. newPara.SetIALAttr("updated", util.TimeFromID(newPara.ID))
  65. ret.Root.AppendChild(newPara)
  66. return ret
  67. }
  68. func IALStr(n *ast.Node) string {
  69. if 1 > len(n.KramdownIAL) {
  70. return ""
  71. }
  72. // 这里不能进行转义,否则会导致从数据库中读取后转换为 IAL 时解析错误
  73. // 所以 Some symbols should not be escaped to avoid inaccurate searches https://github.com/siyuan-note/siyuan/issues/10185 无法被修复了
  74. return string(parse.IAL2Tokens(n.KramdownIAL))
  75. }
  76. func RootChildIDs(rootID string) (ret []string) {
  77. root := GetBlockTree(rootID)
  78. if nil == root {
  79. return
  80. }
  81. ret = append(ret, rootID)
  82. boxLocalPath := filepath.Join(util.DataDir, root.BoxID)
  83. subFolder := filepath.Join(boxLocalPath, strings.TrimSuffix(root.Path, ".sy"))
  84. if !gulu.File.IsDir(subFolder) {
  85. return
  86. }
  87. filelock.Walk(subFolder, func(path string, info fs.FileInfo, err error) error {
  88. if strings.HasSuffix(path, ".sy") {
  89. name := filepath.Base(path)
  90. id := strings.TrimSuffix(name, ".sy")
  91. ret = append(ret, id)
  92. }
  93. return nil
  94. })
  95. return
  96. }
  97. func NewParagraph() (ret *ast.Node) {
  98. newID := ast.NewNodeID()
  99. ret = &ast.Node{ID: newID, Type: ast.NodeParagraph}
  100. ret.SetIALAttr("id", newID)
  101. ret.SetIALAttr("updated", newID[:14])
  102. return
  103. }