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

This commit is contained in:
Vanessa 2022-05-27 21:33:52 +08:00
commit a75320be8e
26 changed files with 525 additions and 784 deletions

2
FUNDING.yml Normal file
View file

@ -0,0 +1,2 @@
open_collective: b3log
custom: https://ld246.com/sponsor

View file

@ -740,7 +740,7 @@
"12": "Query asset failed [%s]",
"13": "Cannot create a file starting with .",
"14": "Export failed: %s",
"15": "The content block with ID [%s] was not found, please rebuild the index and try again",
"15": "The content block with ID [%s] was not found, please try again later in the document tree panel menu [Rebuild Index]",
"16": "Please enter the doc name",
"17": "The initial synchronization failed at startup. Unpredictable data overwriting may occur if you continue to operate. Please perform a synchronization first",
"18": "Get community user account failed",

View file

@ -740,7 +740,7 @@
"12": "Échec de la requête asset [%s]",
"13": "Impossible de créer un fichier commençant par .",
"14": "L'exportation a échoué : %s",
"15": "Le bloc de contenu avec l'ID [%s] n'a pas été trouvé, veuillez reconstruire l'index et réessayer",
"15": "Le bloc de contenu avec l'ID [%s] n'a pas été trouvé, veuillez réessayer plus tard dans le menu du panneau de l'arborescence du document [Reconstruire l'index]",
"16": "Veuillez entrer le nom du fichier",
"17": "La synchronisation initiale a échoué au démarrage. Un écrasement imprévisible des données peut se produire si vous continuez à fonctionner. Veuillez d'abord effectuer une synchronisation.",
"18": "Échec de la récupération du compte utilisateur communautaire",

View file

@ -740,7 +740,7 @@
"12": "查詢資料檔失敗 [%s]",
"13": "無法創建 . 開頭的文件",
"14": "匯出失敗:%s",
"15": "未找到 ID 為 [%s] 的內容塊,請重建索引後再試",
"15": "未找到 ID 為 [%s] 的內容塊,請在文檔樹面板菜單【重建索引】以後再試",
"16": "請輸入文檔名",
"17": "啟動時初次同步失敗,繼續操作可能會發生無法預測的數據覆蓋,請先執行一次同步",
"18": "獲取社區用戶帳號失敗",

View file

@ -740,7 +740,7 @@
"12": "查询资源文件失败 [%s]",
"13": "无法创建 . 开头的文件",
"14": "导出失败:%s",
"15": "未找到 ID 为 [%s] 的内容块,请重建索引后再试",
"15": "未找到 ID 为 [%s] 的内容块,请在文档树面板菜单【重建索引】以后再试",
"16": "请输入文档名",
"17": "启动时初次同步失败,继续操作可能会发生无法预测的数据覆盖,请先执行一次同步",
"18": "获取社区用户账号失败",

View file

