Browse Source

Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	app/src/util/history.ts
Vanessa 2 years ago
parent
commit
1e671307d8

+ 2 - 1
app/appearance/langs/en_US.json

@@ -1,7 +1,8 @@
 {
+  "docNameAndContent": "Doc Name and Content",
   "breadcrumb": "Breadcrumb",
   "embedBlockBreadcrumb": "Embed Block Breadcrumb",
-  "embedBlockBreadcrumbTip": "After enabling embed block will show breadcrumbs",
+  "embedBlockBreadcrumbTip": "After enabling embed blocks will display breadcrumbs, embed blocks in super blocks ignore this option and never show breadcrumbs",
   "appearanceMode": "Appearance Mode",
   "editMode": "Edit Mode",
   "editReadonly": "Read-only mode",

+ 2 - 1
app/appearance/langs/es_ES.json

@@ -1,7 +1,8 @@
 {
+  "docNameAndContent": "Nombre y contenido del documento",
   "miga de pan": "Miga de pan",
   "embedBlockBreadcrumb": "Incrustar migas de pan de bloque",
-  "embedBlockBreadcrumbTip": "Después de habilitar el bloque incrustado, se mostrarán migas de pan",
+  "embedBlockBreadcrumbTip": "Después de habilitar los bloques incrustados, se mostrarán migas de pan, incrustar bloques en superbloques ignora esta opción y nunca muestra migas de pan",
   "appearanceMode": "Modo de apariencia",
   "editMode": "Modo de edición",
   "editReadonly": "Modo de solo lectura",

+ 2 - 1
app/appearance/langs/fr_FR.json

@@ -1,7 +1,8 @@
 {
+  "docNameAndContent": "Nom et contenu du document",
   "fil d'Ariane": "Fil d'Ariane",
   "embedBlockBreadcrumb": "Intégrer le fil d'Ariane du bloc",
-  "embedBlockBreadcrumbTip": "Après avoir activé le bloc d'intégration, le fil d'Ariane s'affichera",
+  "embedBlockBreadcrumbTip": "Après avoir activé l'intégration, les blocs afficheront le fil d'Ariane, intégrer des blocs dans des super blocs ignorent cette option et n'affichent jamais le fil d'Ariane",
   "appearanceMode": "Mode d'apparence",
   "editMode": "Mode d'édition",
   "editReadonly": "Mode lecture seule",

+ 2 - 1
app/appearance/langs/zh_CHT.json

@@ -1,7 +1,8 @@
 {
+  "docNameAndContent": "文檔名和內容",
   "breadcrumb": "麵包屑",
   "embedBlockBreadcrumb": "嵌入塊麵包屑",
-  "embedBlockBreadcrumbTip": "啟用後嵌入塊將顯示麵包屑",
+  "embedBlockBreadcrumbTip": "啟用後嵌入塊將顯示麵包屑,在超級塊中的嵌入塊忽略該選項,始終不顯示麵包屑",
   "appearanceMode": "外觀模式",
   "editMode": "編輯模式",
   "editReadonly": "只讀模式",

+ 2 - 1
app/appearance/langs/zh_CN.json

@@ -1,7 +1,8 @@
 {
+  "docNameAndContent": "文档名和内容",
   "breadcrumb": "面包屑",
   "embedBlockBreadcrumb": "嵌入块面包屑",
-  "embedBlockBreadcrumbTip": "启用后嵌入块将显示面包屑",
+  "embedBlockBreadcrumbTip": "启用后嵌入块将显示面包屑,在超级块中的嵌入块忽略该选项,始终不显示面包屑",
   "appearanceMode": "外观模式",
   "editMode": "编辑模式",
   "editReadonly": "只读模式",

+ 1 - 0
app/src/protyle/markdown/blockRender.ts

@@ -33,6 +33,7 @@ export const blockRender = (protyle: IProtyle, element: Element) => {
             breadcrumb = window.siyuan.config.editor.embedBlockBreadcrumb
         }
         fetchPost("/api/search/searchEmbedBlock", {
+            embedBlockID: item.getAttribute("data-node-id"),
             stmt: content,
             headingMode: item.getAttribute("custom-heading-mode") === "1" ? 1 : 0,
             excludeIDs: [item.getAttribute("data-node-id"), protyle.block.rootID],

+ 9 - 8
app/src/util/history.ts

@@ -29,7 +29,7 @@ const renderDoc = (element: HTMLElement, currentPage: number) => {
     const mdElement = element.querySelector('.history__text[data-type="mdPanel"]') as HTMLTextAreaElement;
     docElement.classList.add("fn__none");
     mdElement.classList.add("fn__none");
-    if (typeElement.value === "0") {
+    if (typeElement.value === "0" || typeElement.value === "1") {
         opElement.removeAttribute("disabled");
         notebookElement.removeAttribute("disabled");
         assetElement.classList.add("fn__none");
@@ -65,7 +65,7 @@ const renderDoc = (element: HTMLElement, currentPage: number) => {
             if (item.items.length > 0) {
                 logsHTML += `<ul class="${index === 0 ? "" : "fn__none"}">`;
                 item.items.forEach((docItem) => {
-                    logsHTML += `<li title="${escapeHtml(docItem.title)}" data-type="${typeElement.value === "1" ? "assets" : "doc"}" data-path="${docItem.path}" class="b3-list-item b3-list-item--hide-action" style="padding-left: 44px">
+                    logsHTML += `<li title="${escapeHtml(docItem.title)}" data-type="${typeElement.value === "2" ? "assets" : "doc"}" data-path="${docItem.path}" class="b3-list-item b3-list-item--hide-action" style="padding-left: 44px">
     <span class="b3-list-item__text">${escapeHtml(docItem.title)}</span>
     <span class="fn__space"></span>
     <span class="b3-list-item__action b3-tooltips b3-tooltips__w" data-type="rollback" aria-label="${window.siyuan.languages.rollback}">
@@ -179,14 +179,14 @@ const renderRmNotebook = (element: HTMLElement) => {
         }
         let logsHTML = "";
         response.data.histories.forEach((item: { items: { path: string, title: string }[], hCreated: string }, index: number) => {
-            logsHTML += `<li class="b3-list-item" data-type="toggle">
-    <span class="b3-list-item__toggle b3-list-item__toggle"><svg class="b3-list-item__arrow${index === 0 ? " b3-list-item__arrow--open" : ""}${item.items.length > 0 ? "" : " fn__hidden"}"><use xlink:href="#iconRight"></use></svg></span>
-    <span style="padding-left: 4px" class="b3-list-item__text">${item.hCreated}</span>
+            logsHTML += `<li class="b3-list-item" style="padding-left: 0" data-type="toggle">
+    <span style="padding-left: 8px" class="b3-list-item__toggle"><svg class="b3-list-item__arrow${index === 0 ? " b3-list-item__arrow--open" : ""}${item.items.length > 0 ? "" : " fn__hidden"}"><use xlink:href="#iconRight"></use></svg></span>
+    <span class="b3-list-item__text">${item.hCreated}</span>
 </li>`;
             if (item.items.length > 0) {
                 logsHTML += `<ul class="${index === 0 ? "" : "fn__none"}">`;
                 item.items.forEach((docItem) => {
-                    logsHTML += `<li data-type="notebook" data-path="${docItem.path}" class="b3-list-item" style="padding-left: 44px">
+                    logsHTML += `<li data-type="notebook" data-path="${docItem.path}" class="b3-list-item" style="padding-left: 32px">
     <span class="b3-list-item__text">${escapeHtml(docItem.title)}</span>
     <span class="fn__space"></span>
     <span class="b3-list-item__action" data-type="rollback">
@@ -239,8 +239,9 @@ export const openHistory = () => {
                 </div>
                 <span class="fn__space"></span>
                 <select data-type="typeselect" class="b3-select" style="min-width: auto">
-                    <option value="0" selected>${window.siyuan.languages.doc}</option>
-                    <option value="1">${window.siyuan.languages.assets}</option>
+                    <option value="0" selected>${window.siyuan.languages.docName}</option>
+                    <option value="1">${window.siyuan.languages.docNameAndContent}</option>
+                    <option value="2">${window.siyuan.languages.assets}</option>
                 </select>
                 <span class="fn__space"></span>
                 <select data-type="opselect" class="b3-select" style="min-width: auto">

+ 2 - 1
kernel/api/search.go

@@ -127,6 +127,7 @@ func searchEmbedBlock(c *gin.Context) {
 		return
 	}
 
+	embedBlockID := arg["embedBlockID"].(string)
 	stmt := arg["stmt"].(string)
 	excludeIDsArg := arg["excludeIDs"].([]interface{})
 	var excludeIDs []string
@@ -144,7 +145,7 @@ func searchEmbedBlock(c *gin.Context) {
 		breadcrumb = breadcrumbArg.(bool)
 	}
 
-	blocks := model.SearchEmbedBlock(stmt, excludeIDs, headingMode, breadcrumb)
+	blocks := model.SearchEmbedBlock(embedBlockID, stmt, excludeIDs, headingMode, breadcrumb)
 	ret.Data = map[string]interface{}{
 		"blocks": blocks,
 	}

+ 13 - 2
kernel/model/assets.go

@@ -405,15 +405,21 @@ func RemoveUnusedAssets() (ret []string) {
 		return
 	}
 
+	var hashes []string
 	for _, p := range unusedAssets {
 		historyPath := filepath.Join(historyDir, p)
 		if p = filepath.Join(util.DataDir, p); gulu.File.IsExist(p) {
 			if err = gulu.File.Copy(p, historyPath); nil != err {
 				return
 			}
+
+			hash, _ := util.GetEtag(p)
+			hashes = append(hashes, hash)
 		}
 	}
 
+	sql.DeleteAssetsByHashes(hashes)
+
 	for _, unusedAsset := range unusedAssets {
 		if unusedAsset = filepath.Join(util.DataDir, unusedAsset); gulu.File.IsExist(unusedAsset) {
 			if err := os.RemoveAll(unusedAsset); nil != err {
@@ -444,8 +450,13 @@ func RemoveUnusedAsset(p string) (ret string) {
 
 	newP := strings.TrimPrefix(p, util.DataDir)
 	historyPath := filepath.Join(historyDir, newP)
-	if err = gulu.File.Copy(p, historyPath); nil != err {
-		return
+	if gulu.File.IsExist(p) {
+		if err = gulu.File.Copy(p, historyPath); nil != err {
+			return
+		}
+
+		hash, _ := util.GetEtag(p)
+		sql.DeleteAssetsByHashes([]string{hash})
 	}
 
 	if err = os.RemoveAll(p); nil != err {

+ 11 - 3
kernel/model/block.go

@@ -381,7 +381,7 @@ func getBlock(id string) (ret *Block, err error) {
 	return
 }
 
-func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, headingMode int, breadcrumb bool) (block *Block, blockPaths []*BlockPath) {
+func getEmbeddedBlock(embedBlockID string, trees map[string]*parse.Tree, sqlBlock *sql.Block, headingMode int, breadcrumb bool) (block *Block, blockPaths []*BlockPath) {
 	tree, _ := trees[sqlBlock.RootID]
 	if nil == tree {
 		tree, _ = loadTreeByBlockID(sqlBlock.RootID)
@@ -434,9 +434,17 @@ func getEmbeddedBlock(trees map[string]*parse.Tree, sqlBlock *sql.Block, heading
 	luteEngine.RenderOptions.ProtyleContenteditable = false // 不可编辑
 	dom := renderBlockDOMByNodes(nodes, luteEngine)
 	block = &Block{Box: def.Box, Path: def.Path, HPath: b.HPath, ID: def.ID, Type: def.Type.String(), Content: dom}
-	if breadcrumb {
-		blockPaths = buildBlockBreadcrumb(def)
 
+	// 位于超级块中的嵌入块不显示面包屑 https://github.com/siyuan-note/siyuan/issues/6258
+	inSuperBlock := false
+	embedNodeTree, _ := loadTreeByBlockID(embedBlockID)
+	if nil != embedNodeTree {
+		embedNode := treenode.GetNodeInTree(embedNodeTree, embedBlockID)
+		inSuperBlock = nil != embedNode && embedNode.ParentIs(ast.NodeSuperBlock)
+	}
+
+	if breadcrumb && !inSuperBlock {
+		blockPaths = buildBlockBreadcrumb(def)
 	}
 	if 1 > len(blockPaths) {
 		blockPaths = []*BlockPath{}

+ 1 - 1
kernel/model/export.go

@@ -1041,7 +1041,7 @@ func exportTree(tree *parse.Tree, wysiwyg, expandKaTexMacros, keepFold bool) (re
 		var defMd string
 		stmt := n.ChildByType(ast.NodeBlockQueryEmbedScript).TokensStr()
 		stmt = html.UnescapeString(stmt)
-		embedBlocks := searchEmbedBlock(stmt, nil, 0, false)
+		embedBlocks := searchEmbedBlock(n.ID, stmt, nil, 0, false)
 		if 1 > len(embedBlocks) {
 			return ast.WalkContinue
 		}

+ 8 - 3
kernel/model/history.go

@@ -343,7 +343,11 @@ func FullTextSearchHistory(query, box, op string, typ, page int) (ret []*History
 		stmt += "1=1"
 	}
 
-	if HistoryTypeDoc == typ {
+	if HistoryTypeDocName == typ {
+		stmt = strings.ReplaceAll(stmt, "{title content}", "{title}")
+	}
+
+	if HistoryTypeDocName == typ || HistoryTypeDoc == typ {
 		if "all" != op {
 			stmt += " AND op = '" + op + "'"
 		}
@@ -578,8 +582,9 @@ func ReindexHistory() (err error) {
 var validOps = []string{HistoryOpClean, HistoryOpUpdate, HistoryOpDelete, HistoryOpFormat, HistoryOpSync}
 
 const (
-	HistoryTypeDoc   = 0
-	HistoryTypeAsset = 1
+	HistoryTypeDocName = 0
+	HistoryTypeDoc     = 1
+	HistoryTypeAsset   = 2
 )
 
 func indexHistoryDir(name string, luteEngine *lute.Lute) {

+ 5 - 4
kernel/model/search.go

@@ -43,12 +43,13 @@ type EmbedBlock struct {
 	BlockPaths []*BlockPath `json:"blockPaths"`
 }
 
-func SearchEmbedBlock(stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
+func SearchEmbedBlock(embedBlockID, stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
+	time.Sleep(512 * time.Millisecond /* 前端队列轮询间隔 */)
 	WaitForWritingFiles()
-	return searchEmbedBlock(stmt, excludeIDs, headingMode, breadcrumb)
+	return searchEmbedBlock(embedBlockID, stmt, excludeIDs, headingMode, breadcrumb)
 }
 
-func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
+func searchEmbedBlock(embedBlockID, stmt string, excludeIDs []string, headingMode int, breadcrumb bool) (ret []*EmbedBlock) {
 	sqlBlocks := sql.SelectBlocksRawStmtNoParse(stmt, Conf.Search.Limit)
 	var tmp []*sql.Block
 	for _, b := range sqlBlocks {
@@ -76,7 +77,7 @@ func searchEmbedBlock(stmt string, excludeIDs []string, headingMode int, breadcr
 	}
 
 	for _, sb := range sqlBlocks {
-		block, blockPaths := getEmbeddedBlock(trees, sb, headingMode, breadcrumb)
+		block, blockPaths := getEmbeddedBlock(embedBlockID, trees, sb, headingMode, breadcrumb)
 		if nil == block {
 			continue
 		}

+ 11 - 3
kernel/sql/aseet.go

@@ -17,9 +17,7 @@
 package sql
 
 import (
-	"crypto/sha256"
 	"database/sql"
-	"fmt"
 	"path/filepath"
 	"strings"
 
@@ -75,7 +73,7 @@ func docTitleImgAsset(root *ast.Node) *Asset {
 		absPath := filepath.Join(util.DataDir, p)
 		if hash, err = util.GetEtag(absPath); nil != err {
 			logging.LogErrorf("read asset [%s] data failed: %s", absPath, err)
-			hash = fmt.Sprintf("%x", sha256.Sum256([]byte(gulu.Rand.String(7))))
+			return nil
 		}
 		name, _ := util.LastID(p)
 		asset := &Asset{
@@ -94,6 +92,16 @@ func docTitleImgAsset(root *ast.Node) *Asset {
 	return nil
 }
 
+func DeleteAssetsByHashes(hashes []string) {
+	sqlStmt := "DELETE FROM assets WHERE hash IN ('" + strings.Join(hashes, "','") + "') OR hash = ''"
+	tx, err := BeginTx()
+	if nil != err {
+		return
+	}
+	execStmtTx(tx, sqlStmt)
+	CommitTx(tx)
+}
+
 func QueryAssetByHash(hash string) (ret *Asset) {
 	sqlStmt := "SELECT * FROM assets WHERE hash = ?"
 	row := queryRow(sqlStmt, hash)