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

This commit is contained in:
Vanessa 2023-02-21 13:22:51 +08:00
commit a106b9fe5f
15 changed files with 112 additions and 88 deletions

View file

@ -1006,7 +1006,7 @@
"104": "The update installation package failed to download, please check the network connection",
"105": "Corrupted data repo have been automatically reset",
"106": "Maximum length is limited to 512 characters",
"107": "Moving document [%s]",
"107": "Moved document [%s]",
"108": "Data sync found conflicts, you can view the generated conflict content in [Data History]",
"109": "Remove reminder completed [%s]",
"110": "Renaming...",

View file

@ -1006,7 +1006,7 @@
"104": "El paquete de instalación de la actualización no se pudo descargar, verifique la conexión de red",
"105": "El repositorio de datos corruptos se ha restablecido automáticamente",
"106": "La longitud máxima está limitada a 512 caracteres",
"107": "Moviendo documento [%s]",
"107": "Documento movido [%s]",
"108": "La sincronizaci\u00f3n de datos encontr\u00f3 en conflictos, puede ver el contenido del conflicto generado en [Historial de datos]",
"109": "Eliminación de recordatorios completada [%s]",
"110": "Renombrar...",

View file

@ -1006,7 +1006,7 @@
"104": "Le package d'installation de la mise à jour n'a pas pu être téléchargé, veuillez vérifier la connexion réseau",
"105": "Le référentiel de données corrompu a été automatiquement réinitialisé",
"106": "La longueur maximale est limitée à 512 caractères",
"107": "Déplacement du document [%s]",
"107": "Document déplacé [%s]",
"108": "La synchronisation des données a trouvé des conflits, vous pouvez afficher le contenu du conflit généré dans [Historique des données]",
"109": "Supprimer le rappel terminé [%s]",
"110": "Renommer...",

View file

@ -1006,7 +1006,7 @@
"104": "更新安裝包下載失敗,請檢查網絡連接",
"105": "已經自動重置損壞的數據倉庫",
"106": "最大長度限制為 512 字元",
"107": "正在移動文檔 [%s]",
"107": "已經移動文檔 [%s]",
"108": "數據同步發現衝突,可在 [數據歷史] 中查看生成的衝突內容",
"109": "移除提醒完畢 [%s]",
"110": "正在重命名...",

View file

@ -1006,7 +1006,7 @@
"104": "更新安装包下载失败,请检查网络连接",
"105": "已经自动重置损坏的数据仓库",
"106": "最大长度限制为 512 字符",
"107": "正在移动文档 [%s]",
"107": "已经移动文档 [%s]",
"108": "数据同步发现冲突,可在 [数据历史] 中查看生成的冲突内容",
"109": "移除提醒完毕 [%s]",
"110": "正在重命名...",

View file