@ -375,6 +375,12 @@ const boot = () => {
mainWindow.show()
},
},
{
label: 'Hide Window',
click: () => {
mainWindow.hide()
},
},
{
label: 'Quit',
click: () => {

View file

@ -6,7 +6,7 @@
"id": "20200923234602-gy54e67",
"title": "Privacy Policy and User Agreement",
"type": "doc",
"updated": "20220511114202"
"updated": "20220526191417"
},
"Children": [
{
@ -322,124 +322,65 @@
]
},
{
"ID": "20220219101351-0tucf6z",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-0tucf6z",
"updated": "20220511114202"
},
"Children": [
{
"Type": "NodeText",
"Data": "This agreement applies and only applies to SiYuan (hereinafter referred to as \"the software\"), and Yunnan Liandi Technology Co., Ltd. has the final right to interpret this agreement."
}
]
},
{
"ID": "20220219101351-vq4zmoc",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-vq4zmoc",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "Once you confirm this agreement and start to use the software, you are deemed to fully understand and accept the terms of this agreement. An agreement in the form of electronic text has full and equivalent legal effect as an agreement signed by both parties in writing."
}
]
},
{
"ID": "20220219101351-k90bwhy",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-k90bwhy",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "While enjoying the power conferred by the terms, it is subject to relevant constraints and restrictions. Behaviors outside the scope of the agreement will directly violate this agreement and constitute infringement. We have the right to terminate the authorization at any time, order to stop the damage, and reserve the right to pursue relevant responsibilities."
}
]
},
{
"ID": "20220219101351-4z646n1",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20220219101351-4z646n1",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "Licensed Rights"
}
]
},
{
"ID": "20220219101351-wdm69r4",
"ID": "20220526172102-26zds8b",
"Type": "NodeList",
"ListData": {
"Typ": 1
},
"ListData": {},
"Properties": {
"id": "20220219101351-wdm69r4",
"updated": "20220219101351"
"id": "20220526172102-26zds8b",
"updated": "20220526172141"
},
"Children": [
{
"ID": "20220219101351-uxailqh",
"ID": "20220526172102-w718t2m",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "MS4=",
"Num": 1
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20220219101351-uxailqh"
"id": "20220526172102-w718t2m",
"updated": "20220526172102"
},
"Children": [
{
"ID": "20220219101351-1hq20f9",
"ID": "20220526172102-0850u1g",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-1hq20f9"
"id": "20220526172102-0850u1g",
"updated": "20220526172102"
},
"Children": [
{
"Type": "NodeText",
"Data": "You can use the software within the constraints and limitations stipulated in the agreement"
"Data": "Release date: February 11, 2022"
}
]
}
]
},
{
"ID": "20220219101351-wj1wwxg",
"ID": "20220526172102-ud15cx9",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "Mi4=",
"Num": 2
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20220219101351-wj1wwxg"
"id": "20220526172102-ud15cx9",
"updated": "20220526172141"
},
"Children": [
{
"ID": "20220219101351-kdfxs0r",
"ID": "20220526172102-ltmv72n",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-kdfxs0r"
"id": "20220526172102-ltmv72n",
"updated": "20220526172141"
},
"Children": [
{
"Type": "NodeText",
"Data": "You own the ownership of the content written by using this software, and independently assume the relevant legal obligations related to these content"
"Data": "Latest date: May 26, 2022"
}
]
}
@ -448,149 +389,118 @@
]
},
{
"ID": "20220219101351-zafgped",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20220219101351-zafgped",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "Constraints and Restrictions under the Agreement"
}
]
},
{
"ID": "20220219101351-33mzoxp",
"Type": "NodeList",
"ListData": {
"Typ": 1
},
"Properties": {
"id": "20220219101351-33mzoxp",
"updated": "20220511114148"
},
"Children": [
{
"ID": "20220219101351-6fxrijg",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "MS4=",
"Num": 1
},
"Properties": {
"id": "20220219101351-6fxrijg",
"updated": "20220219101351"
},
"Children": [
{
"ID": "20220219101351-hahd4aj",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-hahd4aj",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "Development of derivative, modified or third-party versions of the software in whole or in part for redistribution without official permission is prohibited"
}
]
}
]
},
{
"ID": "20220511114148-mhyfpm4",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "Mi4=",
"Num": 2
},
"Properties": {
"id": "20220511114148-mhyfpm4",
"updated": "20220511114148"
},
"Children": [
{
"ID": "20220511114148-eri7s9w",
"Type": "NodeParagraph",
"Properties": {
"id": "20220511114148-eri7s9w",
"updated": "20220511114148"
},
"Children": [
{
"Type": "NodeText",
"Data": "It is forbidden to share the user account to use the software"
}
]
}
]
},
{
"ID": "20220219101351-wrfqyzo",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "My4=",
"Num": 3
},
"Properties": {
"id": "20220219101351-wrfqyzo",
"updated": "20220219101351"
},
"Children": [
{
"ID": "20220219101351-yggu31m",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-yggu31m",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "If you fail to comply with the terms of this agreement, your authorization will be terminated, the licensed rights will be withdrawn, and you will assume the corresponding legal responsibility"
}
]
}
]
}
]
},
{
"ID": "20220219101351-nfsf1sy",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20220219101351-nfsf1sy",
"updated": "20220219101351"
},
"Children": [
{
"Type": "NodeText",
"Data": "LIMITED WARRANTY AND DISCLAIMER"
}
]
},
{
"ID": "20220219101351-jhqa4s1",
"ID": "20220526172025-jc682zl",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101351-jhqa4s1",
"updated": "20220219101351"
"id": "20220526172025-jc682zl",
"updated": "20220526172030"
},
"Children": [
{
"Type": "NodeText",
"Data": "THIS SOFTWARE AND THE ACCOMPANYING DOCUMENTS ARE PROVIDED WITHOUT ANY EXPRESS OR IMPLIED INDEMNITY OR WARRANTY."
"Data": "SiYuan uses the "
},
{
"Type": "NodeLink",
"Data": "span",
"Children": [
{
"Type": "NodeOpenBracket"
},
{
"Type": "NodeLinkText",
"Data": "AGPLv3 Open Source License"
},
{
"Type": "NodeCloseBracket"
},
{
"Type": "NodeOpenParen"
},
{
"Type": "NodeLinkDest",
"Data": "https://github.com/siyuan-note/siyuan/blob/master/LICENSE"
},
{
"Type": "NodeCloseParen"
}
]
},
{
"Type": "NodeText",
"Data": ", please be sure to follow it."
}
]
},
{
"ID": "20220526172038-2fqf9le",
"Type": "NodeBlockquote",
"Properties": {
"id": "20220526172038-2fqf9le",
"updated": "20220526172038"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20220526172038-y5qjebj",
"Type": "NodeParagraph",
"Properties": {
"id": "20220526172038-y5qjebj",
"updated": "20220526172038"
},
"Children": [
{
"Type": "NodeText",
"Data": "// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see "
},
{
"Type": "NodeLink",
"Data": "span",
"Children": [
{
"Type": "NodeOpenBracket"
},
{
"Type": "NodeLinkText",
"Data": "https://www.gnu.org/licenses/"
},
{
"Type": "NodeCloseBracket"
},
{
"Type": "NodeOpenParen"
},
{
"Type": "NodeLinkDest",
"Data": "https://www.gnu.org/licenses/"
},
{
"Type": "NodeCloseParen"
}
]
},
{
"Type": "NodeText",
"Data": "."
}
]
}
]
},
{
"ID": "20220526172045-j259gxu",
"Type": "NodeParagraph",
"Properties": {
"id": "20220526172045-j259gxu",
"updated": "20220526191417"
},
"Children": [
{
"Type": "NodeText",
"Data": "For SiYuan cloud service, it is forbidden to share user accounts, otherwise the account will be deactivated."
}
]
}

