Something went wrong. Try again.
A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. (PERSONAL FORK)
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225// SiYuan - Refactor your thinking// Copyright (c) 2020-present, b3log.org//// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with this program. If not, see <https://www.gnu.org/licenses/>.
package filesys
import ( "bytes"
"github.com/88250/lute" "github.com/88250/lute/ast" "github.com/88250/lute/parse" "github.com/siyuan-note/siyuan/kernel/av" "github.com/siyuan-note/siyuan/kernel/treenode" "github.com/siyuan-note/siyuan/kernel/util")
func ContentStat(content string) (ret *util.BlockStatResult) { luteEngine := util.NewLute() return contentStat(content, luteEngine)}
func contentStat(content string, luteEngine *lute.Lute) (ret *util.BlockStatResult) { tree := luteEngine.BlockDOM2Tree(content) runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat() return &util.BlockStatResult{ RuneCount: runeCnt, WordCount: wordCnt, LinkCount: linkCnt, ImageCount: imgCnt, RefCount: refCnt, }}
func StatBlock(id string) (ret *util.BlockStatResult) { trees := LoadTrees([]string{id}) if 1 > len(trees) { return }
tree := trees[id] if nil == tree { return }
node := treenode.GetNodeInTree(tree, id) if nil == node { return }
if ast.NodeDocument == node.Type { return statTree(tree) }
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := node.Stat() ret = &util.BlockStatResult{ runeCnt, wordCnt, linkCnt, imgCnt, refCnt, 1, } return}
func StatTree(id string) (ret *util.BlockStatResult) { trees := LoadTrees([]string{id}) if 1 > len(trees) { return }
tree := trees[id] if nil == tree { return }
return statTree(tree)}
func statTree(tree *parse.Tree) (ret *util.BlockStatResult) { blockCount := 0 var databaseBlockNodes []*ast.Node ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { if !entering || tree.Root == n { return ast.WalkContinue }
if n.IsBlock() { blockCount++ }
if ast.NodeAttributeView != n.Type { return ast.WalkContinue }
databaseBlockNodes = append(databaseBlockNodes, n) return ast.WalkContinue })
luteEngine := util.NewLute() var dbRuneCnt, dbWordCnt, dbLinkCnt, dbImgCnt, dbRefCnt int for _, n := range databaseBlockNodes { if "" == n.AttributeViewID { continue }
attrView, _ := av.ParseAttributeView(n.AttributeViewID) if nil == attrView { continue }
content := bytes.Buffer{} for _, kValues := range attrView.KeyValues { for _, v := range kValues.Values { switch kValues.Key.Type { case av.KeyTypeURL: if v.IsBlank() { continue }
dbLinkCnt++ content.WriteString(v.URL.Content) case av.KeyTypeMAsset: if v.IsBlank() { continue }
for _, asset := range v.MAsset { if av.AssetTypeImage == asset.Type { dbImgCnt++ } } case av.KeyTypeBlock: if v.IsBlank() { continue }
if !v.IsDetached { dbRefCnt++ } content.WriteString(v.Block.Content) case av.KeyTypeText: if v.IsBlank() { continue } content.WriteString(v.Text.Content) case av.KeyTypeNumber: if v.IsBlank() { continue } v.Number.FormatNumber() content.WriteString(v.Number.FormattedContent) case av.KeyTypeEmail: if v.IsBlank() { continue } content.WriteString(v.Email.Content) case av.KeyTypePhone: if v.IsBlank() { continue } content.WriteString(v.Phone.Content) } } }
dbStat := contentStat(content.String(), luteEngine) dbRuneCnt += dbStat.RuneCount dbWordCnt += dbStat.WordCount }
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat() runeCnt += dbRuneCnt wordCnt += dbWordCnt linkCnt += dbLinkCnt imgCnt += dbImgCnt refCnt += dbRefCnt return &util.BlockStatResult{ RuneCount: runeCnt, WordCount: wordCnt, LinkCount: linkCnt, ImageCount: imgCnt, RefCount: refCnt, BlockCount: blockCount, }}
func BlocksWordCount(ids []string) (ret *util.BlockStatResult) { ret = &util.BlockStatResult{} trees := LoadTrees(ids) for _, id := range ids { tree := trees[id] if nil == tree { continue }
node := treenode.GetNodeInTree(tree, id) if nil == node { continue }
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := node.Stat() ret.RuneCount += runeCnt ret.WordCount += wordCnt ret.LinkCount += linkCnt ret.ImageCount += imgCnt ret.RefCount += refCnt } ret.BlockCount = len(ids) return}