Преглед на файлове

:bug: 只读模式下多项折叠会导致数据类型错误 https://github.com/siyuan-note/siyuan/issues/6557

Liang Ding преди 2 години
родител
ревизия
c9af265903
променени са 2 файла, в които са добавени 51 реда и са изтрити 32 реда
  1. 0 16
      kernel/api/transaction.go
  2. 51 16
      kernel/model/transaction.go

+ 0 - 16
kernel/api/transaction.go

@@ -63,22 +63,6 @@ func performTransactions(c *gin.Context) {
 		return
 	}
 
-	setAttrsOps := model.ExtractSetAttrsOps(&transactions)
-	for _, setAttrsOp := range setAttrsOps {
-		attrs := map[string]string{}
-		if err = gulu.JSON.UnmarshalJSON([]byte(setAttrsOp.Data.(string)), &attrs); nil != err {
-			return
-		}
-		if err = model.SetBlockAttrs(setAttrsOp.ID, attrs); nil != err {
-			if errors.Is(err, filelock.ErrUnableAccessFile) {
-				ret.Code = 1
-				return
-			}
-			logging.LogFatalf("set block attrs failed: %s", err)
-			return
-		}
-	}
-
 	if err = model.PerformTransactions(&transactions); errors.Is(err, filelock.ErrUnableAccessFile) {
 		ret.Code = 1
 		return

+ 51 - 16
kernel/model/transaction.go

@@ -28,6 +28,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/editor"
+	"github.com/88250/lute/lex"
 	"github.com/88250/lute/parse"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/siyuan-note/filelock"
@@ -56,22 +57,6 @@ func IsUnfoldHeading(transactions *[]*Transaction) bool {
 	return false
 }
 
-func ExtractSetAttrsOps(transactions *[]*Transaction) (ret []*Operation) {
-	for _, tx := range *transactions {
-		var setAttrsOps, tmp []*Operation
-		for _, op := range tx.DoOperations {
-			if "setAttrs" == op.Action {
-				setAttrsOps = append(setAttrsOps, op)
-			} else {
-				tmp = append(tmp, op)
-			}
-		}
-		ret = append(ret, setAttrsOps...)
-		tx.DoOperations = tmp
-	}
-	return
-}
-
 const txFixDelay = 10
 
 var (
@@ -241,6 +226,8 @@ func performTx(tx *Transaction) (ret *TxErr) {
 			ret = tx.doFoldHeading(op)
 		case "unfoldHeading":
 			ret = tx.doUnfoldHeading(op)
+		case "setAttrs":
+			ret = tx.setAttrs(op)
 		}
 
 		if nil != ret {
@@ -967,6 +954,54 @@ func (tx *Transaction) doCreate(operation *Operation) (ret *TxErr) {
 	return
 }
 
+func (tx *Transaction) setAttrs(operation *Operation) (ret *TxErr) {
+	id := operation.ID
+	tree, err := tx.loadTree(id)
+	if nil != err {
+		logging.LogErrorf("load tree [id=%s] failed: %s", id, err)
+		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
+	}
+
+	node := treenode.GetNodeInTree(tree, id)
+	if nil == node {
+		logging.LogErrorf("get node [%s] in tree [%s] failed", id, tree.Root.ID)
+		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
+	}
+
+	attrs := map[string]string{}
+	if err = gulu.JSON.UnmarshalJSON([]byte(operation.Data.(string)), &attrs); nil != err {
+		logging.LogErrorf("unmarshal attrs failed: %s", err)
+		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
+	}
+
+	var invalidNames []string
+	for name := range attrs {
+		for i := 0; i < len(name); i++ {
+			if !lex.IsASCIILetterNumHyphen(name[i]) {
+				logging.LogWarnf("invalid attr name [%s]", name)
+				invalidNames = append(invalidNames, name)
+			}
+		}
+	}
+	for _, name := range invalidNames {
+		delete(attrs, name)
+	}
+
+	for name, value := range attrs {
+		if "" == value {
+			node.RemoveIALAttr(name)
+		} else {
+			node.SetIALAttr(name, value)
+		}
+	}
+
+	if err = indexWriteJSONQueue(tree); nil != err {
+		return
+	}
+	cache.PutBlockIAL(id, parse.IAL2Map(node.KramdownIAL))
+	return
+}
+
 func refreshUpdated(n *ast.Node) {
 	updated := util.CurrentTimeSecondsStr()
 	n.SetIALAttr("updated", updated)