View file

@ -6,7 +6,7 @@
"id": "20200813163359-v04n73b",
"title": "隐私政策和用户协议",
"type": "doc",
"updated": "20220511113654"
"updated": "20220526191427"
},
"Children": [
{
@ -4171,7 +4171,7 @@
"ListData": {},
"Properties": {
"id": "20220511113456-gcc1dea",
"updated": "20220511113501"
"updated": "20220526171235"
},
"Children": [
{
@ -4211,7 +4211,7 @@
},
"Properties": {
"id": "20220511113456-u7wd33k",
"updated": "20220511113501"
"updated": "20220526171235"
},
"Children": [
{
@ -4219,12 +4219,12 @@
"Type": "NodeParagraph",
"Properties": {
"id": "20220511113456-p9wsd8q",
"updated": "20220511113501"
"updated": "20220526171235"
},
"Children": [
{
"Type": "NodeText",
"Data": "最新日期2022 年 5 月 11 日"
"Data": "最新日期2022 年 5 月 26 日"
}
]
}
@ -4233,294 +4233,118 @@
]
},
{
"ID": "20210104090915-a04zhlh",
"ID": "20220526171251-8nnjevr",
"Type": "NodeParagraph",
"Properties": {
"id": "20210104090915-a04zhlh",
"updated": "20210104090915"
"id": "20220526171251-8nnjevr",
"updated": "20220526171503"
},
"Children": [
{
"Type": "NodeText",
"Data": "本协议适用且仅适用于思源笔记(以下简称为“本软件”),云南链滴科技有限公司对本协议拥有最终解释权。"
"Data": "思源笔记使用 "
},
{
"Type": "NodeLink",
"Data": "span",
"Children": [
{
"Type": "NodeOpenBracket"
},
{
"Type": "NodeLinkText",
"Data": "AGPLv3 开源协议"
},
{
"Type": "NodeCloseBracket"
},
{
"Type": "NodeOpenParen"
},
{
"Type": "NodeLinkDest",
"Data": "https://github.com/siyuan-note/siyuan/blob/master/LICENSE"
},
{
"Type": "NodeCloseParen"
}
]
},
{
"Type": "NodeText",
"Data": ",请务必遵循。"
}
]
},
{
"ID": "20210104090915-hu6xcln",
"ID": "20220526171636-9q1pwf7",
"Type": "NodeBlockquote",
"Properties": {
"id": "20220526171636-9q1pwf7",
"updated": "20220526171646"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20220526171645-5blv3be",
"Type": "NodeParagraph",
"Properties": {
"id": "20220526171645-5blv3be",
"updated": "20220526171646"
},
"Children": [
{
"Type": "NodeText",
"Data": "// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see "
},
{
"Type": "NodeLink",
"Data": "span",
"Children": [
{
"Type": "NodeOpenBracket"
},
{
"Type": "NodeLinkText",
"Data": "https://www.gnu.org/licenses/"
},
{
"Type": "NodeCloseBracket"
},
{
"Type": "NodeOpenParen"
},
{
"Type": "NodeLinkDest",
"Data": "https://www.gnu.org/licenses/"
},
{
"Type": "NodeCloseParen"
}
]
},
{
"Type": "NodeText",
"Data": "."
}
]
}
]
},
{
"ID": "20220526171506-rurnhwq",
"Type": "NodeParagraph",
"Properties": {
"id": "20210104090915-hu6xcln"
"id": "20220526171506-rurnhwq",
"updated": "20220526191427"
},
"Children": [
{
"Type": "NodeText",
"Data": "你一旦确认本协议并开始使用本软件,即被视为完全理解并接受本协议的各项条款。电子文本形式的协议如同双方书面签署的协议一样,具有完全的和等同的法律效力。"
}
]
},
{
"ID": "20210104090915-1k9kae7",
"Type": "NodeParagraph",
"Properties": {
"id": "20210104090915-1k9kae7"
},
"Children": [
{
"Type": "NodeText",
"Data": "在享有条款授予的权力的同时,受到相关的约束和限制。协议许可范围以外的行为,将直接违反本协议并构成侵权,我们有权随时终止授权,责令停止损害,并保留追究相关责任的权力。"
}
]
},
{
"ID": "20210104090915-ak5egyi",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20210104090915-ak5egyi"
},
"Children": [
{
"Type": "NodeHeadingC8hMarker",
"Data": "### "
},
{
"Type": "NodeText",
"Data": "协议许可的权利"
}
]
},
{
"ID": "20210104090915-rczuc0z",
"Type": "NodeList",
"ListData": {
"Typ": 1,
"Tight": true,
"Start": 1,
"Delimiter": 46,
"Padding": 3,
"Marker": "MQ==",
"Num": 1
},
"Properties": {
"id": "20210104090915-rczuc0z"
},
"Children": [
{
"ID": "20210104090915-b9cczi3",
"Type": "NodeListItem",
"Data": "1",
"ListData": {
"Typ": 1,
"Tight": true,
"Start": 1,
"Delimiter": 46,
"Padding": 3,
"Marker": "MQ==",
"Num": 1
},
"Properties": {
"id": "20210104090915-b9cczi3"
},
"Children": [
{
"ID": "20210302223426-70l51cs",
"Type": "NodeParagraph",
"Properties": {
"id": "20210302223426-70l51cs"
},
"Children": [
{
"Type": "NodeText",
"Data": "你可以在协议规定的约束和限制范围内使用本软件"
}
]
}
]
},
{
"ID": "20210104090915-d43yymc",
"Type": "NodeListItem",
"Data": "2",
"ListData": {
"Typ": 1,
"Tight": true,
"Start": 2,
"Delimiter": 46,
"Padding": 3,
"Marker": "Mg==",
"Num": 2
},
"Properties": {
"id": "20210104090915-d43yymc"
},
"Children": [
{
"ID": "20210302223426-6dffke4",
"Type": "NodeParagraph",
"Properties": {
"id": "20210302223426-6dffke4"
},
"Children": [
{
"Type": "NodeText",
"Data": "你拥有使用本软件所撰写的内容的所有权,并独立承担与这些内容的相关法律义务"
}
]
}
]
}
]
},
{
"ID": "20210104090915-x2wdz7e",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20210104090915-x2wdz7e"
},
"Children": [
{
"Type": "NodeHeadingC8hMarker",
"Data": "### "
},
{
"Type": "NodeText",
"Data": "协议规定的约束和限制"
}
]
},
{
"ID": "20210104090915-0ax0fha",
"Type": "NodeList",
"ListData": {
"Typ": 1
},
"Properties": {
"id": "20210104090915-0ax0fha",
"updated": "20220511113654"
},
"Children": [
{
"ID": "20210104090915-fsygbeb",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "MS4=",
"Num": 1
},
"Properties": {
"id": "20210104090915-fsygbeb",
"updated": "20210302223426"
},
"Children": [
{
"ID": "20210302223426-3q23bq2",
"Type": "NodeParagraph",
"Properties": {
"id": "20210302223426-3q23bq2",
"updated": "20210302223426"
},
"Children": [
{
"Type": "NodeText",
"Data": "未经官方许可,禁止在本软件的整体或任何部分基础上发展派生版本、修改版本或第三方版本用于重新分发"
}
]
}
]
},
{
"ID": "20220511113528-mrrcm2w",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "Mi4=",
"Num": 2
},
"Properties": {
"id": "20220511113528-mrrcm2w",
"updated": "20220511113654"
},
"Children": [
{
"ID": "20220511113528-yf5id9c",
"Type": "NodeParagraph",
"Properties": {
"id": "20220511113528-yf5id9c",
"updated": "20220511113654"
},
"Children": [
{
"Type": "NodeText",
"Data": "禁止共享用户账号使用本软件"
}
]
}
]
},
{
"ID": "20210104090915-q19dcjt",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "My4=",
"Num": 3
},
"Properties": {
"id": "20210104090915-q19dcjt",
"updated": "20210302223426"
},
"Children": [
{
"ID": "20210302223426-h2ew654",
"Type": "NodeParagraph",
"Properties": {
"id": "20210302223426-h2ew654",
"updated": "20210302223426"
},
"Children": [
{
"Type": "NodeText",
"Data": "如果你未能遵守本协议的条款,你的授权将被终止,所被许可的权利将被收回,并承担相应法律责任"
}
]
}
]
}
]
},
{
"ID": "20210104090915-n97gco7",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20210104090915-n97gco7"
},
"Children": [
{
"Type": "NodeHeadingC8hMarker",
"Data": "### "
},
{
"Type": "NodeText",
"Data": "有限担保和免责声明"
}
]
},
{
"ID": "20210104090915-p0f6gq3",
"Type": "NodeParagraph",
"Properties": {
"id": "20210104090915-p0f6gq3"
},
"Children": [
{
"Type": "NodeText",
"Data": "本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的。"
"Data": "对于思源笔记云端服务,禁止共享用户账号,否则账号会被停用。"
}
]
}