@ -63,7 +63,7 @@ func SetBlockReminder(id string, timed string) (err error) {
if ast.NodeDocument != node.Type && node.IsContainerBlock() {
node = treenode.FirstLeafBlock(node)
}
content := treenode.NodeStaticContent(node, nil)
content := treenode.NodeStaticContent(node, nil, false)
content = gulu.Str.SubStr(content, 128)
err = SetCloudBlockReminder(id, content, timedMills)
if nil != err {

View file

@ -385,10 +385,8 @@ func (box *Box) renameSubTrees(tree *parse.Tree) {
}
func (box *Box) moveTrees0(files []*FileInfo) {
totals := len(files) + 5
showProgress := 64 < totals
luteEngine := util.NewLute()
for i, subFile := range files {
for _, subFile := range files {
if !strings.HasSuffix(subFile.path, ".sy") {
continue
}
@ -399,16 +397,9 @@ func (box *Box) moveTrees0(files []*FileInfo) {
}
treenode.SetBlockTreePath(subTree)
sql.UpsertTreeQueue(subTree)
if showProgress {
msg := fmt.Sprintf(Conf.Language(107), subTree.HPath)
util.PushProgress(util.PushProgressCodeProgressed, i, totals, msg)
}
}
if showProgress {
util.ClearPushProgress(totals)
sql.RenameSubTreeQueue(subTree)
msg := fmt.Sprintf(Conf.Language(107), subTree.HPath)
util.PushStatusBar(msg)
}
}

View file

@ -882,11 +882,11 @@ func indexWriteJSONQueueWithoutChangeTime(tree *parse.Tree) (err error) {
return writeJSONQueueWithoutChangeTime(tree)
}
func renameWriteJSONQueue(tree *parse.Tree, oldHPath string) (err error) {
func renameWriteJSONQueue(tree *parse.Tree) (err error) {
if err = filesys.WriteTree(tree); nil != err {
return
}
sql.RenameTreeQueue(tree, oldHPath)
sql.RenameTreeQueue(tree)
treenode.IndexBlockTree(tree)
return
}
@ -1288,12 +1288,10 @@ func RenameDoc(boxID, p, title string) (err error) {
}
title = strings.ReplaceAll(title, "/", "")
oldHPath := tree.HPath
tree.HPath = path.Join(path.Dir(tree.HPath), title)
tree.Root.SetIALAttr("title", title)
tree.Root.SetIALAttr("updated", util.CurrentTimeSecondsStr())
if err = renameWriteJSONQueue(tree, oldHPath); nil != err {
if err = renameWriteJSONQueue(tree); nil != err {
return
}

View file

@ -379,9 +379,11 @@ func RemoveFlashcards(deckID string, blockIDs []string) (err error) {
deckAttrs := node.IALAttr("custom-riff-decks")
var deckIDs []string
for _, dID := range strings.Split(deckAttrs, ",") {
if dID != deckID && gulu.Str.Contains(dID, availableDeckIDs) {
deckIDs = append(deckIDs, dID)
if "" != deckID {
for _, dID := range strings.Split(deckAttrs, ",") {
if dID != deckID && gulu.Str.Contains(dID, availableDeckIDs) {
deckIDs = append(deckIDs, dID)
}
}
}
@ -410,20 +412,32 @@ func RemoveFlashcards(deckID string, blockIDs []string) (err error) {
pushBroadcastAttrTransactions(trans)
}
deck := Decks[deckID]
if nil != deck {
for _, blockID := range blockIDs {
deck.RemoveCard(blockID)
}
err = deck.Save()
if nil != err {
logging.LogErrorf("save deck [%s] failed: %s", deckID, err)
return
if "" == deckID { // 支持在 All 卡包中移除闪卡 https://github.com/siyuan-note/siyuan/issues/7425
for _, deck := range Decks {
removeFlashcard(blockIDs, deck)
}
} else {
removeFlashcard(blockIDs, Decks[deckID])
}
return
}
func removeFlashcard(blockIDs []string, deck *riff.Deck) {
if nil == deck {
logging.LogErrorf("deck is nil")
return
}
for _, blockID := range blockIDs {
deck.RemoveCard(blockID)
}
err := deck.Save()
if nil != err {
logging.LogErrorf("save deck [%s] failed: %s", deck.ID, err)
}
}
func AddFlashcards(deckID string, blockIDs []string) (err error) {
deckLock.Lock()
defer deckLock.Unlock()

View file

@ -78,7 +78,7 @@ func renderOutline(node *ast.Node, luteEngine *lute.Lute) (ret string) {
}
func renderBlockText(node *ast.Node, excludeTypes []string) (ret string) {
ret = treenode.NodeStaticContent(node, excludeTypes)
ret = treenode.NodeStaticContent(node, excludeTypes, false)
ret = strings.TrimSpace(ret)
ret = strings.ReplaceAll(ret, "\n", "")
ret = util.EscapeHTML(ret)
@ -141,7 +141,7 @@ func renderBlockContentByNodes(nodes []*ast.Node) string {
buf := bytes.Buffer{}
for _, n := range subNodes {
buf.WriteString(treenode.NodeStaticContent(n, nil))
buf.WriteString(treenode.NodeStaticContent(n, nil, false))
}
return buf.String()
}

View file

@ -51,7 +51,7 @@ func getBlockVirtualRefKeywords(root *ast.Node) (ret []string) {
return ast.WalkContinue
}
content := treenode.NodeStaticContent(n, nil)
content := treenode.NodeStaticContent(n, nil, false)
buf.WriteString(content)
return ast.WalkContinue
})

View file

@ -17,7 +17,6 @@
package sql
import (
"runtime/debug"
"time"
"github.com/88250/lute/ast"
@ -46,7 +45,6 @@ var blockCache, _ = ristretto.NewCache(&ristretto.Config{
func ClearCache() {
blockCache.Clear()
debug.FreeOSMemory()
}
func putBlockCache(block *Block) {

View file

@ -699,9 +699,10 @@ func buildBlockFromNode(n *ast.Node, tree *parse.Tree) (block *Block, attributes
fcontent = content
length = utf8.RuneCountInString(fcontent)
} else if n.IsContainerBlock() {
markdown, content = treenode.NodeStaticMdContent(n, luteEngine)
markdown = treenode.ExportNodeStdMd(n, luteEngine)
content = treenode.NodeStaticContent(n, nil, true)
fc := treenode.FirstLeafBlock(n)
fcontent = treenode.NodeStaticContent(fc, nil)
fcontent = treenode.NodeStaticContent(fc, nil, false)
parentID = n.Parent.ID
// 将标题块作为父节点
if h := heading(n); nil != h {
@ -709,7 +710,8 @@ func buildBlockFromNode(n *ast.Node, tree *parse.Tree) (block *Block, attributes
}
length = utf8.RuneCountInString(fcontent)
} else {
markdown, content = treenode.NodeStaticMdContent(n, luteEngine)
markdown = treenode.ExportNodeStdMd(n, luteEngine)
content = treenode.NodeStaticContent(n, nil, true)
parentID = n.Parent.ID
// 将标题块作为父节点
if h := heading(n); nil != h {
@ -818,10 +820,6 @@ func heading(node *ast.Node) *ast.Node {
return nil
}
func DeleteBlockByIDs(tx *sql.Tx, ids []string) (err error) {
return deleteBlocksByIDs(tx, ids)
}
func deleteByBoxTx(tx *sql.Tx, box string) (err error) {
if err = deleteBlocksByBoxTx(tx, box); nil != err {
return
@ -867,9 +865,11 @@ func deleteBlocksByIDs(tx *sql.Tx, ids []string) (err error) {
if err = execStmtTx(tx, stmt); nil != err {
return
}
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE id IN " + in.String()
if err = execStmtTx(tx, stmt); nil != err {
return
if !caseSensitive {
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE id IN " + in.String()
if err = execStmtTx(tx, stmt); nil != err {
return
}
}
return
}
@ -883,9 +883,11 @@ func deleteBlocksByBoxTx(tx *sql.Tx, box string) (err error) {
if err = execStmtTx(tx, stmt, box); nil != err {
return
}
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE box = ?"
if err = execStmtTx(tx, stmt, box); nil != err {
return
if !caseSensitive {
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE box = ?"
if err = execStmtTx(tx, stmt, box); nil != err {
return
}
}
ClearCache()
return
@ -991,9 +993,11 @@ func deleteByRootID(tx *sql.Tx, rootID string, context map[string]interface{}) (
if err = execStmtTx(tx, stmt, rootID); nil != err {
return
}
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE root_id = ?"
if err = execStmtTx(tx, stmt, rootID); nil != err {
return
if !caseSensitive {
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE root_id = ?"
if err = execStmtTx(tx, stmt, rootID); nil != err {
return
}
}
stmt = "DELETE FROM spans WHERE root_id = ?"
if err = execStmtTx(tx, stmt, rootID); nil != err {
@ -1027,9 +1031,11 @@ func batchDeleteByRootIDs(tx *sql.Tx, rootIDs []string, context map[string]inter
if err = execStmtTx(tx, stmt); nil != err {
return
}
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE root_id IN " + ids
if err = execStmtTx(tx, stmt); nil != err {
return
if !caseSensitive {
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE root_id IN " + ids
if err = execStmtTx(tx, stmt); nil != err {
return
}
}
stmt = "DELETE FROM spans WHERE root_id IN " + ids
if err = execStmtTx(tx, stmt); nil != err {
@ -1061,9 +1067,11 @@ func batchDeleteByPathPrefix(tx *sql.Tx, boxID, pathPrefix string) (err error) {
if err = execStmtTx(tx, stmt, boxID, pathPrefix+"%"); nil != err {
return
}
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE box = ? AND path LIKE ?"
if err = execStmtTx(tx, stmt, boxID, pathPrefix+"%"); nil != err {
return
if !caseSensitive {
stmt = "DELETE FROM blocks_fts_case_insensitive WHERE box = ? AND path LIKE ?"
if err = execStmtTx(tx, stmt, boxID, pathPrefix+"%"); nil != err {
return
}
}
stmt = "DELETE FROM spans WHERE box = ? AND path LIKE ?"
if err = execStmtTx(tx, stmt, boxID, pathPrefix+"%"); nil != err {
@ -1085,18 +1093,20 @@ func batchDeleteByPathPrefix(tx *sql.Tx, boxID, pathPrefix string) (err error) {
return
}
func batchUpdateHPath(tx *sql.Tx, boxID, rootID, oldHPath, newHPath string) (err error) {
stmt := "UPDATE blocks SET hpath = ? WHERE box = ? AND root_id = ? AND hpath = ?"
if err = execStmtTx(tx, stmt, newHPath, boxID, rootID, oldHPath); nil != err {
func batchUpdateHPath(tx *sql.Tx, boxID, rootID, newHPath string) (err error) {
stmt := "UPDATE blocks SET hpath = ? WHERE box = ? AND root_id = ?"
if err = execStmtTx(tx, stmt, newHPath, boxID, rootID); nil != err {
return
}
stmt = "UPDATE blocks_fts SET hpath = ? WHERE box = ? AND root_id = ? AND hpath = ?"
if err = execStmtTx(tx, stmt, newHPath, boxID, rootID, oldHPath); nil != err {
stmt = "UPDATE blocks_fts SET hpath = ? WHERE box = ? AND root_id = ?"
if err = execStmtTx(tx, stmt, newHPath, boxID, rootID); nil != err {
return
}
stmt = "UPDATE blocks_fts_case_insensitive SET hpath = ? WHERE box = ? AND root_id = ? AND hpath = ?"
if err = execStmtTx(tx, stmt, newHPath, boxID, rootID, oldHPath); nil != err {
return
if !caseSensitive {
stmt = "UPDATE blocks_fts_case_insensitive SET hpath = ? WHERE box = ? AND root_id = ?"
if err = execStmtTx(tx, stmt, newHPath, boxID, rootID); nil != err {
return
}
}
ClearCache()
return

View file

@ -41,7 +41,7 @@ var (
type dbQueueOperation struct {
inQueueTime time.Time
action string // upsert/delete/delete_id/rename/delete_box/delete_box_refs/insert_refs/index/delete_ids/update_block_content/delete_assets
action string // upsert/delete/delete_id/rename/rename_sub_tree/delete_box/delete_box_refs/insert_refs/index/delete_ids/update_block_content/delete_assets
indexPath string // index
upsertTree *parse.Tree // upsert/insert_refs
@ -49,8 +49,7 @@ type dbQueueOperation struct {
removeTreeIDBox, removeTreeID string // delete_id
removeTreeIDs []string // delete_ids
box string // delete_box/delete_box_refs/index
renameTree *parse.Tree // rename
renameTreeOldHPath string // rename
renameTree *parse.Tree // rename/rename_sub_tree
block *Block // update_block_content
removeAssetHashes []string // delete_assets
}
@ -168,11 +167,13 @@ func execOp(op *dbQueueOperation, tx *sql.Tx, context map[string]interface{}) (e
case "delete_ids":
err = batchDeleteByRootIDs(tx, op.removeTreeIDs, context)
case "rename":
err = batchUpdateHPath(tx, op.renameTree.Box, op.renameTree.ID, op.renameTreeOldHPath, op.renameTree.HPath)
err = batchUpdateHPath(tx, op.renameTree.Box, op.renameTree.ID, op.renameTree.HPath)
if nil != err {
break
}
err = updateRootContent(tx, path.Base(op.renameTree.HPath), op.renameTree.Root.IALAttr("updated"), op.renameTree.ID)
case "rename_sub_tree":
err = batchUpdateHPath(tx, op.renameTree.Box, op.renameTree.ID, op.renameTree.HPath)
case "delete_box":
err = deleteByBoxTx(tx, op.box)
case "delete_box_refs":
@ -303,15 +304,15 @@ func UpsertTreeQueue(tree *parse.Tree) {
operationQueue = append(operationQueue, newOp)
}
func RenameTreeQueue(tree *parse.Tree, oldHPath string) {
func RenameTreeQueue(tree *parse.Tree) {
dbQueueLock.Lock()
defer dbQueueLock.Unlock()
newOp := &dbQueueOperation{
renameTree: tree,
renameTreeOldHPath: oldHPath,
inQueueTime: time.Now(),
action: "rename"}
renameTree: tree,
inQueueTime: time.Now(),
action: "rename",
}
for i, op := range operationQueue {
if "rename" == op.action && op.renameTree.ID == tree.ID { // 相同树则覆盖
operationQueue[i] = newOp
@ -321,6 +322,24 @@ func RenameTreeQueue(tree *parse.Tree, oldHPath string) {
operationQueue = append(operationQueue, newOp)
}
func RenameSubTreeQueue(tree *parse.Tree) {
dbQueueLock.Lock()
defer dbQueueLock.Unlock()
newOp := &dbQueueOperation{
renameTree: tree,
inQueueTime: time.Now(),
action: "rename_sub_tree",
}
for i, op := range operationQueue {
if "rename_sub_tree" == op.action && op.renameTree.ID == tree.ID { // 相同树则覆盖
operationQueue[i] = newOp
return
}
}
operationQueue = append(operationQueue, newOp)
}
func RemoveTreeQueue(box, rootID string) {
dbQueueLock.Lock()
defer dbQueueLock.Unlock()

View file

@ -114,12 +114,6 @@ func IsEmbedBlockRef(n *ast.Node) bool {
return "" != GetEmbedBlockRef(n)
}
func NodeStaticMdContent(node *ast.Node, luteEngine *lute.Lute) (md, content string) {
md = ExportNodeStdMd(node, luteEngine)
content = NodeStaticContent(node, nil)
return
}
func FormatNode(node *ast.Node, luteEngine *lute.Lute) string {
markdown, err := lute.FormatNodeSync(node, luteEngine.ParseOptions, luteEngine.RenderOptions)
if nil != err {
@ -138,7 +132,7 @@ func ExportNodeStdMd(node *ast.Node, luteEngine *lute.Lute) string {
return markdown
}
func NodeStaticContent(node *ast.Node, excludeTypes []string) string {
func NodeStaticContent(node *ast.Node, excludeTypes []string, includeTextMarkATitleURL bool) string {
if nil == node {
return ""
}
@ -225,7 +219,7 @@ func NodeStaticContent(node *ast.Node, excludeTypes []string) string {
if n.IsTextMarkType("tag") {
buf.WriteByte('#')
}
if n.IsTextMarkType("a") {
if n.IsTextMarkType("a") && includeTextMarkATitleURL {
// 搜索不到超链接元素的 URL 和标题 https://github.com/siyuan-note/siyuan/issues/7352
if "" != n.TextMarkATitle {
buf.WriteString(" " + n.TextMarkATitle)