diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 55f324f07..193c36bd5 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -16,10 +16,10 @@ Install pnpm: `npm install -g pnpm` Set the Electron mirror environment variable and install Electron: -* macOS/Linux: `ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/ pnpm install electron@25.8.1 -D` +* macOS/Linux: `ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/ pnpm install electron@26.2.3 -D` * Windows: * `SET ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/` - * `pnpm install electron@25.8.1 -D` + * `pnpm install electron@26.2.3 -D` NPM mirror: @@ -30,7 +30,7 @@ NPM mirror: On the desktop, go to the app folder to run: -* `pnpm install electron@25.8.1 -D` +* `pnpm install electron@26.2.3 -D` * `pnpm run dev` * `pnpm run start` diff --git a/.github/CONTRIBUTING_zh_CN.md b/.github/CONTRIBUTING_zh_CN.md index 029f01311..d84b17bba 100644 --- a/.github/CONTRIBUTING_zh_CN.md +++ b/.github/CONTRIBUTING_zh_CN.md @@ -18,11 +18,11 @@ * macOS/Linux: ``` - ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/ pnpm install electron@25.8.1 -D + ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/ pnpm install electron@26.2.3 -D ``` * Windows: * `SET ELECTRON_MIRROR=https://cnpmjs.org/mirrors/electron/` - * `pnpm install electron@25.8.1 -D` + * `pnpm install electron@26.2.3 -D` NPM 镜像: @@ -32,7 +32,7 @@ NPM 镜像: 桌面端进入 app 文件夹运行: -* `pnpm install electron@25.8.1 -D` +* `pnpm install electron@26.2.3 -D` * `pnpm run dev` * `pnpm run start` diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index d0e8cc74f..4816e8d35 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1182,7 +1182,7 @@ "109": "Remove reminder completed [%s]", "110": "Renaming...", "111": "Saving document [%s]...", - "112": "Do not include Markdown syntax marker", + "112": "Do not include Markdown syntax marker [%s]", "113": "Completing data writing...", "114": "Tag cannot be empty", "115": "Please configure [Settings - Export - Pandoc executable path] first", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 8617a9cdf..0fda16619 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1182,7 +1182,7 @@ "109": "Eliminación de recordatorios completada [%s]", "110": "Renombrar...", "111": "Guardando documento [%s]...", - "112": "No incluir marcador de sintaxis Markdown", + "112": "No incluir marcador de sintaxis Markdown [%s]", "113": "Completando la escritura de datos...", "114": "La etiqueta no puede estar vacía", "115": "Por favor, configure primero [Configuración - Exportación - Ruta ejecutable de Pandoc]", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index e6ed51585..88e88c3b6 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1182,7 +1182,7 @@ "109": "Supprimer le rappel terminé [%s]", "110": "Renommer...", "111": "Enregistrement du document [%s]...", - "112": "Ne pas inclure les balises de syntaxe Markdown", + "112": "Ne pas inclure les balises de syntaxe Markdown [%s]", "113": "Fin de l'écriture des données...", "114": "La balise ne peut pas être vide", "115": "Veuillez d'abord configurer [Paramètres - Exporter - Chemin de l'exécutable Pandoc]", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index a8e57dfbd..e5a9efd82 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1182,7 +1182,7 @@ "109": "移除提醒完畢 [%s]", "110": "正在重命名...", "111": "正在保存文檔 [%s]...", - "112": "請勿包含 Markdown 語法標記符", + "112": "請勿包含 Markdown 語法標記符 [%s]", "113": "正在完成資料寫入...", "114": "標籤不能為空", "115": "請先配置 [設置 - 導出 - Pandoc 可執行文件路徑]", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 1ae7f285c..b7b58e9f7 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1182,7 +1182,7 @@ "109": "移除提醒完毕 [%s]", "110": "正在重命名...", "111": "正在保存文档 [%s]...", - "112": "请勿包含 Markdown 语法标记符", + "112": "请勿包含 Markdown 语法标记符 [%s]", "113": "正在完成数据写入...", "114": "标签不能为空", "115": "请先配置 [设置 - 导出 - Pandoc 可执行文件路径]", diff --git a/app/package.json b/app/package.json index 0d443fcb6..a64eab1d8 100644 --- a/app/package.json +++ b/app/package.json @@ -4,7 +4,7 @@ "description": "Refactor your thinking", "homepage": "https://b3log.org/siyuan", "main": "./electron/main.js", - "packageManager": "pnpm@8.2.0", + "packageManager": "pnpm@8.8.0", "scripts": { "lint": "eslint . --fix --cache", "dev": "webpack --mode development", @@ -53,7 +53,7 @@ "clean-webpack-plugin": "^4.0.0", "css-loader": "^6.7.1", "dayjs": "^1.11.5", - "electron": "25.8.1", + "electron": "26.2.3", "electron-builder": "^24.6.3", "encoding": "^0.1.13", "esbuild-loader": "^3.0.1", @@ -74,6 +74,6 @@ "webpack-cli": "^4.10.0" }, "dependencies": { - "@electron/remote": "^2.0.9" + "@electron/remote": "^2.0.11" } } diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index c876f52ee..8f6a9e85d 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@electron/remote': - specifier: ^2.0.9 - version: 2.0.9(electron@25.8.1) + specifier: ^2.0.11 + version: 2.0.11(electron@26.2.3) devDependencies: '@types/node': @@ -32,8 +32,8 @@ devDependencies: specifier: ^1.11.5 version: 1.11.5 electron: - specifier: 25.8.1 - version: 25.8.1 + specifier: 26.2.3 + version: 26.2.3 electron-builder: specifier: ^24.6.3 version: 24.6.3 @@ -160,12 +160,12 @@ packages: - supports-color dev: true - /@electron/remote@2.0.9(electron@25.8.1): - resolution: {integrity: sha512-LR0W0ID6WAKHaSs0x5LX9aiG+5pFBNAJL6eQAJfGkCuZPUa6nZz+czZLdlTDETG45CgF/0raSvCtYOYUpr6c+A==} + /@electron/remote@2.0.11(electron@26.2.3): + resolution: {integrity: sha512-PYEs7W3GrQNuhgiMHjFEvL5MbAL6C7m1AwSAHGqC+xc33IdP7rcGtJSdTP2eg1ssyB3oI00KwTsiSlsQbAoXpA==} peerDependencies: electron: '>= 13.0.0' dependencies: - electron: 25.8.1 + electron: 26.2.3 dev: false /@electron/universal@1.3.4: @@ -1669,8 +1669,8 @@ packages: resolution: {integrity: sha512-YoVeFrGd/7ROjz4R9uPoND1K/hSRC/xADy9639ZmIZeJSaBnKdYx3I6LMPsY7CXLpK7JFgKQVzeZ/dk2br6Eaw==} dev: true - /electron@25.8.1: - resolution: {integrity: sha512-GtcP1nMrROZfFg0+mhyj1hamrHvukfF6of2B/pcWxmWkd5FVY1NJib0tlhiorFZRzQN5Z+APLPr7aMolt7i2AQ==} + /electron@26.2.3: + resolution: {integrity: sha512-osdKf9mbhrqE81ITdvQ7TjVOayXfcAlWm8A6EtBt/eFSh7a/FijebGVkgs0S7qWQdhO0KaNZDb1Gx00sWuDQdw==} engines: {node: '>= 12.20.55'} hasBin: true requiresBuild: true diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 6c93c4b04..252b805f0 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -885,6 +885,51 @@ func removeAttributeViewColumn(operation *Operation) (err error) { return } +func (tx *Transaction) doReplaceAttrViewBlock(operation *Operation) (ret *TxErr) { + err := replaceAttributeViewBlock(operation) + if nil != err { + return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID} + } + return +} + +func replaceAttributeViewBlock(operation *Operation) (err error) { + attrView, err := av.ParseAttributeView(operation.AvID) + if nil != err { + return + } + + for _, keyValues := range attrView.KeyValues { + for _, value := range keyValues.Values { + if value.BlockID == operation.PreviousID { + value.BlockID = operation.NextID + if nil != value.Block { + value.Block.ID = operation.NextID + value.IsDetached = operation.IsDetached + } + + if !operation.IsDetached { + bindBlockAv(operation.AvID, operation.NextID) + } + } + } + } + + for _, v := range attrView.Views { + switch v.LayoutType { + case av.LayoutTypeTable: + for i, rowID := range v.Table.RowIDs { + if rowID == operation.PreviousID { + v.Table.RowIDs[i] = operation.NextID + } + } + } + } + + err = av.SaveAttributeView(attrView) + return +} + func (tx *Transaction) doUpdateAttrViewCell(operation *Operation) (ret *TxErr) { err := updateAttributeViewCell(operation, tx) if nil != err { @@ -937,30 +982,7 @@ func UpdateAttributeViewCell(avID, keyID, rowID, cellID string, valueData interf if oldIsDetached && !val.IsDetached { // 将游离行绑定到新建的块上 - tree, loadErr := loadTreeByBlockID(rowID) - if nil != loadErr { - logging.LogWarnf("load tree by block id [%s] failed: %s", rowID, loadErr) - } else { - node := treenode.GetNodeInTree(tree, rowID) - if nil == node { - logging.LogWarnf("node [%s] not found in tree [%s]", rowID, tree.ID) - } else { - attrs := parse.IAL2Map(node.KramdownIAL) - - if "" == attrs[NodeAttrNameAvs] { - attrs[NodeAttrNameAvs] = avID - } else { - avIDs := strings.Split(attrs[NodeAttrNameAvs], ",") - avIDs = append(avIDs, avID) - avIDs = gulu.Str.RemoveDuplicatedElem(avIDs) - attrs[NodeAttrNameAvs] = strings.Join(avIDs, ",") - } - - if err = setNodeAttrs(node, tree, attrs); nil != err { - logging.LogWarnf("set node [%s] attrs failed: %s", rowID, err) - } - } - } + bindBlockAv(avID, rowID) } if err = av.SaveAttributeView(attrView); nil != err { @@ -969,6 +991,39 @@ func UpdateAttributeViewCell(avID, keyID, rowID, cellID string, valueData interf return } +func bindBlockAv(avID, blockID string) { + tree, loadErr := loadTreeByBlockID(blockID) + if nil != loadErr { + logging.LogWarnf("load tree by block id [%s] failed: %s", blockID, loadErr) + return + } + + node := treenode.GetNodeInTree(tree, blockID) + if nil == node { + logging.LogWarnf("node [%s] not found in tree [%s]", blockID, tree.ID) + return + } + + attrs := parse.IAL2Map(node.KramdownIAL) + if "" == attrs[NodeAttrNameAvs] { + attrs[NodeAttrNameAvs] = avID + } else { + avIDs := strings.Split(attrs[NodeAttrNameAvs], ",") + if gulu.Str.Contains(avID, avIDs) { + return + } + + avIDs = append(avIDs, avID) + avIDs = gulu.Str.RemoveDuplicatedElem(avIDs) + attrs[NodeAttrNameAvs] = strings.Join(avIDs, ",") + } + + if err := setNodeAttrs(node, tree, attrs); nil != err { + logging.LogWarnf("set node [%s] attrs failed: %s", blockID, err) + } + return +} + func (tx *Transaction) doUpdateAttrViewColOptions(operation *Operation) (ret *TxErr) { err := updateAttributeViewColumnOptions(operation) if nil != err { diff --git a/kernel/model/bookmark.go b/kernel/model/bookmark.go index b6a98428b..16d7306cd 100644 --- a/kernel/model/bookmark.go +++ b/kernel/model/bookmark.go @@ -75,8 +75,8 @@ func RemoveBookmark(bookmark string) (err error) { } func RenameBookmark(oldBookmark, newBookmark string) (err error) { - if treenode.ContainsMarker(newBookmark) { - return errors.New(Conf.Language(112)) + if invalidChar := treenode.ContainsMarker(newBookmark); "" != invalidChar { + return errors.New(fmt.Sprintf(Conf.Language(112), invalidChar)) } newBookmark = strings.TrimSpace(newBookmark) diff --git a/kernel/model/tag.go b/kernel/model/tag.go index 1ffcf32d9..744d3f1d4 100644 --- a/kernel/model/tag.go +++ b/kernel/model/tag.go @@ -105,8 +105,8 @@ func RemoveTag(label string) (err error) { } func RenameTag(oldLabel, newLabel string) (err error) { - if treenode.ContainsMarker(newLabel) { - return errors.New(Conf.Language(112)) + if invalidChar := treenode.ContainsMarker(newLabel); "" != invalidChar { + return errors.New(fmt.Sprintf(Conf.Language(112), invalidChar)) } newLabel = strings.TrimSpace(newLabel) diff --git a/kernel/model/transaction.go b/kernel/model/transaction.go index 18c455cf3..ab6c43db0 100644 --- a/kernel/model/transaction.go +++ b/kernel/model/transaction.go @@ -260,6 +260,8 @@ func performTx(tx *Transaction) (ret *TxErr) { ret = tx.doSetAttrViewColCalc(op) case "updateAttrViewColNumberFormat": ret = tx.doUpdateAttrViewColNumberFormat(op) + case "replaceAttrViewBlock": + ret = tx.doReplaceAttrViewBlock(op) } if nil != ret { diff --git a/kernel/treenode/marker.go b/kernel/treenode/marker.go index 41844b6d4..727f69702 100644 --- a/kernel/treenode/marker.go +++ b/kernel/treenode/marker.go @@ -21,17 +21,17 @@ import ( "github.com/88250/lute/lex" ) -func ContainsMarker(str string) bool { +func ContainsMarker(str string) (ret string) { if !gulu.Str.IsASCII(str) { - return false + return } for _, token := range str { if IsMarker(byte(token)) { - return true + return string(token) } } - return false + return } func IsMarker(token byte) bool {