View file

@ -5,7 +5,7 @@
"icon": "1f4c4",
"id": "20211226114339-dk0gtpr",
"title": "隱私政策和用戶協議",
"updated": "20220511113836"
"updated": "20220526191434"
},
"Children": [
{
@ -3323,7 +3323,7 @@
},
"Properties": {
"id": "20220212225553-ud2rl66",
"updated": "20220511113836"
"updated": "20220526171944"
},
"Children": [
{
@ -4115,7 +4115,7 @@
"Type": "NodeListItem",
"ListData": {
"BulletChar": 42,
"Marker": "Kg=="
"Marker": "NC4="
},
"Properties": {
"id": "20220511113836-twa99rf",
@ -4139,177 +4139,148 @@
]
},
{
"ID": "20220219101327-c97vfrq",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101327-c97vfrq",
"updated": "20220219101327"
},
"Children": [
{
"Type": "NodeText",
"Data": "本協議適用且僅適用於思源筆記(以下簡稱為“本軟件”),雲南鏈滴科技有限公司對本協議擁有最終解釋權。"
}
]
},
{
"ID": "20220219101327-avt2nxg",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101327-avt2nxg",
"updated": "20220219101327"
},
"Children": [
{
"Type": "NodeText",
"Data": "你一旦確認本協議並開始使用本軟件,即被視為完全理解並接受本協議的各項條款。電子文本形式的協議如同雙方書面簽署的協議一樣,具有完全的和等同的法律效力。"
}
]
},
{
"ID": "20220219101327-mu3z2n3",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101327-mu3z2n3",
"updated": "20220219101327"
},
"Children": [
{
"Type": "NodeText",
"Data": "在享有條款授予的權力的同時,受到相關的約束和"
},
{
"Type": "NodeText",
"Data": "限制"
},
{
"Type": "NodeText",
"Data": "。協議許可範圍以外的行為,將直接違反本協議並構成侵權,我們有權隨時終止授權,責令停止損害,並保留追究相關責任的權力。"
}
]
},
{
"ID": "20220219101327-3fyi23b",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20220219101327-3fyi23b",
"updated": "20220219101327"
},
"Children": [
{
"Type": "NodeText",
"Data": "協議許可的權利"
}
]
},
{
"ID": "20220511113820-fwgcxhr",
"ID": "20220526171828-dsh8zoi",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "MS4=",
"Num": 1
"BulletChar": 42,
"Marker": "Kg=="
},
"Properties": {
"id": "20220511113820-fwgcxhr",
"updated": "20220511113820"
"id": "20220526171828-dsh8zoi",
"updated": "20220526171944"
},
"Children": [
{
"ID": "20220511113820-14zy4is",
"ID": "20220526171828-7yiz1nj",
"Type": "NodeParagraph",
"Properties": {
"id": "20220511113820-14zy4is",
"updated": "20220511113820"
"id": "20220526171828-7yiz1nj",
"updated": "20220526171944"
},
"Children": [
{
"Type": "NodeText",
"Data": "你可以在協議規定的約束和限制範圍內使用本軟件"
"Data": "最新日期2022 年 5 月 26 日"
}
]
}
]
}
]
},
{
"ID": "20220526171900-uln5cce",
"Type": "NodeParagraph",
"Properties": {
"id": "20220526171900-uln5cce",
"updated": "20220526171901"
},
"Children": [
{
"Type": "NodeText",
"Data": "思源筆記使用 "
},
{
"ID": "20220219101327-64p7fiz",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Type": "NodeLink",
"Data": "span",
"Children": [
{
"Type": "NodeOpenBracket"
},
{
"Type": "NodeLinkText",
"Data": "AGPLv3 開源協議"
},
{
"Type": "NodeCloseBracket"
},
{
"Type": "NodeOpenParen"
},
{
"Type": "NodeLinkDest",
"Data": "https://github.com/siyuan-note/siyuan/blob/master/LICENSE"
},
{
"Type": "NodeCloseParen"
}
]
},
{
"Type": "NodeText",
"Data": ",請務必遵循。"
}
]
},
{
"ID": "20220526171914-w0rh0tr",
"Type": "NodeBlockquote",
"Properties": {
"id": "20220526171914-w0rh0tr",
"updated": "20220526171914"
},
"Children": [
{
"Type": "NodeBlockquoteMarker",
"Data": "\u003e"
},
{
"ID": "20220526171914-pf17jbe",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101327-64p7fiz",
"updated": "20220219101327"
"id": "20220526171914-pf17jbe",
"updated": "20220526171914"
},
"Children": [
{
"Type": "NodeText",
"Data": "協議規定的約束和"
"Data": "// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see "
},
{
"Type": "NodeLink",
"Data": "span",
"Children": [
{
"Type": "NodeOpenBracket"
},
{
"Type": "NodeLinkText",
"Data": "https://www.gnu.org/licenses/"
},
{
"Type": "NodeCloseBracket"
},
{
"Type": "NodeOpenParen"
},
{
"Type": "NodeLinkDest",
"Data": "https://www.gnu.org/licenses/"
},
{
"Type": "NodeCloseParen"
}
]
},
{
"Type": "NodeText",
"Data": "限制"
"Data": "."
}
]
},
}
]
},
{
"ID": "20220526171930-a4yynx6",
"Type": "NodeParagraph",
"Properties": {
"id": "20220526171930-a4yynx6",
"updated": "20220526191434"
},
"Children": [
{
"ID": "20220511113804-hd2wvlx",
"Type": "NodeListItem",
"ListData": {
"Typ": 1,
"Delimiter": 46,
"Marker": "MS4=",
"Num": 1
},
"Properties": {
"id": "20220511113804-hd2wvlx",
"updated": "20220511113804"
},
"Children": [
{
"ID": "20220511113804-jvi5ugm",
"Type": "NodeParagraph",
"Properties": {
"id": "20220511113804-jvi5ugm",
"updated": "20220511113804"
},
"Children": [
{
"Type": "NodeText",
"Data": "未經官方許可,禁止在本軟件的整體或任何部分基礎上發展派生版本、修改版本或第三方版本用於重新分發"
}
]
}
]
},
{
"ID": "20220219101327-kj36lkk",
"Type": "NodeHeading",
"HeadingLevel": 3,
"Properties": {
"id": "20220219101327-kj36lkk",
"updated": "20220219101327"
},
"Children": [
{
"Type": "NodeText",
"Data": "有限擔保和免責聲明"
}
]
},
{
"ID": "20220219101327-07qxlkd",
"Type": "NodeParagraph",
"Properties": {
"id": "20220219101327-07qxlkd",
"updated": "20220219101327"
},
"Children": [
{
"Type": "NodeText",
"Data": "本軟件及所附帶的文件是作為不提供任何明確的或隱含的賠償或擔保的形式提供的。"
}
]
"Type": "NodeText",
"Data": "對於思源筆記云端服務,禁止共享用戶賬號,否則賬號會被停用。"
}
]
}

