diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index 5034676b3..8956b3bc0 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -265,10 +265,6 @@ "vLayout": "Vertical layout", "hLayout": "Horizontal layout", "merge": "Merge", - "docWordCount": "Document words", - "blockWordCount": "Block words", - "docRuneCount": "Document characters", - "blockRuneCount": "Block characters", "wordCount": "Words", "runeCount": "Characters", "kbd": "Keyboard", @@ -733,6 +729,8 @@ "italic": "Italic", "line": "Divider", "link": "Link", + "image": "Image", + "ref": "Ref", "list": "List", "more": "More", "nameEmpty": "Name is empty", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 4d1444037..e35c4391b 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -265,10 +265,6 @@ "vLayout": "Diseño vertical", "hLayout": "Diseño horizontal", "merge": "Fusionar", - "docWordCount": "Palabras del documento", - "blockWordCount": "Palabras del bloque", - "docRuneCount": "Caracteres del documento", - "blockRuneCount": "Caracteres del bloque", "wordCount": "Palabras", "runeCount": "Caracteres", "kbd": "Teclado", @@ -733,6 +729,8 @@ "italic": "Cursiva", "line": "Divisor", "link": "Enlace", + "imagen": "Imagen", + "ref": "Ref", "list": "Lista", "more": "Más", "nameEmpty": "El nombre está vacío", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index dff3879b1..09b727c6e 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -265,10 +265,6 @@ "vLayout": "Disposition verticale", "hLayout": "Horizontal horizontale", "merge": "Merge", - "docWordCount": "Document words", - "blockWordCount": "Mots de bloc", - "docRuneCount": "Caractères des documents", - "blockRuneCount": "Caractères de bloc", "wordCount": "Mots", "runeCount": "Caractères", "kbd": "Clavier", @@ -733,6 +729,8 @@ "italic": "Italique", "line": "Diviseur", "link": "Lien", + "image": "Image", + "ref": "Réf", "list": "Liste", "more": "Plus", "nameEmpty": "Nom est vide", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index b75cfdb39..3fcf3c6fc 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -265,10 +265,6 @@ "vLayout": "垂直佈局", "hLayout": "水平佈局", "merge": "合併", - "docWordCount": "文檔詞數", - "blockWordCount": " 塊詞數", - "docRuneCount": "文檔字數", - "blockRuneCount": " 塊字數", "wordCount": "詞數", "runeCount": "字數", "kbd": "鍵盤", @@ -733,6 +729,8 @@ "italic": "斜體", "line": "分隔線", "link": "連結", + "image": "圖片", + "ref": "引用", "list": "無序列表", "more": "更多", "nameEmpty": "檔案名不能為空", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index b72e943ec..f0ab779f8 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -265,10 +265,6 @@ "vLayout": "垂直布局", "hLayout": "水平布局", "merge": "合并", - "docWordCount": "文档词数", - "blockWordCount": " 块词数", - "docRuneCount": "文档字数", - "blockRuneCount": " 块字数", "wordCount": "词数", "runeCount": "字数", "kbd": "键盘", @@ -733,6 +729,8 @@ "italic": "斜体", "line": "分隔线", "link": "链接", + "image": "图片", + "ref": "引用", "list": "无序列表", "more": "更多", "nameEmpty": "文件名不能为空", diff --git a/app/src/dialog/processSystem.ts b/app/src/dialog/processSystem.ts index df17cd3d8..2462d557e 100644 --- a/app/src/dialog/processSystem.ts +++ b/app/src/dialog/processSystem.ts @@ -189,7 +189,7 @@ export const progressStatus = (data: IWebSocketData) => { }; export const handleStatusbarCounter = (data: IWebSocketData) => { - renderStatusbarCounter(data.data.runeCount, data.data.wordCount); + renderStatusbarCounter(data.data); }; export const progressLoading = (data: IWebSocketData) => { diff --git a/app/src/layout/status.ts b/app/src/layout/status.ts index dd783b140..a9b656e5a 100644 --- a/app/src/layout/status.ts +++ b/app/src/layout/status.ts @@ -137,7 +137,7 @@ export const countSelectWord = (range: Range) => { const selectText = range.toString(); if (selectText) { fetchPost("/api/block/getContentWordCount", {"content": range.toString()}, (response) => { - renderStatusbarCounter(response.data.runeCount, response.data.wordCount); + renderStatusbarCounter(response.data); }); } else { document.querySelector("#status .status__counter").innerHTML = ""; @@ -152,7 +152,7 @@ export const countBlockWord = (ids: string[]) => { } if (ids.length > 0) { fetchPost("/api/block/getBlocksWordCount", {ids}, (response) => { - renderStatusbarCounter(response.data.runeCount, response.data.wordCount); + renderStatusbarCounter(response.data); }); } else { document.querySelector("#status .status__counter").innerHTML = ""; @@ -160,10 +160,17 @@ export const countBlockWord = (ids: string[]) => { /// #endif }; -export const renderStatusbarCounter = (runeCount: number, wordCount: number) => { - document.querySelector("#status .status__counter").innerHTML = `${window.siyuan.languages.runeCount} - ${runeCount} - -${window.siyuan.languages.wordCount} - ${wordCount}`; +export const renderStatusbarCounter = (stat: { runeCount: number, wordCount: number, linkCount: number, imageCount: number, refCount: number }) => { + let html = `${window.siyuan.languages.runeCount} ${stat.runeCount} +${window.siyuan.languages.wordCount} ${stat.wordCount}` + if (0 < stat.linkCount) { + html += `${window.siyuan.languages.link} ${stat.linkCount}` + } + if (0 < stat.imageCount) { + html += `${window.siyuan.languages.image} ${stat.imageCount}` + } + if (0 < stat.refCount) { + html += `${window.siyuan.languages.ref} ${stat.refCount}` + } + document.querySelector("#status .status__counter").innerHTML = html; } diff --git a/app/src/protyle/breadcrumb/index.ts b/app/src/protyle/breadcrumb/index.ts index 881504f42..6d3036088 100644 --- a/app/src/protyle/breadcrumb/index.ts +++ b/app/src/protyle/breadcrumb/index.ts @@ -135,7 +135,7 @@ export class Breadcrumb { if (cursorNodeElement) { id = cursorNodeElement.getAttribute("data-node-id"); } - fetchPost("/api/block/getBlockWordCount", {id: id || protyle.block.id}, (response) => { + fetchPost("/api/block/getTreeStat", {id: id || protyle.block.id}, (response) => { window.siyuan.menus.menu.remove(); if (!protyle.contentElement.classList.contains("fn__none")) { @@ -327,10 +327,11 @@ export class Breadcrumb { window.siyuan.menus.menu.append(new MenuItem({type: "separator"}).element); window.siyuan.menus.menu.append(new MenuItem({ type: "readonly", - label: `
${window.siyuan.languages.docRuneCount}${response.data.rootBlockRuneCount}
-
${window.siyuan.languages.docWordCount}${response.data.rootBlockWordCount}
-
${window.siyuan.languages.blockRuneCount}${response.data.blockRuneCount}
-
${window.siyuan.languages.blockWordCount}${response.data.blockWordCount}
`, + label: `
${window.siyuan.languages.runeCount}${response.data.runeCount}
+
${window.siyuan.languages.wordCount}${response.data.wordCount}
+
${window.siyuan.languages.link}${response.data.linkCount}
+
${window.siyuan.languages.image}${response.data.imageCount}
+
${window.siyuan.languages.ref}${response.data.refCount}
`, }).element); window.siyuan.menus.menu.popup(position); }); diff --git a/kernel/api/block.go b/kernel/api/block.go index 1c494d7cb..5111d2a5f 100644 --- a/kernel/api/block.go +++ b/kernel/api/block.go @@ -157,11 +157,7 @@ func getContentWordCount(c *gin.Context) { } content := arg["content"].(string) - runeCount, wordCount := model.ContentWordCount(content) - ret.Data = map[string]interface{}{ - "runeCount": runeCount, - "wordCount": wordCount, - } + ret.Data = model.ContentStat(content) } func getBlocksWordCount(c *gin.Context) { @@ -178,14 +174,10 @@ func getBlocksWordCount(c *gin.Context) { for _, id := range idsArg { ids = append(ids, id.(string)) } - runeCount, wordCount := model.BlocksWordCount(ids) - ret.Data = map[string]interface{}{ - "runeCount": runeCount, - "wordCount": wordCount, - } + ret.Data = model.BlocksWordCount(ids) } -func getBlockWordCount(c *gin.Context) { +func getTreeStat(c *gin.Context) { ret := gulu.Ret.NewResult() defer c.JSON(http.StatusOK, ret) @@ -195,13 +187,7 @@ func getBlockWordCount(c *gin.Context) { } id := arg["id"].(string) - blockRuneCount, blockWordCount, rootBlockRuneCount, rootBlockWordCount := model.BlockWordCount(id) - ret.Data = map[string]interface{}{ - "blockRuneCount": blockRuneCount, - "blockWordCount": blockWordCount, - "rootBlockRuneCount": rootBlockRuneCount, - "rootBlockWordCount": rootBlockWordCount, - } + ret.Data = model.StatTree(id) } func getRefText(c *gin.Context) { diff --git a/kernel/api/router.go b/kernel/api/router.go index 7b7b6d9bb..54e4c475a 100644 --- a/kernel/api/router.go +++ b/kernel/api/router.go @@ -134,7 +134,7 @@ func ServeAPI(ginServer *gin.Engine) { ginServer.Handle("POST", "/api/block/getRefIDsByFileAnnotationID", model.CheckAuth, getRefIDsByFileAnnotationID) ginServer.Handle("POST", "/api/block/getBlockDefIDsByRefText", model.CheckAuth, getBlockDefIDsByRefText) ginServer.Handle("POST", "/api/block/getRefText", model.CheckAuth, getRefText) - ginServer.Handle("POST", "/api/block/getBlockWordCount", model.CheckAuth, getBlockWordCount) + ginServer.Handle("POST", "/api/block/getTreeStat", model.CheckAuth, getTreeStat) ginServer.Handle("POST", "/api/block/getBlocksWordCount", model.CheckAuth, getBlocksWordCount) ginServer.Handle("POST", "/api/block/getContentWordCount", model.CheckAuth, getContentWordCount) ginServer.Handle("POST", "/api/block/getRecentUpdatedBlocks", model.CheckAuth, getRecentUpdatedBlocks) diff --git a/kernel/go.mod b/kernel/go.mod index 4938f1ccd..0891bccc2 100644 --- a/kernel/go.mod +++ b/kernel/go.mod @@ -6,7 +6,7 @@ require ( github.com/88250/clipboard v0.1.5 github.com/88250/css v0.1.2 github.com/88250/gulu v1.2.3-0.20220929123404-da1dc91c9343 - github.com/88250/lute v1.7.5-0.20220928025238-bda91cbd4072 + github.com/88250/lute v1.7.5-0.20221001045738-06a8c2407d65 github.com/88250/pdfcpu v0.3.13 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 github.com/ConradIrwin/font v0.0.0-20210318200717-ce8d41cc0732 diff --git a/kernel/go.sum b/kernel/go.sum index 4e85b6c6a..b472f4023 100644 --- a/kernel/go.sum +++ b/kernel/go.sum @@ -19,6 +19,8 @@ github.com/88250/gulu v1.2.3-0.20220929123404-da1dc91c9343 h1:GJxJRZmA8GkAiU3Gsw github.com/88250/gulu v1.2.3-0.20220929123404-da1dc91c9343/go.mod h1:I1qBzsksFL2ciGSuqDE7R3XW4BUMrfDgOvSXEk7FsAI= github.com/88250/lute v1.7.5-0.20220928025238-bda91cbd4072 h1:0d7YXGtw2ybeGs6oClIFiKvTqySfJCu5SUdJJWil6MA= github.com/88250/lute v1.7.5-0.20220928025238-bda91cbd4072/go.mod h1:cEoBGi0zArPqAsp0MdG9SKinvH/xxZZWXU7sRx8vHSA= +github.com/88250/lute v1.7.5-0.20221001045738-06a8c2407d65 h1:EyxFJkB2DXZrAzSaMPZhSs72NzEdsn4YNh/zmqat8IY= +github.com/88250/lute v1.7.5-0.20221001045738-06a8c2407d65/go.mod h1:cEoBGi0zArPqAsp0MdG9SKinvH/xxZZWXU7sRx8vHSA= github.com/88250/pdfcpu v0.3.13 h1:touMWMZkCGalMIbEg9bxYp7rETM+zwb9hXjwhqi4I7Q= github.com/88250/pdfcpu v0.3.13/go.mod h1:S5YT38L/GCjVjmB4PB84PymA1qfopjEhfhTNQilLpv4= github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY= diff --git a/kernel/model/file.go b/kernel/model/file.go index 73786c9d9..8f36679ec 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -387,14 +387,21 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err return } -func ContentWordCount(content string) (runeCount, wordCount int) { +func ContentStat(content string) (ret *util.BlockStatResult) { luteEngine := NewLute() tree := luteEngine.BlockDOM2Tree(content) - runeCount, wordCount = tree.Root.ContentLen() - return + runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat() + return &util.BlockStatResult{ + RuneCount: runeCnt, + WordCount: wordCnt, + LinkCount: linkCnt, + ImageCount: imgCnt, + RefCount: refCnt, + } } -func BlocksWordCount(ids []string) (runeCount, wordCount int) { +func BlocksWordCount(ids []string) (ret *util.BlockStatResult) { + ret = &util.BlockStatResult{} trees := map[string]*parse.Tree{} // 缓存 for _, id := range ids { bt := treenode.GetBlockTree(id) @@ -413,34 +420,30 @@ func BlocksWordCount(ids []string) (runeCount, wordCount int) { } node := treenode.GetNodeInTree(tree, id) - blockRuneCount, blockWordCount := node.ContentLen() - runeCount += blockRuneCount - wordCount += blockWordCount + runeCnt, wordCnt, linkCnt, imgCnt, refCnt := node.Stat() + ret.RuneCount += runeCnt + ret.WordCount += wordCnt + ret.LinkCount += linkCnt + ret.ImageCount += imgCnt + ret.RefCount += refCnt } return } -func BlockWordCount(id string) (blockRuneCount, blockWordCount, rootBlockRuneCount, rootBlockWordCount int) { +func StatTree(id string) (ret *util.BlockStatResult) { tree, _ := loadTreeByBlockID(id) if nil == tree { return } - node := treenode.GetNodeInTree(tree, id) - blockRuneCount, blockWordCount = node.ContentLen() - if ast.NodeHeading == node.Type { - level := node.HeadingLevel - for n := node.Next; nil != n; n = n.Next { - if ast.NodeHeading == n.Type && n.HeadingLevel <= level { - break - } - rc, wc := n.ContentLen() - blockRuneCount += rc - blockWordCount += wc - } + runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat() + return &util.BlockStatResult{ + RuneCount: runeCnt, + WordCount: wordCnt, + LinkCount: linkCnt, + ImageCount: imgCnt, + RefCount: refCnt, } - rootBlockRuneCount, rootBlockWordCount = tree.Root.ContentLen() - return } func GetDoc(startID, endID, id string, index int, keyword string, mode int, size int) (blockCount, childBlockCount int, dom, parentID, parent2ID, rootID, typ string, eof bool, boxID, docPath string, err error) { diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index def28cf2d..70faf8abc 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -1010,8 +1010,8 @@ func (tx *Transaction) commit() (err error) { } func pushTreeStat(tree *parse.Tree) { - runeCount, wordCount := treenode.TreeStat(tree) - util.PushStatusBarCounter(runeCount, wordCount) + stat := treenode.StatTree(tree) + util.PushStatusBarCounter(stat) } func (tx *Transaction) rollback() { diff --git a/kernel/treenode/tree.go b/kernel/treenode/tree.go index f102ff43e..22f9ba950 100644 --- a/kernel/treenode/tree.go +++ b/kernel/treenode/tree.go @@ -31,9 +31,15 @@ import ( "github.com/siyuan-note/siyuan/kernel/util" ) -func TreeStat(tree *parse.Tree) (runeCount, wordCount int) { - runeCount, wordCount = tree.Root.ContentLen() - return +func StatTree(tree *parse.Tree) (ret *util.BlockStatResult) { + runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat() + return &util.BlockStatResult{ + RuneCount: runeCnt, + WordCount: wordCnt, + LinkCount: linkCnt, + ImageCount: imgCnt, + RefCount: refCnt, + } } func NodeHash(node *ast.Node, tree *parse.Tree, luteEngine *lute.Lute) string { diff --git a/kernel/util/websocket.go b/kernel/util/websocket.go index b290db176..2d8c7db46 100644 --- a/kernel/util/websocket.go +++ b/kernel/util/websocket.go @@ -151,11 +151,16 @@ func PushStatusBar(msg string) { BroadcastByType("main", "statusbar", 0, msg, nil) } -func PushStatusBarCounter(runeCount, wordCount int) { - BroadcastByType("main", "statusbarCounter", 0, "", map[string]interface{}{ - "runeCount": runeCount, - "wordCount": wordCount}, - ) +type BlockStatResult struct { + RuneCount int `json:"runeCount"` + WordCount int `json:"wordCount"` + LinkCount int `json:"linkCount"` + ImageCount int `json:"imageCount"` + RefCount int `json:"refCount"` +} + +func PushStatusBarCounter(stat *BlockStatResult) { + BroadcastByType("main", "statusbarCounter", 0, "", stat) } func ContextPushMsg(context map[string]interface{}, msg string) {