View file

@ -386,7 +386,6 @@ declare interface IBlockTree {
nodeType: string,
subType: string,
name: string,
full: string,
type: string,
depth: number,
url?: string,

View file

@ -71,7 +71,7 @@ data-type="${item.nodeType}"
data-subtype="${item.subType}"
${item.label ? "data-label='" + item.label + "'" : ""}>
<span style="padding-left: ${item.depth * 16}px" class="b3-list-item__toggle">
<svg data-id="${item.full || (item.name + item.depth)}" class="b3-list-item__arrow ${((item.children && item.children.length > 0) || (item.blocks && item.blocks.length > 0)) ? "b3-list-item__arrow--open" : "fn__hidden"}"><use xlink:href="#iconRight"></use></svg>
<svg data-id="${encodeURIComponent(item.name + item.depth)}" class="b3-list-item__arrow ${((item.children && item.children.length > 0) || (item.blocks && item.blocks.length > 0)) ? "b3-list-item__arrow--open" : "fn__hidden"}"><use xlink:href="#iconRight"></use></svg>
</span>
${iconHTML}
<span class="b3-list-item__text">${item.name}</span>

View file

@ -1,4 +0,0 @@
echo 'Building UI'
cd app
call npm install && npm run build
cd ..

View file

@ -1,6 +0,0 @@
#!/bin/bash
echo 'Building UI'
cd app
npm install && npm run build
cd ..

View file

@ -100,6 +100,9 @@ func NetImg2LocalAssets(rootID string) (err error) {
} else {
name = path.Base(u)
}
if strings.Contains(name, "#") {
name = name[:strings.Index(name, "#")]
}
name, _ = url.PathUnescape(name)
ext := path.Ext(name)
if "" == ext {

View file

@ -64,7 +64,6 @@ type Path struct {
ID string `json:"id"` // 块 ID
Box string `json:"box"` // 块 Box
Name string `json:"name"` // 当前路径
Full string `json:"full"` // 全路径
Type string `json:"type"` // "path"
NodeType string `json:"nodeType"` // 节点类型
SubType string `json:"subType"` // 节点子类型

View file

@ -17,13 +17,9 @@
package model
import (
"bytes"
"context"
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path"
@ -662,7 +658,7 @@ func localUpsertRemoveListOSS(localDirPath string, cloudFileList map[string]*Clo
return nil
}
localHash, hashErr := GetEtag(path)
localHash, hashErr := util.GetEtag(path)
if nil != hashErr {
util.LogErrorf("get local file [%s] etag failed: %s", path, hashErr)
return nil
@ -696,7 +692,7 @@ func cloudUpsertRemoveListOSS(localDirPath string, cloudFileList map[string]*Clo
continue
}
localHash, hashErr := GetEtag(localCheckPath)
localHash, hashErr := util.GetEtag(localCheckPath)
if nil != hashErr {
util.LogErrorf("get local file [%s] hash failed: %s", localCheckPath, hashErr)
err = hashErr
@ -760,62 +756,3 @@ func putFileToCloud(filePath, key, upToken string) (err error) {
}
return
}
// 以下是七牛云 Hash 算法实现 https://github.com/qiniu/qetag/blob/master/qetag.go
func GetEtag(filename string) (etag string, err error) {
f, err := os.Open(filename)
if err != nil {
return
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return
}
fsize := fi.Size()
blockCnt := BlockCount(fsize)
sha1Buf := make([]byte, 0, 21)
if blockCnt <= 1 { // file size <= 4M
sha1Buf = append(sha1Buf, 0x16)
sha1Buf, err = CalSha1(sha1Buf, f)
if err != nil {
return
}
} else { // file size > 4M
sha1Buf = append(sha1Buf, 0x96)
sha1BlockBuf := make([]byte, 0, blockCnt*20)
for i := 0; i < blockCnt; i++ {
body := io.LimitReader(f, BLOCK_SIZE)
sha1BlockBuf, err = CalSha1(sha1BlockBuf, body)
if err != nil {
return
}
}
sha1Buf, _ = CalSha1(sha1Buf, bytes.NewReader(sha1BlockBuf))
}
etag = base64.URLEncoding.EncodeToString(sha1Buf)
return
}
const (
BLOCK_BITS = 22 // Indicate that the blocksize is 4M
BLOCK_SIZE = 1 << BLOCK_BITS
)
func BlockCount(fsize int64) int {
return int((fsize + (BLOCK_SIZE - 1)) >> BLOCK_BITS)
}
func CalSha1(b []byte, r io.Reader) ([]byte, error) {
h := sha1.New()
_, err := io.Copy(h, r)
if err != nil {
return nil, err
}
return h.Sum(b), nil
}

View file

@ -82,30 +82,22 @@ func Outline(rootID string) (ret []*Path, err error) {
}
ret = toFlatTree(blocks, 0, "outline")
if 0 < len(ret) {
children := ret[0].Blocks
ret = nil
for _, b := range children {
resetDepth(b, 0)
ret = append(ret, &Path{
ID: b.ID,
Box: b.Box,
Name: b.Content,
Type: b.Type,
SubType: b.SubType,
Blocks: b.Children,
Depth: 0,
Count: b.Count,
})
}
}
resetDepth(ret)
return
}
func resetDepth(b *Block, depth int) {
b.Depth = depth
b.Count = len(b.Children)
for _, c := range b.Children {
resetDepth(c, depth+1)
func resetDepth(paths []*Path) {
for _, p := range paths {
for _, b := range p.Blocks {
resetDepth0(b, p.Depth)
}
}
}
func resetDepth0(b *Block, depth int) {
b.Depth = depth + 1
b.Count = len(b.Children)
for _, c := range b.Children {
resetDepth0(c, depth+1)
}
}

View file

@ -571,7 +571,7 @@ func genCloudIndex(localDirPath string, excludes map[string]bool) (err error) {
return nil
}
hash, hashErr := GetEtag(path)
hash, hashErr := util.GetEtag(path)
if nil != hashErr {
util.LogErrorf("get file [%s] hash failed: %s", path, hashErr)
return hashErr

View file

@ -17,9 +17,7 @@
package model
import (
"crypto/sha256"
"errors"
"fmt"
"io"
"os"
"path"
@ -58,20 +56,22 @@ func InsertLocalAssets(id string, assetPaths []string) (succMap map[string]inter
continue
}
var f *os.File
f, err = os.Open(p)
if nil != err {
fi, statErr := os.Stat(p)
if nil != statErr {
err = statErr
return
}
f, openErr := os.Open(p)
if nil != openErr {
err = openErr
return
}
hash, hashErr := util.GetEtagByHandle(f, fi.Size())
if nil != hashErr {
f.Close()
return
}
var data []byte
data, err = io.ReadAll(f)
f.Close()
if nil != err {
return
}
hash := fmt.Sprintf("%x", sha256.Sum256(data))
if existAsset := sql.QueryAssetByHash(hash); nil != existAsset {
// 已经存在同样数据的资源文件的话不重复保存
succMap[baseName] = existAsset.Path
@ -80,9 +80,15 @@ func InsertLocalAssets(id string, assetPaths []string) (succMap map[string]inter
fName = fName[0 : len(fName)-len(ext)]
fName = fName + "-" + ast.NewNodeID() + ext
writePath := filepath.Join(assets, fName)
if err = gulu.File.WriteFileSafer(writePath, data, 0644); nil != err {
if _, err = f.Seek(0, io.SeekStart); nil != err {
f.Close()
return
}
if err = gulu.File.WriteFileSaferByReader(writePath, f, 0644); nil != err {
f.Close()
return
}
f.Close()
succMap[baseName] = "assets/" + fName
}
}
@ -134,22 +140,21 @@ func Upload(c *gin.Context) {
ext = strings.ToLower(ext)
fName += ext
baseName := fName
f, err := file.Open()
if nil != err {
f, openErr := file.Open()
if nil != openErr {
errFiles = append(errFiles, fName)
ret.Msg = err.Error()
ret.Msg = openErr.Error()
break
}
data, err := io.ReadAll(f)
if nil != err {
hash, hashErr := util.GetEtagByHandle(f, file.Size)
if nil != hashErr {
errFiles = append(errFiles, fName)
ret.Msg = err.Error()
f.Close()
break
}
f.Close()
hash := fmt.Sprintf("%x", sha256.Sum256(data))
if existAsset := sql.QueryAssetByHash(hash); nil != existAsset {
// 已经存在同样数据的资源文件的话不重复保存
succMap[baseName] = existAsset.Path
@ -168,11 +173,19 @@ func Upload(c *gin.Context) {
}
}
writePath := filepath.Join(assetsDirPath, fName)
if err = gulu.File.WriteFileSafer(writePath, data, 0644); nil != err {
if _, err = f.Seek(0, io.SeekStart); nil != err {
errFiles = append(errFiles, fName)
ret.Msg = err.Error()
f.Close()
break
}
if err = gulu.File.WriteFileSaferByReader(writePath, f, 0644); nil != err {
errFiles = append(errFiles, fName)
ret.Msg = err.Error()
f.Close()
break
}
f.Close()
succMap[baseName] = "assets/" + fName
}
}

View file

@ -44,7 +44,7 @@ var cookieStore = cookie.NewStore([]byte("ATN51UlxVq1Gcvdf"))
func Serve(fastMode bool) {
gin.SetMode(gin.ReleaseMode)
ginServer := gin.New()
ginServer.MaxMultipartMemory = 1024 * 1024 * 1024 * 4
ginServer.MaxMultipartMemory = 1024 * 1024 * 32 // 插入较大的资源文件时内存占用较大 https://github.com/siyuan-note/siyuan/issues/5023
ginServer.Use(gin.Recovery())
ginServer.Use(cors.Default())
ginServer.Use(gzip.Gzip(gzip.DefaultCompression, gzip.WithExcludedExtensions([]string{".pdf", ".mp3", ".wav", ".ogg", ".mov", ".weba", ".mkv", ".mp4", ".webm"})))

View file

@ -20,7 +20,6 @@ import (
"crypto/sha256"
"database/sql"
"fmt"
"os"
"path/filepath"
"strings"
@ -71,12 +70,11 @@ func docTitleImgAsset(root *ast.Node) *Asset {
}
var hash string
var err error
absPath := filepath.Join(util.DataDir, p)
if data, err := os.ReadFile(absPath); nil != err {
if hash, err = util.GetEtag(absPath); nil != err {
util.LogErrorf("read asset [%s] data failed: %s", absPath, err)
hash = fmt.Sprintf("%x", sha256.Sum256([]byte(gulu.Rand.String(7))))
} else {
hash = fmt.Sprintf("%x", sha256.Sum256(data))
}
name, _ := util.LastID(p)
asset := &Asset{

View file

@ -18,10 +18,8 @@ package sql
import (
"bytes"
"crypto/sha256"
"database/sql"
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
@ -522,12 +520,12 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
}
var hash string
var hashErr error
if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp {
if !gulu.File.IsDir(lp) {
if data, err := os.ReadFile(lp); nil != err {
util.LogErrorf("read asset [%s] data failed: %s", lp, err)
} else {
hash = fmt.Sprintf("%x", sha256.Sum256(data))
hash, hashErr = util.GetEtag(lp)
if nil != hashErr {
util.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr)
}
}
}
@ -597,11 +595,11 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
dest := string(src)
var hash string
var hashErr error
if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp {
if data, err := os.ReadFile(lp); nil != err {
util.LogErrorf("read asset [%s] data failed: %s", lp, err)
} else {
hash = fmt.Sprintf("%x", sha256.Sum256(data))
hash, hashErr = util.GetEtag(lp)
if nil != hashErr {
util.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr)
}
}

88
kernel/util/etag.go Normal file
View file

@ -0,0 +1,88 @@
// SiYuan - Build Your Eternal Digital Garden
// Copyright (c) 2020-present, b3log.org
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package util
import (
"bytes"
"crypto/sha1"
"encoding/base64"
"io"
"os"
)
// 以下是七牛云 Hash 算法实现 https://github.com/qiniu/qetag/blob/master/qetag.go
func GetEtagByHandle(f io.Reader, size int64) (etag string, err error) {
blockCnt := BlockCount(size)
sha1Buf := make([]byte, 0, 21)
if blockCnt <= 1 { // file size <= 4M
sha1Buf = append(sha1Buf, 0x16)
sha1Buf, err = CalSha1(sha1Buf, f)
if err != nil {
return
}
} else { // file size > 4M
sha1Buf = append(sha1Buf, 0x96)
sha1BlockBuf := make([]byte, 0, blockCnt*20)
for i := 0; i < blockCnt; i++ {
body := io.LimitReader(f, BLOCK_SIZE)
sha1BlockBuf, err = CalSha1(sha1BlockBuf, body)
if err != nil {
return
}
}
sha1Buf, _ = CalSha1(sha1Buf, bytes.NewReader(sha1BlockBuf))
}
etag = base64.URLEncoding.EncodeToString(sha1Buf)
return
}
func GetEtag(filename string) (etag string, err error) {
f, err := os.Open(filename)
if err != nil {
return
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return
}
etag, err = GetEtagByHandle(f, fi.Size())
return
}
const (
BLOCK_BITS = 22 // Indicate that the blocksize is 4M
BLOCK_SIZE = 1 << BLOCK_BITS
)
func BlockCount(fsize int64) int {
return int((fsize + (BLOCK_SIZE - 1)) >> BLOCK_BITS)
}
func CalSha1(b []byte, r io.Reader) ([]byte, error) {
h := sha1.New()
_, err := io.Copy(h, r)
if err != nil {
return nil, err
}
return h.Sum(b), nil
}

View file

@ -2,9 +2,10 @@
echo 'Building UI'
cd app
npm run build
npm install && npm run build
cd ..
echo 'Cleaning Builds'
rm -rf app/build
rm -rf app/kernel-darwin
rm -rf app/kernel-darwin-arm64

View file

@ -1,7 +1,11 @@
#!/bin/bash
./build-ui.sh
echo 'Building UI'
cd app
npm install && npm run build
cd ..
echo 'Cleaning Builds'
rm -rf app/build
rm -rf app/kernel-linux

View file

@ -1,4 +1,10 @@
echo 'Building UI'
cd app
call npm install
call npm run build
cd ..
echo 'Cleaning Builds'
del /S /Q /F app\build 1>nul
del /S /Q /F app\kernel 1>nul
del /S /Q /F app\kernel32 1>nul