Compare commits

...

114 commits

Author SHA1 Message Date
Daniel
f1c91863b9
🔖 Release v3.3.2
Some checks failed
Release Docker Image / build (push) Has been cancelled
Signed-off-by: Daniel <845765@qq.com>
2025-09-09 18:15:27 +08:00
Daniel
8a9e746891
🎨 Clean code
Signed-off-by: Daniel <845765@qq.com>
2025-09-09 18:11:49 +08:00
Jeffrey Chen
517f5c8453
🎨 Hide the separator line in the top bar plugin menu in publish service (#15809) 2025-09-09 18:08:21 +08:00
Vanessa
88431279bf 🎨 https://github.com/siyuan-note/siyuan/issues/15806 2025-09-09 17:32:35 +08:00
Vanessa
dc656d83a2 🎨 https://github.com/siyuan-note/siyuan/issues/15806 2025-09-09 16:43:39 +08:00
Vanessa
b69fd04137 🎨 https://github.com/siyuan-note/siyuan/issues/15806 2025-09-09 10:18:44 +08:00
Vanessa
ff909fa149 🎨 https://github.com/siyuan-note/siyuan/issues/15805 2025-09-09 10:02:51 +08:00
Vanessa
bfe50d9009 🚨 2025-09-09 09:29:00 +08:00
Daniel
93422c134d
🎨 Add field disabledInPublish to the code snippet to indicate whether it is disabled in the publish service https://github.com/siyuan-note/siyuan/issues/15806
Signed-off-by: Daniel <845765@qq.com>
2025-09-09 09:18:12 +08:00
Daniel
2f70ef43a1
🎨 Clean code
Signed-off-by: Daniel <845765@qq.com>
2025-09-09 09:07:23 +08:00
Daniel
5f6ddb4655
📝 Update changelogs
Signed-off-by: Daniel <845765@qq.com>
2025-09-08 19:41:02 +08:00
Daniel
39c4b3325e
🧑‍💻 Improve kernel API appendBlock, insertBlock and prependBlock https://github.com/siyuan-note/siyuan/issues/15798
Signed-off-by: Daniel <845765@qq.com>
2025-09-08 19:24:41 +08:00
Vanessa
393c53941a
🎨 https://github.com/siyuan-note/siyuan/issues/15801
Signed-off-by: Daniel <845765@qq.com>
2025-09-08 17:39:03 +08:00
Daniel
a4f03191fa
🎨 https://github.com/siyuan-note/siyuan/issues/15777 2025-09-08 10:58:58 +08:00
Vanessa
de9e648e9e 🎨 https://github.com/siyuan-note/siyuan/issues/15782 2025-09-08 10:52:40 +08:00
Vanessa
c1f14a33d9 🎨 https://github.com/siyuan-note/siyuan/pull/15731 2025-09-08 10:06:52 +08:00
Jeffrey Chen
adca241ed5
🎨 Improve slash menu (#15731)
fix https://github.com/siyuan-note/siyuan/issues/12518
2025-09-08 09:57:36 +08:00
Vanessa
006da6bc90 🎨 https://github.com/siyuan-note/siyuan/issues/15782 2025-09-08 09:48:36 +08:00
Vanessa
490234caab 🚨 2025-09-08 09:44:52 +08:00
Daniel
80c357564d
🎨 Regen pnpm-lock.yaml 2025-09-07 21:47:41 +08:00
Daniel
6852a49620
🎨 Improve build script 2025-09-07 21:40:17 +08:00
Daniel
93591ad44e
🐛 Fix NPE https://github.com/siyuan-note/siyuan/issues/15796 2025-09-07 21:05:54 +08:00
Daniel
6510d7dbf0
🧑‍💻 Improve kernel API appendBlock and insertBlock https://github.com/siyuan-note/siyuan/issues/15798 2025-09-07 20:58:38 +08:00
Daniel
29244a1f8c
🧑‍💻 https://github.com/siyuan-note/siyuan/issues/15798 2025-09-07 19:20:44 +08:00
Daniel
a85467751f
⬆️ Upgrade lute 2025-09-07 19:02:52 +08:00
Vanessa
14251d8dae 🎨 https://github.com/siyuan-note/siyuan/pull/15772 2025-09-07 18:40:12 +08:00
Jeffrey Chen
52a4815419
🐛 Improve database date field (#15772)
fix https://github.com/siyuan-note/siyuan/issues/13252 , https://github.com/siyuan-note/siyuan/issues/15747
2025-09-07 18:37:33 +08:00
Vanessa
45a6a190d0 🎨 https://github.com/siyuan-note/siyuan/issues/15185 2025-09-07 18:14:46 +08:00
Vanessa
c1a4aa3128 🐛 https://github.com/siyuan-note/siyuan/issues/15791 2025-09-07 11:01:11 +08:00
Vanessa
0fce405a05 Merge remote-tracking branch 'origin/dev' into dev 2025-09-07 09:59:48 +08:00
Vanessa
fe143bcb12 🎨 https://github.com/siyuan-note/siyuan/issues/8019 2025-09-07 09:59:35 +08:00
Daniel
0ad7c4cf23
🎨 Improve open the user guide https://github.com/siyuan-note/siyuan/issues/15792 2025-09-07 09:35:48 +08:00
Vanessa
c326989391 🎨 https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 22:47:16 +08:00
Vanessa
468b670bcc 🎨 https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 22:33:31 +08:00
Vanessa
4e4398ef47 🎨 https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 18:31:38 +08:00
Vanessa
fc1cbf46aa Merge remote-tracking branch 'origin/dev' into dev 2025-09-06 18:02:31 +08:00
Vanessa
80cccd41b5 🎨 https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 18:02:18 +08:00
Daniel
68991a6aef
🎨 Copy/Cut folded heading changed to copy/cut Headings and Bottom Blocks and support multiple headings copy/cut https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 17:30:35 +08:00
Daniel
2a8b47b518
🎨 Copy/Cut folded heading changed to copy/cut Headings and Bottom Blocks and support multiple headings copy/cut https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 17:15:42 +08:00
Daniel
8ad3cb00ad
🎨 Copy/Cut folded heading changed to copy/cut Headings and Bottom Blocks and support multiple headings copy/cut https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 17:11:21 +08:00
Daniel
c55c413365
🎨 Copy/Cut folded heading changed to copy/cut Headings and Bottom Blocks and support multiple headings copy/cut https://github.com/siyuan-note/siyuan/issues/8019 2025-09-06 17:10:43 +08:00
Vanessa
4767e399e2 Merge remote-tracking branch 'origin/dev' into dev 2025-09-06 10:22:29 +08:00
Vanessa
5ade06a3b6 🎨 https://github.com/siyuan-note/siyuan/issues/15609 2025-09-06 10:22:16 +08:00
Daniel
8ebb617072
📝 Database rollup field filtering rules support "Any", "All", and "None" https://github.com/siyuan-note/siyuan/issues/15609 2025-09-06 08:43:59 +08:00
Daniel
305bd9dfb0
🎨 Improve duplicating doc/av https://github.com/siyuan-note/siyuan/issues/15786 2025-09-06 08:28:54 +08:00
Vanessa
d2f990a830 🎨 https://github.com/siyuan-note/siyuan/issues/15609 2025-09-05 23:44:46 +08:00
Vanessa
5775aa9734 Merge remote-tracking branch 'origin/dev' into dev 2025-09-05 23:38:13 +08:00
Vanessa
80f1c6c3ec 🎨 https://github.com/siyuan-note/siyuan/issues/15609 2025-09-05 23:37:58 +08:00
Daniel
f220e3627f
📝 Database rollup field filtering rules support "Any", "All", and "None" https://github.com/siyuan-note/siyuan/issues/15609 2025-09-05 23:15:20 +08:00
Daniel
1fb4ed980b
⬆️ Upgrade lute 2025-09-05 22:51:41 +08:00
Daniel
04bf9e9848
🎨 Improve av https://github.com/siyuan-note/siyuan/issues/15775 2025-09-05 17:44:03 +08:00
Daniel
9447f1c5a8
🎨 Clean code 2025-09-05 17:38:46 +08:00
Vanessa
afa74ebb4b 🎨 https://github.com/siyuan-note/siyuan/issues/15771 2025-09-05 17:16:48 +08:00
Jeffrey Chen
17a96ee1b1
🎨 Dragging multiple files into the editor will cause them to be opened by the default program (#15773) 2025-09-05 12:10:44 +08:00
Vanessa
647204eee1 🎨 https://github.com/siyuan-note/siyuan/issues/15733 2025-09-05 12:01:46 +08:00
Vanessa
4eb91f2e40 Merge remote-tracking branch 'origin/dev' into dev 2025-09-05 11:26:31 +08:00
Vanessa
d48e3d5211 🎨 https://github.com/siyuan-note/siyuan/issues/15771 2025-09-05 11:26:18 +08:00
Jeffrey Chen
59265bfc94
📝 Improve text (#15774) 2025-09-05 10:27:07 +08:00
Daniel
16913fb065
⬆️ Upgrade pnpm 2025-09-05 10:16:25 +08:00
Vanessa
65b52a2bc6 🎨 https://github.com/siyuan-note/siyuan/issues/15771 2025-09-05 08:59:52 +08:00
Vanessa
ac6b1d6689 🎨 https://github.com/siyuan-note/siyuan/issues/15768 2025-09-04 21:45:25 +08:00
Vanessa
7ae90058c3 🎨 https://github.com/siyuan-note/siyuan/issues/15771 2025-09-04 20:48:40 +08:00
Daniel
fdfd453e2b
🎨 https://github.com/siyuan-note/siyuan/issues/15748 2025-09-04 19:53:53 +08:00
Vanessa
0aa5624495 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 19:48:31 +08:00
Vanessa
0b3cef8964 🎨 https://github.com/siyuan-note/siyuan/issues/15748 2025-09-04 19:48:18 +08:00
Daniel
2c5d4d47a4
🎨 https://github.com/siyuan-note/siyuan/issues/15749 2025-09-04 19:38:49 +08:00
Vanessa
3379d29e67 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 18:24:04 +08:00
Vanessa
ba95f45b92 🎨 https://github.com/siyuan-note/siyuan/issues/15751 2025-09-04 18:23:51 +08:00
Daniel
ed78e67af2
🎨 Clean code 2025-09-04 18:08:45 +08:00
Daniel
ba10d96a10
Revert "🎨 Add tags to the database when binding blocks to the database https://github.com/siyuan-note/siyuan/issues/15757"
This reverts commit 4d8bc1672c.
2025-09-04 18:00:47 +08:00
Daniel
4d8bc1672c
🎨 Add tags to the database when binding blocks to the database https://github.com/siyuan-note/siyuan/issues/15757 2025-09-04 17:43:18 +08:00
Vanessa
e91a37a98b 🎨 https://github.com/siyuan-note/siyuan/issues/15760 2025-09-04 16:38:07 +08:00
Vanessa
f6bd240a85 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 16:31:24 +08:00
Vanessa
c08f88156f 🎨 https://github.com/siyuan-note/siyuan/issues/15750 2025-09-04 16:31:12 +08:00
Daniel
74826fc0ce
🎨 Improve database performance https://github.com/siyuan-note/siyuan/issues/15764 2025-09-04 16:17:39 +08:00
Daniel
e1bb9874be
🎨 Clean code 2025-09-04 16:15:03 +08:00
Daniel
2b85cb1b6c
🎨 Improve database performance https://github.com/siyuan-note/siyuan/issues/15764 2025-09-04 16:14:38 +08:00
Daniel
cd8c3a41e6
🎨 Clean code 2025-09-04 15:40:23 +08:00
Jeffrey Chen
bdace41d97
📝 Improve User Guide (#15767)
https://github.com/siyuan-note/siyuan/issues/14430
2025-09-04 15:40:06 +08:00
Vanessa
ea2294e901 🎨 https://github.com/siyuan-note/siyuan/issues/15761 2025-09-04 12:11:22 +08:00
Vanessa
868c9d980a Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 10:30:18 +08:00
Vanessa
2d53c81026 Merge remote-tracking branch 'origin/dev' into dev 2025-09-04 10:30:06 +08:00
Daniel
6ff4439be3
🧑‍💻 Add field disabledInPublish to the marketplace package metadata to indicate whether it is disabled in the publishing service https://github.com/siyuan-note/siyuan/issues/11730 2025-09-04 10:29:58 +08:00
Vanessa
d47a8ffe02 🎨 https://github.com/siyuan-note/siyuan/issues/15639 2025-09-04 10:29:54 +08:00
Daniel
9410a70a2b
🎨 Add marketplace package config item minAppVersion https://github.com/siyuan-note/siyuan/issues/8330 2025-09-04 10:22:57 +08:00
Daniel
3c3f34442f
🎨 Improve bazaar package 2025-09-04 10:14:41 +08:00
Daniel
9dc6f56bff
🎨 Improve bazaar package 2025-09-04 10:14:21 +08:00
Vanessa
22fdaa71ef 🎨 https://github.com/siyuan-note/siyuan/issues/15759 2025-09-03 23:44:04 +08:00
Daniel
fd7dba5ed4
🎨 Update text https://github.com/siyuan-note/siyuan/issues/15759 2025-09-03 23:26:43 +08:00
Daniel
d6a33c8c02
⬆️ Upgrade kernel deps 2025-09-03 22:10:26 +08:00
Daniel
6f2b8e47ae
⬆️ Upgrade lute 2025-09-03 21:50:57 +08:00
Vanessa
aa47a93501 Merge remote-tracking branch 'origin/dev' into dev 2025-09-03 21:36:30 +08:00
Vanessa
0b33edd213 🐛 https://github.com/siyuan-note/siyuan/issues/15741 2025-09-03 21:36:17 +08:00
Daniel
fe3ee14417
🎨 After dragging database entries across groups, groups in other views need to be updated https://github.com/siyuan-note/siyuan/issues/15755 2025-09-03 21:30:50 +08:00
Daniel
543ea20686
⬆️ Upgrade lute 2025-09-03 21:15:50 +08:00
Vanessa
f3358cc8b6 🐛 https://github.com/siyuan-note/siyuan/issues/15756 2025-09-03 21:12:56 +08:00
Vanessa
356356d888 🎨 https://github.com/siyuan-note/siyuan/issues/15226 2025-09-03 20:49:12 +08:00
Vanessa
78a7491173 Merge remote-tracking branch 'origin/dev' into dev 2025-09-03 18:28:26 +08:00
Vanessa
042768550d 🎨 https://github.com/siyuan-note/siyuan/issues/15699 2025-09-03 18:26:53 +08:00
Daniel
cfb976eb89
🐛 PDF files with too long file names cannot generate annotated images https://github.com/siyuan-note/siyuan/issues/15739 https://github.com/siyuan-note/siyuan/issues/10666 2025-09-03 17:37:27 +08:00
Jeffrey Chen
1e95b68df6
📝 Improve User Guide (#15753)
fix https://github.com/siyuan-note/siyuan/issues/14983
2025-09-03 16:40:29 +08:00
Daniel
f35a7f8892
🐛 PDF files with too long file names cannot generate annotated images https://github.com/siyuan-note/siyuan/issues/15739 https://github.com/siyuan-note/siyuan/issues/10666 2025-09-03 11:54:42 +08:00
Daniel
2f64492ee7
⬆️ Upgrade lute 2025-09-03 11:54:42 +08:00
Vanessa
125d18a0e1 🎨 https://github.com/siyuan-note/siyuan/issues/15699 1&3 2025-09-03 11:41:55 +08:00
Vanessa
2738b9adb0 🐛 https://github.com/siyuan-note/siyuan/issues/15742 2025-09-03 10:19:04 +08:00
Vanessa
d8bb794437 Merge remote-tracking branch 'origin/dev' into dev 2025-09-03 09:41:54 +08:00
Vanessa
91626c8fb5 🎨 https://github.com/siyuan-note/siyuan/issues/15639 2025-09-03 09:41:42 +08:00
Daniel
a5d268665d
🎨 Improve database date field filtering https://github.com/siyuan-note/siyuan/issues/15744 2025-09-03 08:56:30 +08:00
Daniel
a26c72d293
🎨 Database rollup field filtering rules support "Any", "All", and "None" https://github.com/siyuan-note/siyuan/issues/15609 2025-09-02 22:04:29 +08:00
Daniel
8cefe5ce47
♻️ Improve cache ds 2025-09-02 18:59:53 +08:00
Daniel
04c46b3a56
🎨 Improve database rollup field filtering https://github.com/siyuan-note/siyuan/issues/15740 2025-09-02 18:37:42 +08:00
Vanessa
7b2e48d54e 🎨 https://github.com/siyuan-note/siyuan/issues/15740 2025-09-02 18:36:38 +08:00
Vanessa
8d2e3bfd20 🎨 https://github.com/siyuan-note/siyuan/issues/15737 2025-09-02 17:16:56 +08:00
Vanessa
7f1f354d4e 🎨 https://github.com/siyuan-note/siyuan/issues/15728 2025-09-02 17:01:35 +08:00
106 changed files with 3211 additions and 1197 deletions

View file

@ -7,7 +7,7 @@
## NPM dependencies ## NPM dependencies
Install pnpm: `npm install -g pnpm@10.15.0` Install pnpm: `npm install -g pnpm@10.15.1`
<details> <details>
<summary>For China mainland</summary> <summary>For China mainland</summary>

View file

@ -7,7 +7,7 @@
## NPM 依赖 ## NPM 依赖
安装 pnpm`npm install -g pnpm@10.15.0` 安装 pnpm`npm install -g pnpm@10.15.1`
<details> <details>
<summary>适用于中国大陆</summary> <summary>适用于中国大陆</summary>

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "بعد تبديل التطبيقات، سيستغرق الأمر بعض الوقت لاستعادة تشغيل نواة SiYuan. يرجى الانتظار بضع ثوانٍ أو النقر فوق الزر \"إعادة المحاولة\"", "reconnectPrompt": "بعد تبديل التطبيقات، سيستغرق الأمر بعض الوقت لاستعادة تشغيل نواة SiYuan. يرجى الانتظار بضع ثوانٍ أو النقر فوق الزر \"إعادة المحاولة\"",
"relativeFontSize": "نسبة إلى حجم خط المحرر", "relativeFontSize": "نسبة إلى حجم خط المحرر",
"localFileSystem": "نظام الملفات المحلي", "localFileSystem": "نظام الملفات المحلي",
"deviceNotSupport": "الجهاز الحالي غير مدعوم", "mobileNotSupport": "هذه الميزة غير مدعومة حاليًا على الأجهزة المحمولة (الهاتف أو الجهاز اللوحي)",
"second": "ثانية", "second": "ثانية",
"syncInterval": "الفاصل الزمني للمزامنة", "syncInterval": "الفاصل الزمني للمزامنة",
"syncIntervalTip": "مزامنة البيانات تلقائياً بعد أن توقف عن التغيير", "syncIntervalTip": "مزامنة البيانات تلقائياً بعد أن توقف عن التغيير",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "عدد لقطات البيانات في اليوم", "dataRepoAutoPurgeRetentionIndexesDaily": "عدد لقطات البيانات في اليوم",
"fields": "حقول", "fields": "حقول",
"dynamicIcon": "أيقونة ديناميكية", "dynamicIcon": "أيقونة ديناميكية",
"dynamicIconDateEmptyInfo": "إذا كان التاريخ فارغًا، فسيظهر أيقونة التقويم التاريخ الحالي بشكل ديناميكي", "dynamicIconDateEmptyInfo": "مسح التاريخ، سيعرض رمز التقويم تاريخ اليوم ديناميكيًا",
"backlinkContainChildren": "جعل الروابط المرجعية تحتوي على كتل فرعية", "backlinkContainChildren": "جعل الروابط المرجعية تحتوي على كتل فرعية",
"backlinkContainChildrenTip": "عند التمكين، سيتم تضمين الكتل الفرعية في حساب الروابط المرجعية", "backlinkContainChildrenTip": "عند التمكين، سيتم تضمين الكتل الفرعية في حساب الروابط المرجعية",
"entryNum": "عدد المدخلات", "entryNum": "عدد المدخلات",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "بعد", "filterOperatorIsAfter": "بعد",
"filterOperatorIsOnOrBefore": "في أو قبل", "filterOperatorIsOnOrBefore": "في أو قبل",
"filterOperatorIsOnOrAfter": "في أو بعد", "filterOperatorIsOnOrAfter": "في أو بعد",
"filterQuantifierAny": "أي",
"filterQuantifierAll": "الكل",
"filterQuantifierNone": "لا شيء",
"asc": "تصاعدي", "asc": "تصاعدي",
"desc": "تنازلي", "desc": "تنازلي",
"hideCol": "إخفاء الحقل", "hideCol": "إخفاء الحقل",
@ -1121,7 +1124,7 @@
"fileTree3": "لا يتطلب تأكيد عند حذف المستندات", "fileTree3": "لا يتطلب تأكيد عند حذف المستندات",
"fileTree4": "في حالة عدم التمكين، سوف يظهر مربع التأكيد في كل مرة تقوم فيها بحذف مستند", "fileTree4": "في حالة عدم التمكين، سوف يظهر مربع التأكيد في كل مرة تقوم فيها بحذف مستند",
"fileTree5": "موقع حفظ المستند الجديد المنشَأ من المرجع", "fileTree5": "موقع حفظ المستند الجديد المنشَأ من المرجع",
"fileTree6": "‫عند استخدام <code class='fn__code'>((</code>، مسار حفظ المستند الجديد (على سبيل المثال، <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "‫عند استخدام <code class='fn__code'>((</code> أو <code class='fn__code'>[[</code>، مسار حفظ المستند الجديد (على سبيل المثال، <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "فتح في علامة التبويب الحالية", "fileTree7": "فتح في علامة التبويب الحالية",
"fileTree8": "سيتم استبدال علامة التبويب المستند المفتوحة حديثا علامة التبويب غير المعدلة", "fileTree8": "سيتم استبدال علامة التبويب المستند المفتوحة حديثا علامة التبويب غير المعدلة",
"fileTree9": "إغلاق جميع علامات التبويب عند بدء التشغيل", "fileTree9": "إغلاق جميع علامات التبويب عند بدء التشغيل",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "Nach dem Wechseln der Anwendungen dauert es einige Zeit, bis der Betrieb des SiYuan-Kernels wiederhergestellt ist. Bitte warten Sie einige Sekunden oder klicken Sie auf die Schaltfläche „Erneut versuchen“", "reconnectPrompt": "Nach dem Wechseln der Anwendungen dauert es einige Zeit, bis der Betrieb des SiYuan-Kernels wiederhergestellt ist. Bitte warten Sie einige Sekunden oder klicken Sie auf die Schaltfläche „Erneut versuchen“",
"relativeFontSize": "relativ zur Schriftgröße des Editors", "relativeFontSize": "relativ zur Schriftgröße des Editors",
"localFileSystem": "Lokales Dateisystem", "localFileSystem": "Lokales Dateisystem",
"deviceNotSupport": "Das aktuelle Gerät wird nicht unterstützt", "mobileNotSupport": "Diese Funktion wird derzeit auf mobilen Geräten (Telefon oder Tablet) nicht unterstützt",
"second": "Sekunde", "second": "Sekunde",
"syncInterval": "Synchronisierungsintervall", "syncInterval": "Synchronisierungsintervall",
"syncIntervalTip": "Automatische Datensynchronisierung, nachdem die Daten nicht mehr geändert werden", "syncIntervalTip": "Automatische Datensynchronisierung, nachdem die Daten nicht mehr geändert werden",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Daten-Snapshots pro Tag", "dataRepoAutoPurgeRetentionIndexesDaily": "Daten-Snapshots pro Tag",
"fields": "Attribut", "fields": "Attribut",
"dynamicIcon": "Dynamisches Icon", "dynamicIcon": "Dynamisches Icon",
"dynamicIconDateEmptyInfo": "Wenn das Datum leer ist, zeigt das Kalendersymbol dynamisch das heutige Datum an", "dynamicIconDateEmptyInfo": "Datum löschen, das Kalender-Symbol zeigt dynamisch das heutige Datum an",
"backlinkContainChildren": "Enthalten Rückverweise untergeordnete Blöcke", "backlinkContainChildren": "Enthalten Rückverweise untergeordnete Blöcke",
"backlinkContainChildrenTip": "Wenn aktiviert, werden untergeordnete Blöcke in die Berechnung der Rückverweise einbezogen", "backlinkContainChildrenTip": "Wenn aktiviert, werden untergeordnete Blöcke in die Berechnung der Rückverweise einbezogen",
"entryNum": "Anzahl der Einträge", "entryNum": "Anzahl der Einträge",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "Ist nach", "filterOperatorIsAfter": "Ist nach",
"filterOperatorIsOnOrBefore": "Ist am oder vor", "filterOperatorIsOnOrBefore": "Ist am oder vor",
"filterOperatorIsOnOrAfter": "Ist am oder nach", "filterOperatorIsOnOrAfter": "Ist am oder nach",
"filterQuantifierAny": "Beliebig",
"filterQuantifierAll": "Alle",
"filterQuantifierNone": "Keine",
"asc": "Aufsteigend", "asc": "Aufsteigend",
"desc": "Absteigend", "desc": "Absteigend",
"hideCol": "Spalte ausblenden", "hideCol": "Spalte ausblenden",
@ -1121,7 +1124,7 @@
"fileTree3": "Keine Bestätigung erforderlich beim Löschen von Dokumenten", "fileTree3": "Keine Bestätigung erforderlich beim Löschen von Dokumenten",
"fileTree4": "Wenn nicht aktiviert, wird jedes Mal ein Bestätigungsfeld angezeigt, wenn Sie ein Dokument löschen", "fileTree4": "Wenn nicht aktiviert, wird jedes Mal ein Bestätigungsfeld angezeigt, wenn Sie ein Dokument löschen",
"fileTree5": "Referenz erstellt Doc-Speicherort", "fileTree5": "Referenz erstellt Doc-Speicherort",
"fileTree6": "Beim Verwenden von <code class='fn__code'>((</code> der Speicherpfad des neuen Dokuments (z.B. <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "Beim Verwenden von <code class='fn__code'>((</code> oder <code class='fn__code'>[[</code> der Speicherpfad des neuen Dokuments (z.B. <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Im aktuellen Tab öffnen", "fileTree7": "Im aktuellen Tab öffnen",
"fileTree8": "Der neu geöffnete Dokumenten-Tab ersetzt den nicht modifizierten Tab", "fileTree8": "Der neu geöffnete Dokumenten-Tab ersetzt den nicht modifizierten Tab",
"fileTree9": "Alle Tabs beim Start schließen", "fileTree9": "Alle Tabs beim Start schließen",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "After switching applications, it will take some time to restore the SiYuan kernel operation. Please wait a few seconds or click the \"Retry\" button", "reconnectPrompt": "After switching applications, it will take some time to restore the SiYuan kernel operation. Please wait a few seconds or click the \"Retry\" button",
"relativeFontSize": "relative to the editor font size", "relativeFontSize": "relative to the editor font size",
"localFileSystem": "Local file system", "localFileSystem": "Local file system",
"deviceNotSupport": "The current device is not supported", "mobileNotSupport": "This feature is currently not supported on mobile devices (phone or tablet)",
"second": "second", "second": "second",
"syncInterval": "sync interval", "syncInterval": "sync interval",
"syncIntervalTip": "Automatically sync data after it stops changing", "syncIntervalTip": "Automatically sync data after it stops changing",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Data snapshots per day", "dataRepoAutoPurgeRetentionIndexesDaily": "Data snapshots per day",
"fields": "Fields", "fields": "Fields",
"dynamicIcon": "Dynamic icon", "dynamicIcon": "Dynamic icon",
"dynamicIconDateEmptyInfo": "When date is empty, the calendar icon will show today's date dynamically", "dynamicIconDateEmptyInfo": "Clear the date, the calendar icon will dynamically display todays date",
"backlinkContainChildren": "Do backlinks contain child blocks", "backlinkContainChildren": "Do backlinks contain child blocks",
"backlinkContainChildrenTip": "When enabled, child blocks will be included in the backlink calculation", "backlinkContainChildrenTip": "When enabled, child blocks will be included in the backlink calculation",
"entryNum": "Number of entries", "entryNum": "Number of entries",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "Is after", "filterOperatorIsAfter": "Is after",
"filterOperatorIsOnOrBefore": "Is on or before", "filterOperatorIsOnOrBefore": "Is on or before",
"filterOperatorIsOnOrAfter": "Is on or after", "filterOperatorIsOnOrAfter": "Is on or after",
"filterQuantifierAny": "Any",
"filterQuantifierAll": "All",
"filterQuantifierNone": "None",
"asc": "Ascending", "asc": "Ascending",
"desc": "Descending", "desc": "Descending",
"hideCol": "Hide field", "hideCol": "Hide field",
@ -1121,7 +1124,7 @@
"fileTree3": "No confirmation required when deleting documents", "fileTree3": "No confirmation required when deleting documents",
"fileTree4": "If not enabled, a confirmation box will pop up every time you delete a document", "fileTree4": "If not enabled, a confirmation box will pop up every time you delete a document",
"fileTree5": "Ref create doc save location", "fileTree5": "Ref create doc save location",
"fileTree6": "When using <code class='fn__code'>((</code>, the save path of the new document (for example, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "When using <code class='fn__code'>((</code> or <code class='fn__code'>[[</code>, the save path of the new document (for example, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Open in the current tab", "fileTree7": "Open in the current tab",
"fileTree8": "The newly opened document tab will replace the unmodified tab", "fileTree8": "The newly opened document tab will replace the unmodified tab",
"fileTree9": "Close all tabs at startup", "fileTree9": "Close all tabs at startup",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "Después de cambiar de aplicación, tomará algún tiempo restaurar el funcionamiento del núcleo de SiYuan. Espere unos segundos o haga clic en el botón \"Reintentar\"", "reconnectPrompt": "Después de cambiar de aplicación, tomará algún tiempo restaurar el funcionamiento del núcleo de SiYuan. Espere unos segundos o haga clic en el botón \"Reintentar\"",
"relativeFontSize": "en relación con el tamaño de fuente del editor", "relativeFontSize": "en relación con el tamaño de fuente del editor",
"localFileSystem": "Sistema de archivos local", "localFileSystem": "Sistema de archivos local",
"deviceNotSupport": "El dispositivo actual no es compatible", "mobileNotSupport": "Esta función no está disponible actualmente en dispositivos móviles (teléfono o tableta)",
"second": "segundo", "second": "segundo",
"syncInterval": "intervalo de sincronización", "syncInterval": "intervalo de sincronización",
"syncIntervalTip": "Sincronización automática de datos después de que los datos dejen de cambiar", "syncIntervalTip": "Sincronización automática de datos después de que los datos dejen de cambiar",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Número de instantáneas de datos por día", "dataRepoAutoPurgeRetentionIndexesDaily": "Número de instantáneas de datos por día",
"fields": "Atributo", "fields": "Atributo",
"dynamicIcon": "Icono dinámico", "dynamicIcon": "Icono dinámico",
"dynamicIconDateEmptyInfo": "Si la fecha está vacía, el icono del calendario mostrará dinámicamente la fecha de hoy", "dynamicIconDateEmptyInfo": "Borrar la fecha, el icono del calendario mostrará dinámicamente la fecha actual",
"backlinkContainChildren": "¿Los enlaces inversos contienen bloques secundarios?", "backlinkContainChildren": "¿Los enlaces inversos contienen bloques secundarios?",
"backlinkContainChildrenTip": "Una vez habilitado, los bloques secundarios se incluirán en el cálculo de los enlaces inversos", "backlinkContainChildrenTip": "Una vez habilitado, los bloques secundarios se incluirán en el cálculo de los enlaces inversos",
"entryNum": "Número de entradas", "entryNum": "Número de entradas",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "Es posterior a", "filterOperatorIsAfter": "Es posterior a",
"filterOperatorIsOnOrBefore": "Está activado o antes", "filterOperatorIsOnOrBefore": "Está activado o antes",
"filterOperatorIsOnOrAfter": "Está encendido o después", "filterOperatorIsOnOrAfter": "Está encendido o después",
"filterQuantifierAny": "Cualquiera",
"filterQuantifierAll": "Todos",
"filterQuantifierNone": "Ninguno",
"asc": "Ascendente", "asc": "Ascendente",
"desc": "Descendente", "desc": "Descendente",
"hideCol": "Ocultar columna", "hideCol": "Ocultar columna",
@ -1121,7 +1124,7 @@
"fileTree3": "No se requiere confirmación al borrar documentos", "fileTree3": "No se requiere confirmación al borrar documentos",
"fileTree4": "Si no se activa, aparecerá un cuadro de confirmación cada vez que se elimine un documento", "fileTree4": "Si no se activa, aparecerá un cuadro de confirmación cada vez que se elimine un documento",
"fileTree5": "Ref crear ubicación de guardado de documentos", "fileTree5": "Ref crear ubicación de guardado de documentos",
"fileTree6": "Al utilizar <code class='fn__code'>((</code>, la ruta de guardado del nuevo documento (por ejemplo, <code class='fn__code'>/carpeta1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "Al utilizar <code class='fn__code'>((</code> o <code class='fn__code'>[[</code>, la ruta de guardado del nuevo documento (por ejemplo, <code class='fn__code'>/carpeta1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Abrir en la pestaña actual", "fileTree7": "Abrir en la pestaña actual",
"fileTree8": "La pestaña del documento recién abierto sustituirá a la pestaña no modificada", "fileTree8": "La pestaña del documento recién abierto sustituirá a la pestaña no modificada",
"fileTree9": "Cerrar todas las pestañas al inicio", "fileTree9": "Cerrar todas las pestañas al inicio",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "Après avoir changé d'application, il faudra un certain temps pour rétablir le fonctionnement du noyau SiYuan. Veuillez patienter quelques secondes ou cliquer sur le bouton « Réessayer »", "reconnectPrompt": "Après avoir changé d'application, il faudra un certain temps pour rétablir le fonctionnement du noyau SiYuan. Veuillez patienter quelques secondes ou cliquer sur le bouton « Réessayer »",
"relativeFontSize": "par rapport à la taille de la police de l'éditeur", "relativeFontSize": "par rapport à la taille de la police de l'éditeur",
"localFileSystem": "Système de fichiers local", "localFileSystem": "Système de fichiers local",
"deviceNotSupport": "L'appareil actuel n'est pas pris en charge", "mobileNotSupport": "Cette fonctionnalité n'est pas prise en charge sur les appareils mobiles (téléphone ou tablette) pour le moment",
"second": "seconde", "second": "seconde",
"syncInterval": "intervalle de synchronisation", "syncInterval": "intervalle de synchronisation",
"syncIntervalTip": "Synchronisation automatique des données après l'arrêt des modifications", "syncIntervalTip": "Synchronisation automatique des données après l'arrêt des modifications",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Nombre d'instantanés de données par jour", "dataRepoAutoPurgeRetentionIndexesDaily": "Nombre d'instantanés de données par jour",
"fields": "Attribut", "fields": "Attribut",
"dynamicIcon": "Icône dynamique", "dynamicIcon": "Icône dynamique",
"dynamicIconDateEmptyInfo": "Si la date est vide, l'icône du calendrier affichera dynamiquement la date d'aujourd'hui", "dynamicIconDateEmptyInfo": "Effacer la date, licône du calendrier affichera dynamiquement la date du jour",
"backlinkContainChildren": "Les liens retour contiennent-ils des sous-blocs", "backlinkContainChildren": "Les liens retour contiennent-ils des sous-blocs",
"backlinkContainChildrenTip": "Une fois activé, les sous-blocs seront inclus dans le calcul des liens retour", "backlinkContainChildrenTip": "Une fois activé, les sous-blocs seront inclus dans le calcul des liens retour",
"entryNum": "Nombre d'entrées", "entryNum": "Nombre d'entrées",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "Est après", "filterOperatorIsAfter": "Est après",
"filterOperatorIsOnOrBefore": "Est le ou avant", "filterOperatorIsOnOrBefore": "Est le ou avant",
"filterOperatorIsOnOrAfter": "Est allumé ou après", "filterOperatorIsOnOrAfter": "Est allumé ou après",
"filterQuantifierAny": "N'importe lequel",
"filterQuantifierAll": "Tous",
"filterQuantifierNone": "Aucun",
"asc": "Ascendant", "asc": "Ascendant",
"desc": "Descendant", "desc": "Descendant",
"hideCol": "Masquer la colonne", "hideCol": "Masquer la colonne",
@ -1121,7 +1124,7 @@
"fileTree3": "Aucune confirmation requise lors de la suppression de documents", "fileTree3": "Aucune confirmation requise lors de la suppression de documents",
"fileTree4": "Si non activé, une boîte de confirmation apparaîtra à chaque fois que vous supprimerez un document", "fileTree4": "Si non activé, une boîte de confirmation apparaîtra à chaque fois que vous supprimerez un document",
"fileTree5": "Référence créer doc enregistrer emplacement", "fileTree5": "Référence créer doc enregistrer emplacement",
"fileTree6": "Lors de l'utilisation de <code class='fn__code'>((</code>, le chemin d'enregistrement du nouveau document (par exemple, <code class='fn__code'>/dossier1/{{now | date \"20060102150405\"}}/</code>).", "fileTree6": "Lors de l'utilisation de <code class='fn__code'>((</code> ou <code class='fn__code'>[[</code>, le chemin d'enregistrement du nouveau document (par exemple, <code class='fn__code'>/dossier1/{{now | date \"20060102150405\"}}/</code>).",
"fileTree7": "Ouvrir dans l'Onglet actuel", "fileTree7": "Ouvrir dans l'Onglet actuel",
"fileTree8": "L'onglet du document nouvellement ouvert remplacera l'Onglet non modifié.", "fileTree8": "L'onglet du document nouvellement ouvert remplacera l'Onglet non modifié.",
"fileTree9": "Fermer tous les onglets au démarrage", "fileTree9": "Fermer tous les onglets au démarrage",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "לאחר מעבר בין יישומים, יידרש זמן מה כדי לשחזר את פעולת ליבת SiYuan. אנא המתן מספר שניות או לחץ על כפתור \"נסה שוב\"", "reconnectPrompt": "לאחר מעבר בין יישומים, יידרש זמן מה כדי לשחזר את פעולת ליבת SiYuan. אנא המתן מספר שניות או לחץ על כפתור \"נסה שוב\"",
"relativeFontSize": "יחסית לגודל הגופן של העורך", "relativeFontSize": "יחסית לגודל הגופן של העורך",
"localFileSystem": "מערכת קבצים מקומית", "localFileSystem": "מערכת קבצים מקומית",
"deviceNotSupport": "המכשיר הנוכחי אינו נתמך", "mobileNotSupport": "פונקציה זו אינה נתמכת כרגע במכשירים ניידים (טלפון או טאבלט)",
"second": "שנייה", "second": "שנייה",
"syncInterval": "מרווח סנכרון", "syncInterval": "מרווח סנכרון",
"syncIntervalTip": "סנכרון נתונים אוטומטי לאחר שהנתונים מפסיקים להשתנות", "syncIntervalTip": "סנכרון נתונים אוטומטי לאחר שהנתונים מפסיקים להשתנות",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "מספר תמונות נתונים ביום", "dataRepoAutoPurgeRetentionIndexesDaily": "מספר תמונות נתונים ביום",
"fields": "מאפיין", "fields": "מאפיין",
"dynamicIcon": "אייקון דינמי", "dynamicIcon": "אייקון דינמי",
"dynamicIconDateEmptyInfo": "אם התאריך ריק, סמל הלוח השנה יציג באופן דינמי את התאריך של היום", "dynamicIconDateEmptyInfo": "נקה את התאריך, סמל לוח השנה יציג באופן דינמי את התאריך של היום",
"backlinkContainChildren": "האם קישורים חוזרים כוללים בלוקים משניים", "backlinkContainChildren": "האם קישורים חוזרים כוללים בלוקים משניים",
"backlinkContainChildrenTip": "לאחר ההפעלה, בלוקים משניים ייכללו בחישוב הקישורים החוזרים", "backlinkContainChildrenTip": "לאחר ההפעלה, בלוקים משניים ייכללו בחישוב הקישורים החוזרים",
"entryNum": "מספר ערכים", "entryNum": "מספר ערכים",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "היה אחרי", "filterOperatorIsAfter": "היה אחרי",
"filterOperatorIsOnOrBefore": "היה על או לפני", "filterOperatorIsOnOrBefore": "היה על או לפני",
"filterOperatorIsOnOrAfter": "היה על או אחרי", "filterOperatorIsOnOrAfter": "היה על או אחרי",
"filterQuantifierAny": "כל אחד",
"filterQuantifierAll": "הכל",
"filterQuantifierNone": "אין",
"asc": "עולה", "asc": "עולה",
"desc": "יורד", "desc": "יורד",
"hideCol": "החבא עמודה", "hideCol": "החבא עמודה",
@ -1121,7 +1124,7 @@
"fileTree3": "אין צורך באישור בעת מחיקת מסמכים", "fileTree3": "אין צורך באישור בעת מחיקת מסמכים",
"fileTree4": "אם לא הופק, תופיע תיבת אישור בכל פעם שמחקים מסמך", "fileTree4": "אם לא הופק, תופיע תיבת אישור בכל פעם שמחקים מסמך",
"fileTree5": "מיקום שמירת מסמך להפניה", "fileTree5": "מיקום שמירת מסמך להפניה",
"fileTree6": "בעת השימוש <code class='fn__code'>((</code>, מסלול השמירה של המסמך החדש (למשל, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}</code>)", "fileTree6": "בעת השימוש <code class='fn__code'>((</code> או <code class='fn__code'>[[</code>, מסלול השמירה של המסמך החדש (למשל, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}</code>)",
"fileTree7": "פתח בטאב הנוכחי", "fileTree7": "פתח בטאב הנוכחי",
"fileTree8": "טאב המסמך הנפתח החדש יחליף את הטאב הלא משתנה", "fileTree8": "טאב המסמך הנפתח החדש יחליף את הטאב הלא משתנה",
"fileTree9": "סגור את כל הטאבים בעת אתחול", "fileTree9": "סגור את כל הטאבים בעת אתחול",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "Dopo aver cambiato applicazione, ci vorrà un po' di tempo per ripristinare il funzionamento del kernel SiYuan. Attendere qualche secondo o fare clic sul pulsante \"Riprova\"", "reconnectPrompt": "Dopo aver cambiato applicazione, ci vorrà un po' di tempo per ripristinare il funzionamento del kernel SiYuan. Attendere qualche secondo o fare clic sul pulsante \"Riprova\"",
"relativeFontSize": "rispetto alla dimensione del carattere dell'editor", "relativeFontSize": "rispetto alla dimensione del carattere dell'editor",
"localFileSystem": "File system locale", "localFileSystem": "File system locale",
"deviceNotSupport": "Il dispositivo corrente non è supportato", "mobileNotSupport": "La funzione non è attualmente supportata su dispositivi mobili (telefono o tablet)",
"second": "secondo", "second": "secondo",
"syncInterval": "intervallo di sincronizzazione", "syncInterval": "intervallo di sincronizzazione",
"syncIntervalTip": "Sincronizzazione automatica dei dati dopo che non ci sono più variazioni", "syncIntervalTip": "Sincronizzazione automatica dei dati dopo che non ci sono più variazioni",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Numero di snapshot dei dati al giorno", "dataRepoAutoPurgeRetentionIndexesDaily": "Numero di snapshot dei dati al giorno",
"fields": "Campi", "fields": "Campi",
"dynamicIcon": "Emoji dinamica", "dynamicIcon": "Emoji dinamica",
"dynamicIconDateEmptyInfo": "Se la data è vuota, l'icona del calendario mostrerà dinamicamente la data odierna", "dynamicIconDateEmptyInfo": "Cancella la data, l'icona del calendario mostrerà dinamicamente la data odierna",
"backlinkContainChildren": "I backlink contengono blocchi figli", "backlinkContainChildren": "I backlink contengono blocchi figli",
"backlinkContainChildrenTip": "Dopo l'attivazione, i blocchi figli saranno inclusi nel calcolo dei backlink", "backlinkContainChildrenTip": "Dopo l'attivazione, i blocchi figli saranno inclusi nel calcolo dei backlink",
"entryNum": "Numero di voci", "entryNum": "Numero di voci",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "È dopo", "filterOperatorIsAfter": "È dopo",
"filterOperatorIsOnOrBefore": "È il giorno o prima di", "filterOperatorIsOnOrBefore": "È il giorno o prima di",
"filterOperatorIsOnOrAfter": "È il giorno o dopo di", "filterOperatorIsOnOrAfter": "È il giorno o dopo di",
"filterQuantifierAny": "Qualsiasi",
"filterQuantifierAll": "Tutti",
"filterQuantifierNone": "Nessuno",
"asc": "Ascendente", "asc": "Ascendente",
"desc": "Discendente", "desc": "Discendente",
"hideCol": "Nascondi campo", "hideCol": "Nascondi campo",
@ -1121,7 +1124,7 @@
"fileTree3": "Nessuna conferma richiesta durante l'eliminazione dei documenti", "fileTree3": "Nessuna conferma richiesta durante l'eliminazione dei documenti",
"fileTree4": "Se non abilitato, ogni volta che elimini un documento verrà visualizzata una finestra di conferma", "fileTree4": "Se non abilitato, ogni volta che elimini un documento verrà visualizzata una finestra di conferma",
"fileTree5": "Percorso di salvataggio dei nuovi documenti creati con riferimento", "fileTree5": "Percorso di salvataggio dei nuovi documenti creati con riferimento",
"fileTree6": "Quando usi <code class='fn__code'>((</code>, il percorso di salvataggio del nuovo documento (ad esempio, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "Quando usi <code class='fn__code'>((</code> o <code class='fn__code'>[[</code>, il percorso di salvataggio del nuovo documento (ad esempio, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Apri nella scheda corrente", "fileTree7": "Apri nella scheda corrente",
"fileTree8": "La scheda del documento appena aperta sostituirà la scheda non modificata", "fileTree8": "La scheda del documento appena aperta sostituirà la scheda non modificata",
"fileTree9": "Chiudi tutte le schede all'avvio", "fileTree9": "Chiudi tutte le schede all'avvio",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "アプリを切り替えた後、思源カーネルの実行を再開するには少し時間がかかります。数秒待つか、「再試行」ボタンをクリックしてください", "reconnectPrompt": "アプリを切り替えた後、思源カーネルの実行を再開するには少し時間がかかります。数秒待つか、「再試行」ボタンをクリックしてください",
"relativeFontSize": "エディターのフォントサイズに対して", "relativeFontSize": "エディターのフォントサイズに対して",
"localFileSystem": "ローカルファイルシステム", "localFileSystem": "ローカルファイルシステム",
"deviceNotSupport": "現在のデバイスはサポートされていません", "mobileNotSupport": "モバイル端末(スマートフォンまたはタブレット)では現在この機能はサポートされていません",
"second": "秒", "second": "秒",
"syncInterval": "同期間隔", "syncInterval": "同期間隔",
"syncIntervalTip": "データが変動しなくなった後に自動的にデータを同期します", "syncIntervalTip": "データが変動しなくなった後に自動的にデータを同期します",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "データスナップショットの毎日の保持数", "dataRepoAutoPurgeRetentionIndexesDaily": "データスナップショットの毎日の保持数",
"fields": "属性", "fields": "属性",
"dynamicIcon": "動的アイコン", "dynamicIcon": "動的アイコン",
"dynamicIconDateEmptyInfo": "日付が空の場合、カレンダーアイコンは現在の日付を動的に表示します", "dynamicIconDateEmptyInfo": "日付をクリアすると、カレンダーアイコンが当日の日付を動的に表示します",
"backlinkContainChildren": "バックリンクに子ブロックを含めるかどうか", "backlinkContainChildren": "バックリンクに子ブロックを含めるかどうか",
"backlinkContainChildrenTip": "有効にすると、子ブロックがバックリンク計算に含まれます", "backlinkContainChildrenTip": "有効にすると、子ブロックがバックリンク計算に含まれます",
"entryNum": "エントリ数", "entryNum": "エントリ数",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "より後", "filterOperatorIsAfter": "より後",
"filterOperatorIsOnOrBefore": "以前", "filterOperatorIsOnOrBefore": "以前",
"filterOperatorIsOnOrAfter": "以降", "filterOperatorIsOnOrAfter": "以降",
"filterQuantifierAny": "いずれか",
"filterQuantifierAll": "すべて",
"filterQuantifierNone": "なし",
"asc": "昇順", "asc": "昇順",
"desc": "降順", "desc": "降順",
"hideCol": "列を非表示", "hideCol": "列を非表示",
@ -1121,7 +1124,7 @@
"fileTree3": "ドキュメントを削除するときに確認しない", "fileTree3": "ドキュメントを削除するときに確認しない",
"fileTree4": "ドキュメントを削除するときに確認ボックスを表示しません", "fileTree4": "ドキュメントを削除するときに確認ボックスを表示しません",
"fileTree5": "参照の保存場所", "fileTree5": "参照の保存場所",
"fileTree6": "<code class='fn__code'>((</code> を使用した時の参照の保存パス (例: <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "<code class='fn__code'>((</code> または <code class='fn__code'>[[</code> を使用した時の参照の保存パス (例: <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "現在のタブで開く", "fileTree7": "現在のタブで開く",
"fileTree8": "新しく開いたドキュメントのタブが未変更のタブを置き換えます", "fileTree8": "新しく開いたドキュメントのタブが未変更のタブを置き換えます",
"fileTree9": "起動時にすべてのタブを閉じる", "fileTree9": "起動時にすべてのタブを閉じる",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "Po przełączeniu aplikacji ponowne uruchomienie jądra SiYuan może zająć trochę czasu. Proszę poczekać kilka sekund lub kliknąć przycisk „Ponów próbę”", "reconnectPrompt": "Po przełączeniu aplikacji ponowne uruchomienie jądra SiYuan może zająć trochę czasu. Proszę poczekać kilka sekund lub kliknąć przycisk „Ponów próbę”",
"relativeFontSize": "względem rozmiaru czcionki edytora", "relativeFontSize": "względem rozmiaru czcionki edytora",
"localFileSystem": "Lokalny system plików", "localFileSystem": "Lokalny system plików",
"deviceNotSupport": "Bieżące urządzenie nie jest obsługiwane", "mobileNotSupport": "Funkcja nie jest obecnie obsługiwana na urządzeniach mobilnych (telefon lub tablet)",
"second": "sekunda", "second": "sekunda",
"syncInterval": "interwał synchronizacji", "syncInterval": "interwał synchronizacji",
"syncIntervalTip": "Automatyczna synchronizacja danych po zaprzestaniu zmian", "syncIntervalTip": "Automatyczna synchronizacja danych po zaprzestaniu zmian",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Liczba migawek danych dziennie", "dataRepoAutoPurgeRetentionIndexesDaily": "Liczba migawek danych dziennie",
"fields": "Atrybut", "fields": "Atrybut",
"dynamicIcon": "Ikona dynamiczna", "dynamicIcon": "Ikona dynamiczna",
"dynamicIconDateEmptyInfo": "Jeśli data jest pusta, ikona kalendarza będzie dynamicznie pokazywać dzisiejszą datę", "dynamicIconDateEmptyInfo": "Wyczyść datę, ikona kalendarza będzie dynamicznie wyświetlać bieżącą datę",
"backlinkContainChildren": "Czy linki zwrotne zawierają bloki podrzędne", "backlinkContainChildren": "Czy linki zwrotne zawierają bloki podrzędne",
"backlinkContainChildrenTip": "Po włączeniu bloki podrzędne zostaną uwzględnione w obliczeniach linków zwrotnych", "backlinkContainChildrenTip": "Po włączeniu bloki podrzędne zostaną uwzględnione w obliczeniach linków zwrotnych",
"entryNum": "Количество записей", "entryNum": "Количество записей",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "Jest po", "filterOperatorIsAfter": "Jest po",
"filterOperatorIsOnOrBefore": "Jest na lub przed", "filterOperatorIsOnOrBefore": "Jest na lub przed",
"filterOperatorIsOnOrAfter": "Jest na lub po", "filterOperatorIsOnOrAfter": "Jest na lub po",
"filterQuantifierAny": "Dowolny",
"filterQuantifierAll": "Wszystkie",
"filterQuantifierNone": "Brak",
"asc": "Rosnąco", "asc": "Rosnąco",
"desc": "Malejąco", "desc": "Malejąco",
"hideCol": "Ukryj kolumnę", "hideCol": "Ukryj kolumnę",
@ -1121,7 +1124,7 @@
"fileTree3": "Nie wymaga potwierdzenia przy usuwaniu dokumentów", "fileTree3": "Nie wymaga potwierdzenia przy usuwaniu dokumentów",
"fileTree4": "Jeśli nie jest włączone, okno potwierdzenia pojawi się za każdym razem, gdy usuniesz dokument", "fileTree4": "Jeśli nie jest włączone, okno potwierdzenia pojawi się za każdym razem, gdy usuniesz dokument",
"fileTree5": "Ref stworzone miejsce zapisu dokumentu", "fileTree5": "Ref stworzone miejsce zapisu dokumentu",
"fileTree6": "Kiedy używasz <code class='fn__code'>((</code>, ścieżka zapisu nowego dokumentu (na przykład <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "Kiedy używasz <code class='fn__code'>((</code> lub <code class='fn__code'>[[</code>, ścieżka zapisu nowego dokumentu (na przykład <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Otwórz w bieżącej zakładce", "fileTree7": "Otwórz w bieżącej zakładce",
"fileTree8": "Nowa otwarta zakładka dokumentu zastąpi niezmodyfikowaną zakładkę", "fileTree8": "Nowa otwarta zakładka dokumentu zastąpi niezmodyfikowaną zakładkę",
"fileTree9": "Zamknij wszystkie zakładki przy uruchamianiu", "fileTree9": "Zamknij wszystkie zakładki przy uruchamianiu",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "Após alternar aplicativos, levará algum tempo para restaurar a operação do kernel SiYuan. Por favor, aguarde alguns segundos ou clique no botão \"Tentar novamente\"", "reconnectPrompt": "Após alternar aplicativos, levará algum tempo para restaurar a operação do kernel SiYuan. Por favor, aguarde alguns segundos ou clique no botão \"Tentar novamente\"",
"relativeFontSize": "relativo ao tamanho da fonte do editor", "relativeFontSize": "relativo ao tamanho da fonte do editor",
"localFileSystem": "Sistema de arquivos local", "localFileSystem": "Sistema de arquivos local",
"deviceNotSupport": "O dispositivo atual não é suportado", "mobileNotSupport": "O recurso não é suportado em dispositivos móveis (celular ou tablet) no momento,",
"second": "segundo", "second": "segundo",
"syncInterval": "intervalo de sincronização", "syncInterval": "intervalo de sincronização",
"syncIntervalTip": "Sincronizar dados automaticamente após parar de alterar", "syncIntervalTip": "Sincronizar dados automaticamente após parar de alterar",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Instantâneos de dados por dia", "dataRepoAutoPurgeRetentionIndexesDaily": "Instantâneos de dados por dia",
"fields": "Campos", "fields": "Campos",
"dynamicIcon": "Ícone dinâmico", "dynamicIcon": "Ícone dinâmico",
"dynamicIconDateEmptyInfo": "Se a data estiver vazia, o ícone do calendário exibirá dinamicamente a data atual", "dynamicIconDateEmptyInfo": "Limpar a data, o ícone do calendário exibirá dinamicamente a data atual",
"backlinkContainChildren": "Os backlinks contêm blocos filhos", "backlinkContainChildren": "Os backlinks contêm blocos filhos",
"backlinkContainChildrenTip": "Quando ativado, os blocos filhos serão incluídos no cálculo do backlink", "backlinkContainChildrenTip": "Quando ativado, os blocos filhos serão incluídos no cálculo do backlink",
"entryNum": "Número de entradas", "entryNum": "Número de entradas",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "É depois de", "filterOperatorIsAfter": "É depois de",
"filterOperatorIsOnOrBefore": "É em ou antes de", "filterOperatorIsOnOrBefore": "É em ou antes de",
"filterOperatorIsOnOrAfter": "É em ou depois de", "filterOperatorIsOnOrAfter": "É em ou depois de",
"filterQuantifierAny": "Qualquer",
"filterQuantifierAll": "Todos",
"filterQuantifierNone": "Nenhum",
"asc": "Ascendente", "asc": "Ascendente",
"desc": "Descendente", "desc": "Descendente",
"hideCol": "Ocultar campo", "hideCol": "Ocultar campo",
@ -1121,7 +1124,7 @@
"fileTree3": "Nenhuma confirmação necessária ao excluir documentos", "fileTree3": "Nenhuma confirmação necessária ao excluir documentos",
"fileTree4": "Se não estiver ativado, uma caixa de confirmação aparecerá toda vez que você excluir um documento", "fileTree4": "Se não estiver ativado, uma caixa de confirmação aparecerá toda vez que você excluir um documento",
"fileTree5": "Local de salvamento do documento criado por Ref", "fileTree5": "Local de salvamento do documento criado por Ref",
"fileTree6": "Ao usar <code class='fn__code'>((</code>, o caminho de salvamento do novo documento (por exemplo, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "Ao usar <code class='fn__code'>((</code> ou <code class='fn__code'>[[</code>, o caminho de salvamento do novo documento (por exemplo, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Abrir na aba atual", "fileTree7": "Abrir na aba atual",
"fileTree8": "A nova aba de documento substituirá a aba não modificada", "fileTree8": "A nova aba de documento substituirá a aba não modificada",
"fileTree9": "Fechar todas as abas na inicialização", "fileTree9": "Fechar todas as abas na inicialização",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "После переключения приложений потребуется некоторое время, чтобы восстановить работу ядра SiYuan. Пожалуйста, подождите несколько секунд или нажмите кнопку «Повторить»", "reconnectPrompt": "После переключения приложений потребуется некоторое время, чтобы восстановить работу ядра SiYuan. Пожалуйста, подождите несколько секунд или нажмите кнопку «Повторить»",
"relativeFontSize": "относительно размера шрифта редактора", "relativeFontSize": "относительно размера шрифта редактора",
"localFileSystem": "Локальная файловая система", "localFileSystem": "Локальная файловая система",
"deviceNotSupport": "Текущее устройство не поддерживается", "mobileNotSupport": "Мобильные устройства (телефон или планшет) в настоящее время не поддерживают эту функцию,",
"second": "секунда", "second": "секунда",
"syncInterval": "интервал синхронизации", "syncInterval": "интервал синхронизации",
"syncIntervalTip": "Автоматическая синхронизация данных после прекращения изменений", "syncIntervalTip": "Автоматическая синхронизация данных после прекращения изменений",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "Количество снимков данных в день", "dataRepoAutoPurgeRetentionIndexesDaily": "Количество снимков данных в день",
"fields": "Атрибут", "fields": "Атрибут",
"dynamicIcon": "Динамическая иконка", "dynamicIcon": "Динамическая иконка",
"dynamicIconDateEmptyInfo": "Если дата пуста, иконка календаря будет динамически отображать сегодняшнюю дату", "dynamicIconDateEmptyInfo": "Очистить дату, иконка календаря будет динамически отображать текущую дату",
"backlinkContainChildren": "Включать ли дочерние блоки в обратные ссылки", "backlinkContainChildren": "Включать ли дочерние блоки в обратные ссылки",
"backlinkContainChildrenTip": "После включения дочерние блоки будут включены в расчет обратных ссылок", "backlinkContainChildrenTip": "После включения дочерние блоки будут включены в расчет обратных ссылок",
"entryNum": "Количество записей", "entryNum": "Количество записей",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "Находится после", "filterOperatorIsAfter": "Находится после",
"filterOperatorIsOnOrBefore": "Находится на или до", "filterOperatorIsOnOrBefore": "Находится на или до",
"filterOperatorIsOnOrAfter": "Находится на или после", "filterOperatorIsOnOrAfter": "Находится на или после",
"filterQuantifierAny": "Любой",
"filterQuantifierAll": "Все",
"filterQuantifierNone": "Нет",
"asc": "По возрастанию", "asc": "По возрастанию",
"desc": "По убыванию", "desc": "По убыванию",
"hideCol": "Скрыть колонку", "hideCol": "Скрыть колонку",
@ -1121,7 +1124,7 @@
"fileTree3": "Подтверждение не требуется при удалении документов", "fileTree3": "Подтверждение не требуется при удалении документов",
"fileTree4": "Если не включено, будет появляться окно подтверждения каждый раз при удалении документа", "fileTree4": "Если не включено, будет появляться окно подтверждения каждый раз при удалении документа",
"fileTree5": "Сохранить местоположение созданного документа с ссылкой", "fileTree5": "Сохранить местоположение созданного документа с ссылкой",
"fileTree6": "При использовании <code class='fn__code'>((</code> путь для нового документа (например, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)", "fileTree6": "При использовании <code class='fn__code'>((</code> или <code class='fn__code'>[[</code> путь для нового документа (например, <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>)",
"fileTree7": "Открыть в текущей вкладке", "fileTree7": "Открыть в текущей вкладке",
"fileTree8": "Вкладка нового открытого документа заменит неизмененную вкладку", "fileTree8": "Вкладка нового открытого документа заменит неизмененную вкладку",
"fileTree9": "Закрыть все вкладки при запуске", "fileTree9": "Закрыть все вкладки при запуске",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "切換應用後再次進入需要一些時間恢復思源內核運行,請稍等幾秒或者點擊“重試”按鈕", "reconnectPrompt": "切換應用後再次進入需要一些時間恢復思源內核運行,請稍等幾秒或者點擊“重試”按鈕",
"relativeFontSize": "相對於編輯器字號", "relativeFontSize": "相對於編輯器字號",
"localFileSystem": "本地檔案系統", "localFileSystem": "本地檔案系統",
"deviceNotSupport": "當前設備不支援", "mobileNotSupport": "行動裝置(手機或平板)目前不支援此功能,",
"second": "秒", "second": "秒",
"syncInterval": "同步間隔", "syncInterval": "同步間隔",
"syncIntervalTip": "數據不再變動後自動進行數據同步", "syncIntervalTip": "數據不再變動後自動進行數據同步",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "數據快照每天保留個數", "dataRepoAutoPurgeRetentionIndexesDaily": "數據快照每天保留個數",
"fields": "欄位", "fields": "欄位",
"dynamicIcon": "動態圖標", "dynamicIcon": "動態圖標",
"dynamicIconDateEmptyInfo": "若日期為空,日曆圖示將動態顯示當天日期", "dynamicIconDateEmptyInfo": "清除日期,日曆圖示將動態顯示當天日期",
"backlinkContainChildren": "反向鏈接包含子塊", "backlinkContainChildren": "反向鏈接包含子塊",
"backlinkContainChildrenTip": "啟用後子塊將被納入到反向鏈接計算中", "backlinkContainChildrenTip": "啟用後子塊將被納入到反向鏈接計算中",
"entryNum": "條目數", "entryNum": "條目數",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "晚於", "filterOperatorIsAfter": "晚於",
"filterOperatorIsOnOrBefore": "早於或等於", "filterOperatorIsOnOrBefore": "早於或等於",
"filterOperatorIsOnOrAfter": "晚於或等於", "filterOperatorIsOnOrAfter": "晚於或等於",
"filterQuantifierAny": "任一",
"filterQuantifierAll": "所有",
"filterQuantifierNone": "沒有",
"asc": "升序", "asc": "升序",
"desc": "降序", "desc": "降序",
"hideCol": "隱藏欄位", "hideCol": "隱藏欄位",
@ -1121,7 +1124,7 @@
"fileTree3": "刪除文檔時不需要確認", "fileTree3": "刪除文檔時不需要確認",
"fileTree4": "不啟用時每次刪除文檔都會彈出確認框", "fileTree4": "不啟用時每次刪除文檔都會彈出確認框",
"fileTree5": "塊引新建文檔存放位置", "fileTree5": "塊引新建文檔存放位置",
"fileTree6": "使用 <code class='fn__code'>((</code> 時新建文檔的存放路徑(例如 <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>", "fileTree6": "使用 <code class='fn__code'>((</code> 或 <code class='fn__code'>[[</code> 時新建文檔的存放路徑(例如 <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>",
"fileTree7": "在當前分頁中打開", "fileTree7": "在當前分頁中打開",
"fileTree8": "新打開的文檔分頁將會替換沒有修改過的分頁", "fileTree8": "新打開的文檔分頁將會替換沒有修改過的分頁",
"fileTree9": "啟動時關閉所有分頁", "fileTree9": "啟動時關閉所有分頁",

View file

@ -41,7 +41,7 @@
"reconnectPrompt": "切换应用后再次进入需要一些时间恢复思源内核运行,请稍等几秒或者点击“重试”按钮", "reconnectPrompt": "切换应用后再次进入需要一些时间恢复思源内核运行,请稍等几秒或者点击“重试”按钮",
"relativeFontSize": "相对于编辑器字号", "relativeFontSize": "相对于编辑器字号",
"localFileSystem": "本地文件系统", "localFileSystem": "本地文件系统",
"deviceNotSupport": "当前设备不支持", "mobileNotSupport": "移动端(手机或平板)设备目前不支持该功能",
"second": "秒", "second": "秒",
"syncInterval": "同步间隔", "syncInterval": "同步间隔",
"syncIntervalTip": "数据不再变动后自动进行数据同步", "syncIntervalTip": "数据不再变动后自动进行数据同步",
@ -54,7 +54,7 @@
"dataRepoAutoPurgeRetentionIndexesDaily": "数据快照每天保留个数", "dataRepoAutoPurgeRetentionIndexesDaily": "数据快照每天保留个数",
"fields": "字段", "fields": "字段",
"dynamicIcon": "动态图标", "dynamicIcon": "动态图标",
"dynamicIconDateEmptyInfo": "若日期为空,日历图标将动态显示当天日期", "dynamicIconDateEmptyInfo": "清除日期,日历图标将动态显示当天日期",
"backlinkContainChildren": "反向链接包含子块", "backlinkContainChildren": "反向链接包含子块",
"backlinkContainChildrenTip": "启用后子块将被纳入到反向链接计算中", "backlinkContainChildrenTip": "启用后子块将被纳入到反向链接计算中",
"entryNum": "条目数", "entryNum": "条目数",
@ -340,6 +340,9 @@
"filterOperatorIsAfter": "晚于", "filterOperatorIsAfter": "晚于",
"filterOperatorIsOnOrBefore": "早于或等于", "filterOperatorIsOnOrBefore": "早于或等于",
"filterOperatorIsOnOrAfter": "晚于或等于", "filterOperatorIsOnOrAfter": "晚于或等于",
"filterQuantifierAny": "任一",
"filterQuantifierAll": "所有",
"filterQuantifierNone": "没有",
"asc": "升序", "asc": "升序",
"desc": "降序", "desc": "降序",
"hideCol": "隐藏字段", "hideCol": "隐藏字段",
@ -1121,7 +1124,7 @@
"fileTree3": "删除文档时不需要确认", "fileTree3": "删除文档时不需要确认",
"fileTree4": "不启用时每次删除文档都会弹出确认框", "fileTree4": "不启用时每次删除文档都会弹出确认框",
"fileTree5": "块引新建文档存放位置", "fileTree5": "块引新建文档存放位置",
"fileTree6": "使用 <code class='fn__code'>((</code> 时新建文档的存放路径(例如 <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>", "fileTree6": "使用 <code class='fn__code'>((</code> 或 <code class='fn__code'>[[</code> 时新建文档的存放路径(例如 <code class='fn__code'>/folder1/{{now | date \"20060102150405\"}}/</code>",
"fileTree7": "在当前页签中打开", "fileTree7": "在当前页签中打开",
"fileTree8": "新打开的文档页签将会替换没有修改过的页签", "fileTree8": "新打开的文档页签将会替换没有修改过的页签",
"fileTree9": "启动时关闭所有页签", "fileTree9": "启动时关闭所有页签",

View file

@ -9,7 +9,7 @@
<Identity Name="89C2A984.SiYuan" <Identity Name="89C2A984.SiYuan"
ProcessorArchitecture="x64" ProcessorArchitecture="x64"
Publisher="CN=087C656E-C1D9-42D8-8807-CED45A74FC0F" Publisher="CN=087C656E-C1D9-42D8-8807-CED45A74FC0F"
Version="3.3.1.0"/> Version="3.3.2.0"/>
<Properties> <Properties>
<DisplayName>SiYuan</DisplayName> <DisplayName>SiYuan</DisplayName>
<PublisherDisplayName>云南链滴科技有限公司</PublisherDisplayName> <PublisherDisplayName>云南链滴科技有限公司</PublisherDisplayName>

View file

@ -21,7 +21,7 @@ Below are the detailed changes in this version.
* [Database cells support vertical dragging to fill values](https://github.com/siyuan-note/siyuan/issues/12907) * [Database cells support vertical dragging to fill values](https://github.com/siyuan-note/siyuan/issues/12907)
* [Improve document tree movement and its animation](https://github.com/siyuan-note/siyuan/issues/12914) * [Improve document tree movement and its animation](https://github.com/siyuan-note/siyuan/issues/12914)
* [Improve S3/WebDAV data sync config](https://github.com/siyuan-note/siyuan/issues/12923) * [Improve S3/WebDAV data sync config](https://github.com/siyuan-note/siyuan/issues/12923)
* [The Publishing service no longer support export](https://github.com/siyuan-note/siyuan/issues/12928) * [The Publish service no longer support export](https://github.com/siyuan-note/siyuan/issues/12928)
* [Display document title in data history preview area](https://github.com/siyuan-note/siyuan/issues/12948) * [Display document title in data history preview area](https://github.com/siyuan-note/siyuan/issues/12948)
* [Improve parsing `<img>` when importing markdown](https://github.com/siyuan-note/siyuan/issues/12956) * [Improve parsing `<img>` when importing markdown](https://github.com/siyuan-note/siyuan/issues/12956)
* [Improve parsing of YAML Front Matter when importing Markdown](https://github.com/siyuan-note/siyuan/issues/12962) * [Improve parsing of YAML Front Matter when importing Markdown](https://github.com/siyuan-note/siyuan/issues/12962)

View file

@ -0,0 +1,48 @@
## Overview
This version improves some details.
## Changelogs
Below are the detailed changes in this version.
### Enhancement
* [Copy/Cut folded heading changed to copy/cut `Headings and Bottom Blocks` and support multiple headings copy/cut](https://github.com/siyuan-note/siyuan/issues/8019)
* [Improve database field editing menu](https://github.com/siyuan-note/siyuan/issues/15185)
* [Database rollup field filtering rules support "Any", "All", and "None"](https://github.com/siyuan-note/siyuan/issues/15609)
* [Improve flashcards](https://github.com/siyuan-note/siyuan/issues/15699)
* [If the new data created in the database is in a collapsed group, the edit box will not pop up](https://github.com/siyuan-note/siyuan/issues/15728)
* [Select Copy in the code block to copy only the plain text](https://github.com/siyuan-note/siyuan/issues/15733)
* [Use the default sorting when the search content in the code block language prompt is empty](https://github.com/siyuan-note/siyuan/issues/15737)
* [Improve database rollup field filtering](https://github.com/siyuan-note/siyuan/issues/15740)
* [Improve database date field filtering](https://github.com/siyuan-note/siyuan/issues/15744)
* [Disable editing when adding options to the database](https://github.com/siyuan-note/siyuan/issues/15751)
* [After dragging database entries across groups, groups in other views need to be updated](https://github.com/siyuan-note/siyuan/issues/15755)
* [Browser clipping extension supports clipping page to the database](https://github.com/siyuan-note/siyuan/issues/15758)
* [Hide the bottom gesture navigation bar on Android](https://github.com/siyuan-note/siyuan/issues/15763)
* [Improve database group view performance](https://github.com/siyuan-note/siyuan/issues/15764)
* [Dragging multiple files into the editor will cause them to be opened by the default program](https://github.com/siyuan-note/siyuan/pull/15773)
* [Improve HTML table clipping](https://github.com/siyuan-note/siyuan/issues/15781)
* [Automatically create a new document when clicking on a notebook without documents](https://github.com/siyuan-note/siyuan/issues/15782)
* [Add field `disabledInPublish` to the code snippet to indicate whether it is disabled in the publish service](https://github.com/siyuan-note/siyuan/issues/15806)
### Bugfix
* [PDF files with too long file names cannot generate annotated images](https://github.com/siyuan-note/siyuan/issues/15739)
* [The video block network address is incorrect](https://github.com/siyuan-note/siyuan/issues/15741)
* [The database date field cannot paste the time of 0 o'clock](https://github.com/siyuan-note/siyuan/issues/15742)
* [Read-only mode cannot be set in preview mode](https://github.com/siyuan-note/siyuan/issues/15756)
* [Exception when inserting batch files into the editor](https://github.com/siyuan-note/siyuan/issues/15768)
* [When using certain input methods, punctuation characters are inserted twice after pasting a link at the end of a block](https://github.com/siyuan-note/siyuan/issues/15801)
### Development
* [Add field `disabledInPublish` to the marketplace plugin package metadata to indicate whether it is disabled in the publish service](https://github.com/siyuan-note/siyuan/issues/11730)
* [Add plugin function `expandDocTree`](https://github.com/siyuan-note/siyuan/issues/15639)
* [Improve kernel API `appendBlock`, `insertBlock` and `prependBlock`](https://github.com/siyuan-note/siyuan/issues/15798)
## Download
* [B3log](https://b3log.org/siyuan/en/download.html)
* [GitHub](https://github.com/siyuan-note/siyuan/releases)

View file

@ -0,0 +1,48 @@
## 概述
該版本改進了一些細節。
## 變更記錄
以下是此版本中的詳細變更。
### 改進功能
* [折疊標題的複製/剪切改為複製/剪切 `標題及其下方塊`,並支援多標題複製/剪切](https://github.com/siyuan-note/siyuan/issues/8019)
* [改進資料庫欄位編輯選單](https://github.com/siyuan-note/siyuan/issues/15185)
* [資料庫匯總欄位篩選規則支援「任一」、「所有」和「沒有」](https://github.com/siyuan-note/siyuan/issues/15609)
* [改良閃卡](https://github.com/siyuan-note/siyuan/issues/15699)
* [資料庫中新建資料如果在折疊分組內,不再彈出編輯框](https://github.com/siyuan-note/siyuan/issues/15728)
* [程式碼區塊選擇複製時僅複製純文字](https://github.com/siyuan-note/siyuan/issues/15733)
* [程式碼區塊語言提示搜尋內容為空時使用預設排序](https://github.com/siyuan-note/siyuan/issues/15737)
* [改進資料庫匯總欄位篩選](https://github.com/siyuan-note/siyuan/issues/15740)
* [改進資料庫日期欄位篩選](https://github.com/siyuan-note/siyuan/issues/15744)
* [資料庫新增選項時禁止編輯](https://github.com/siyuan-note/siyuan/issues/15751)
* [資料庫條目跨分組拖曳後,同步更新其他檢視中的分組](https://github.com/siyuan-note/siyuan/issues/15755)
* [瀏覽器剪藏擴充功能支援剪藏頁面到資料庫](https://github.com/siyuan-note/siyuan/issues/15758)
* [Android 隱藏底部手勢導覽列](https://github.com/siyuan-note/siyuan/issues/15763)
* [提升資料庫分組檢視效能](https://github.com/siyuan-note/siyuan/issues/15764)
* [拖入多個檔案到編輯器不再被預設程式開啟](https://github.com/siyuan-note/siyuan/pull/15773)
* [改進 HTML 表格剪藏](https://github.com/siyuan-note/siyuan/issues/15781)
* [點選無文件的筆記本時自動新建文件](https://github.com/siyuan-note/siyuan/issues/15782)
* [程式碼片段新增欄位 `disabledInPublish`,用於識別發佈服務中是否已停用](https://github.com/siyuan-note/siyuan/issues/15806)
### 修復缺陷
* [PDF 檔名過長無法產生標註圖片](https://github.com/siyuan-note/siyuan/issues/15739)
* [影片區塊網路網址不正確](https://github.com/siyuan-note/siyuan/issues/15741)
* [資料庫日期欄位無法貼上 0 點時間](https://github.com/siyuan-note/siyuan/issues/15742)
* [預覽模式下無法設定唯讀模式](https://github.com/siyuan-note/siyuan/issues/15756)
* [批次插入檔案到編輯器時異常](https://github.com/siyuan-note/siyuan/issues/15768)
* [部分輸入法在區塊末尾貼上連結後標點符號重複插入](https://github.com/siyuan-note/siyuan/issues/15801)
### 開發者
* [集市插件包元資料新增欄位 `disabledInPublish`,用於識別發布服務中是否已停用](https://github.com/siyuan-note/siyuan/issues/11730)
* [新增外掛程式 `expandDocTree`](https://github.com/siyuan-note/siyuan/issues/15639)
* [改進內核 API `appendBlock`、`insertBlock` 和 `prependBlock`](https://github.com/siyuan-note/siyuan/issues/15798)
## 下載
* [B3log](https://b3log.org/siyuan/download.html)
* [GitHub](https://github.com/siyuan-note/siyuan/releases)

View file

@ -0,0 +1,48 @@
## 概述
该版本改进了一些细节。
## 变更记录
以下是此版本中的详细变更。
### 改进功能
* [折叠标题的复制/剪切改为复制/剪切 `标题及其下方块`,并支持多标题复制/剪切](https://github.com/siyuan-note/siyuan/issues/8019)
* [改进数据库字段编辑菜单](https://github.com/siyuan-note/siyuan/issues/15185)
* [数据库汇总字段筛选规则支持“任一”、“所有”和“没有”](https://github.com/siyuan-note/siyuan/issues/15609)
* [改进闪卡](https://github.com/siyuan-note/siyuan/issues/15699)
* [数据库中新建数据如果在折叠分组内,不再弹出编辑框](https://github.com/siyuan-note/siyuan/issues/15728)
* [代码块选择复制时仅复制纯文本](https://github.com/siyuan-note/siyuan/issues/15733)
* [代码块语言提示搜索内容为空时使用默认排序](https://github.com/siyuan-note/siyuan/issues/15737)
* [改进数据库汇总字段筛选](https://github.com/siyuan-note/siyuan/issues/15740)
* [改进数据库日期字段筛选](https://github.com/siyuan-note/siyuan/issues/15744)
* [数据库添加选项时禁止编辑](https://github.com/siyuan-note/siyuan/issues/15751)
* [数据库条目跨分组拖动后,同步更新其他视图中的分组](https://github.com/siyuan-note/siyuan/issues/15755)
* [浏览器剪藏扩展支持剪藏页面到数据库](https://github.com/siyuan-note/siyuan/issues/15758)
* [Android 隐藏底部手势导航栏](https://github.com/siyuan-note/siyuan/issues/15763)
* [提升数据库分组视图性能](https://github.com/siyuan-note/siyuan/issues/15764)
* [拖入多个文件到编辑器不再被默认程序打开](https://github.com/siyuan-note/siyuan/pull/15773)
* [改进 HTML 表格剪藏](https://github.com/siyuan-note/siyuan/issues/15781)
* [点击无文档的笔记本时自动新建文档](https://github.com/siyuan-note/siyuan/issues/15782)
* [代码片段新增字段 `disabledInPublish`,用于标识发布服务中是否禁用](https://github.com/siyuan-note/siyuan/issues/15806)
### 修复缺陷
* [PDF 文件名过长无法生成标注图片](https://github.com/siyuan-note/siyuan/issues/15739)
* [视频块网络地址不正确](https://github.com/siyuan-note/siyuan/issues/15741)
* [数据库日期字段无法粘贴 0 点时间](https://github.com/siyuan-note/siyuan/issues/15742)
* [预览模式下无法设置只读模式](https://github.com/siyuan-note/siyuan/issues/15756)
* [批量插入文件到编辑器时异常](https://github.com/siyuan-note/siyuan/issues/15768)
* [部分输入法在块末尾粘贴链接后标点符号重复插入](https://github.com/siyuan-note/siyuan/issues/15801)
### 开发者
* [集市插件包元数据新增字段 `disabledInPublish`,用于标识发布服务中是否禁用](https://github.com/siyuan-note/siyuan/issues/11730)
* [新增插件函数 `expandDocTree`](https://github.com/siyuan-note/siyuan/issues/15639)
* [改进内核 API `appendBlock`、`insertBlock` 和 `prependBlock`](https://github.com/siyuan-note/siyuan/issues/15798)
## 下载
* [B3log](https://b3log.org/siyuan/download.html)
* [GitHub](https://github.com/siyuan-note/siyuan/releases)

View file

@ -3820,7 +3820,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "In the code block, only select the content of the code block" "Data": "Double press to select all loaded content blocks in the document; in the code block, only select the content of the code block"
} }
] ]
} }

View file

@ -102,7 +102,7 @@
}, },
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": " to enter the publishing service settings panel." "Data": " to enter the publish service settings panel."
} }
] ]
} }
@ -252,7 +252,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "If access control is required for the publishing service:" "Data": "If access control is required for the publish service:"
} }
] ]
}, },
@ -333,7 +333,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "When enabled, the publishing service will use the " "Data": "When enabled, the publish service will use the "
}, },
{ {
"Type": "NodeTextMark", "Type": "NodeTextMark",
@ -482,7 +482,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "After enabling the publishing service, visitors can browse the content of the entire workspace." "Data": "After enabling the publish service, visitors can browse the content of the entire workspace."
} }
] ]
} }

View file

@ -5,7 +5,8 @@
"Properties": { "Properties": {
"id": "20230805232134-3d6mx2k", "id": "20230805232134-3d6mx2k",
"title": "Search asset content", "title": "Search asset content",
"updated": "20231026085302" "type": "doc",
"updated": "20250903163017"
}, },
"Children": [ "Children": [
{ {
@ -46,7 +47,7 @@
"ListData": {}, "ListData": {},
"Properties": { "Properties": {
"id": "20230818102341-ny18orr", "id": "20230818102341-ny18orr",
"updated": "20230818102341" "updated": "20250903163017"
}, },
"Children": [ "Children": [
{ {
@ -58,7 +59,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818102341-eg8labw", "id": "20230818102341-eg8labw",
"updated": "20230818102341" "updated": "20250903163017"
}, },
"Children": [ "Children": [
{ {
@ -66,12 +67,318 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102341-izc16tp", "id": "20230818102341-izc16tp",
"updated": "20230818102426" "updated": "20250903163017"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "Text files (.txt, .md, .json, .log, .sql, .html, .xml, .java, .h, .c, .cpp, .go, .rs, .swift, .kt, . py, .php, .js, .css, .ts, .sh, .bat, .cmd, .ini, .yaml, .rst, .adoc, .textile, .opml, .org, .wiki)" "Data": "Text files ("
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".txt"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".md"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".markdown"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".json"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".log"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sql"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".html"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xml"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".java"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".h"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".c"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cpp"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".go"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rs"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".swift"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".kt"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".py"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".php"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".js"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".css"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ts"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sh"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".bat"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cmd"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ini"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".yaml"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rst"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".adoc"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".textile"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".opml"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".org"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".wiki"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".epub"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cs"
},
{
"Type": "NodeText",
"Data": ")"
} }
] ]
} }
@ -85,7 +392,8 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818102427-os9c4nm" "id": "20230818102427-os9c4nm",
"updated": "20250903162955"
}, },
"Children": [ "Children": [
{ {
@ -93,12 +401,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102427-dyojs23", "id": "20230818102427-dyojs23",
"updated": "20230818102429" "updated": "20250903162955"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".docx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".docx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -112,7 +429,8 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818102430-sw9p4uf" "id": "20230818102430-sw9p4uf",
"updated": "20250903162956"
}, },
"Children": [ "Children": [
{ {
@ -120,12 +438,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102430-boci4wf", "id": "20230818102430-boci4wf",
"updated": "20230818102431" "updated": "20250903162956"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pptx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pptx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -139,7 +466,8 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818102432-6uclx4n" "id": "20230818102432-6uclx4n",
"updated": "20250903162957"
}, },
"Children": [ "Children": [
{ {
@ -147,12 +475,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102432-3n95b7k", "id": "20230818102432-3n95b7k",
"updated": "20230818102433" "updated": "20250903162957"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".xlsx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xlsx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -166,19 +503,30 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818102434-9xgwy7r" "id": "20230818102434-9xgwy7r",
"updated": "20250903162959"
}, },
"Children": [ "Children": [
{ {
"ID": "20230818102434-1efdkw9", "ID": "20230818102434-1efdkw9",
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102434-1efdkw9" "id": "20230818102434-1efdkw9",
"updated": "20250903162959"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pdf" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pdf"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }

View file

@ -3818,7 +3818,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "代码块中使用时仅选中代码块中的内容" "Data": "连续按下两次以选中文档中所有已加载的内容块;代码块中使用时仅选中代码块中的内容"
} }
] ]
} }

View file

@ -5,7 +5,8 @@
"Properties": { "Properties": {
"id": "20230805230218-aea8icj", "id": "20230805230218-aea8icj",
"title": "搜索资源文件内容", "title": "搜索资源文件内容",
"updated": "20231026085139" "type": "doc",
"updated": "20250903162923"
}, },
"Children": [ "Children": [
{ {
@ -46,7 +47,7 @@
"ListData": {}, "ListData": {},
"Properties": { "Properties": {
"id": "20230818101450-4a6lzdg", "id": "20230818101450-4a6lzdg",
"updated": "20230818101545" "updated": "20250903162923"
}, },
"Children": [ "Children": [
{ {
@ -58,7 +59,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818101510-rfacaaf", "id": "20230818101510-rfacaaf",
"updated": "20230818101800" "updated": "20250903162915"
}, },
"Children": [ "Children": [
{ {
@ -66,12 +67,318 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818101510-duzarcy", "id": "20230818101510-duzarcy",
"updated": "20230818101800" "updated": "20250903162915"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "文本文件(.txt、.md、.json、.log、.sql、.html、.xml、.java、.h、.c、.cpp、.go、.rs、.swift、.kt、.py、.php、.js、.css、.ts、.sh、.bat、.cmd、.ini、.yaml、.rst、.adoc、.textile、.opml、.org、.wiki" "Data": "文本文件("
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".txt"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".md"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".markdown"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".json"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".log"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sql"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".html"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xml"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".java"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".h"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".c"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cpp"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".go"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rs"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".swift"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".kt"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".py"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".php"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".js"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".css"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ts"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sh"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".bat"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cmd"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ini"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".yaml"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rst"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".adoc"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".textile"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".opml"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".org"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".wiki"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".epub"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cs"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -85,7 +392,8 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818101513-x5baw16" "id": "20230818101513-x5baw16",
"updated": "20250903162918"
}, },
"Children": [ "Children": [
{ {
@ -93,12 +401,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818101513-558ntbl", "id": "20230818101513-558ntbl",
"updated": "20230818101520" "updated": "20250903162918"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".docx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".docx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -112,7 +429,8 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818101521-n1r8yqv" "id": "20230818101521-n1r8yqv",
"updated": "20250903162920"
}, },
"Children": [ "Children": [
{ {
@ -120,12 +438,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818101521-mutuxqo", "id": "20230818101521-mutuxqo",
"updated": "20230818101526" "updated": "20250903162920"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pptx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pptx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -139,7 +466,8 @@
"Marker": "Kg==" "Marker": "Kg=="
}, },
"Properties": { "Properties": {
"id": "20230818101526-oortrwo" "id": "20230818101526-oortrwo",
"updated": "20250903162921"
}, },
"Children": [ "Children": [
{ {
@ -147,12 +475,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818101526-t4uvb3w", "id": "20230818101526-t4uvb3w",
"updated": "20230818101529" "updated": "20250903162921"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".xlsx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xlsx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -167,7 +504,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818101543-ejcoq3j", "id": "20230818101543-ejcoq3j",
"updated": "20230818101545" "updated": "20250903162923"
}, },
"Children": [ "Children": [
{ {
@ -175,12 +512,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818101543-36waszk", "id": "20230818101543-36waszk",
"updated": "20230818101545" "updated": "20250903162923"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pdf" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pdf"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }

View file

@ -3808,7 +3808,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "代碼塊中使用時僅選中代碼塊中的內容" "Data": "連續按下兩次以選中文檔中所有已加載的內容塊;代碼塊中使用時僅選中代碼塊中的內容"
} }
] ]
} }

View file

@ -5,7 +5,8 @@
"Properties": { "Properties": {
"id": "20230805232920-5fdco36", "id": "20230805232920-5fdco36",
"title": "搜索資源文件內容", "title": "搜索資源文件內容",
"updated": "20231026085346" "type": "doc",
"updated": "20250903162952"
}, },
"Children": [ "Children": [
{ {
@ -46,7 +47,7 @@
"ListData": {}, "ListData": {},
"Properties": { "Properties": {
"id": "20230818102501-gq9fesz", "id": "20230818102501-gq9fesz",
"updated": "20230818102519" "updated": "20250903162952"
}, },
"Children": [ "Children": [
{ {
@ -58,7 +59,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818102501-2qu8flm", "id": "20230818102501-2qu8flm",
"updated": "20230818102519" "updated": "20250903162947"
}, },
"Children": [ "Children": [
{ {
@ -66,12 +67,318 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102501-p1l631d", "id": "20230818102501-p1l631d",
"updated": "20230818102519" "updated": "20250903162947"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "文本文件(.txt、.md、.json、.log、.sql、.html、.xml、.java、.h、.c、.cpp、.go、.rs、.swift、.kt、.py、.php、.js、.css、.ts、.sh、.bat、.cmd、.ini、.yaml、.rst、.adoc、.textile、.opml、.org、.wiki" "Data": "文本文件("
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".txt"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".md"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".markdown"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".json"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".log"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sql"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".html"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xml"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".java"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".h"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".c"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cpp"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".go"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rs"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".swift"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".kt"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".py"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".php"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".js"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".css"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ts"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sh"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".bat"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cmd"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ini"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".yaml"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rst"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".adoc"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".textile"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".opml"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".org"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".wiki"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".epub"
},
{
"Type": "NodeText",
"Data": "​、"
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cs"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -86,7 +393,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818102501-8jue7y8", "id": "20230818102501-8jue7y8",
"updated": "20230818102501" "updated": "20250903162949"
}, },
"Children": [ "Children": [
{ {
@ -94,12 +401,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102501-fom9qf4", "id": "20230818102501-fom9qf4",
"updated": "20230818102501" "updated": "20250903162949"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".docx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".docx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -114,7 +430,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818102501-609htp0", "id": "20230818102501-609htp0",
"updated": "20230818102501" "updated": "20250903162950"
}, },
"Children": [ "Children": [
{ {
@ -122,12 +438,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102501-fu9up7s", "id": "20230818102501-fu9up7s",
"updated": "20230818102501" "updated": "20250903162950"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pptx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pptx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -142,7 +467,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818102501-cjozdv1", "id": "20230818102501-cjozdv1",
"updated": "20230818102501" "updated": "20250903162951"
}, },
"Children": [ "Children": [
{ {
@ -150,12 +475,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102501-ewonoc2", "id": "20230818102501-ewonoc2",
"updated": "20230818102501" "updated": "20250903162951"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".xlsx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xlsx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -170,7 +504,7 @@
}, },
"Properties": { "Properties": {
"id": "20230818102501-ljun2c0", "id": "20230818102501-ljun2c0",
"updated": "20230818102501" "updated": "20250903162952"
}, },
"Children": [ "Children": [
{ {
@ -178,12 +512,21 @@
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"id": "20230818102501-w0e68xh", "id": "20230818102501-w0e68xh",
"updated": "20230818102501" "updated": "20250903162952"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pdf" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pdf"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }

View file

@ -7,7 +7,7 @@
"id": "20240530101000-5k5d5i3", "id": "20240530101000-5k5d5i3",
"title": "アセットの内容検索", "title": "アセットの内容検索",
"type": "doc", "type": "doc",
"updated": "20240530101000" "updated": "20250903163024"
}, },
"Children": [ "Children": [
{ {
@ -50,7 +50,7 @@
"Properties": { "Properties": {
"ID": "20240530101000-gui4fuq", "ID": "20240530101000-gui4fuq",
"id": "20240530101000-dy607mr", "id": "20240530101000-dy607mr",
"updated": "20240530101000" "updated": "20250903163024"
}, },
"Children": [ "Children": [
{ {
@ -63,21 +63,326 @@
"Properties": { "Properties": {
"ID": "20240530101000-d6fzgev", "ID": "20240530101000-d6fzgev",
"id": "20240530101000-423ygdo", "id": "20240530101000-423ygdo",
"updated": "20240530101000" "updated": "20250903163024"
}, },
"Children": [ "Children": [
{ {
"ID": "20240530101000-5htsgo0", "ID": "20240530101000-5htsgo0",
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"ID": "20240530101000-lunnpt0",
"id": "20240530101000-5htsgo0", "id": "20240530101000-5htsgo0",
"updated": "20240530101000" "updated": "20250903163024"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "テキストファイル (.txt, .md, .json, .log, .sql, .html, .xml, .java, .h, .c, .cpp, .go, .rs, .swift, .kt, . py, .php, .js, .css, .ts, .sh, .bat, .cmd, .ini, .yaml, .rst, .adoc, .textile, .opml, .org, .wiki)" "Data": "テキストファイル ("
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".txt"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".md"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".markdown"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".json"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".log"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sql"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".html"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xml"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".java"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".h"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".c"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cpp"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".go"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rs"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".swift"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".kt"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".py"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".php"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".js"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".css"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ts"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".sh"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".bat"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cmd"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".ini"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".yaml"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".rst"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".adoc"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".textile"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".opml"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".org"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".wiki"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".epub"
},
{
"Type": "NodeText",
"Data": ", "
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".cs"
},
{
"Type": "NodeText",
"Data": ")"
} }
] ]
} }
@ -92,21 +397,30 @@
}, },
"Properties": { "Properties": {
"ID": "20240530101000-jhc3a4i", "ID": "20240530101000-jhc3a4i",
"id": "20240530101000-ddgjyye" "id": "20240530101000-ddgjyye",
"updated": "20250903163001"
}, },
"Children": [ "Children": [
{ {
"ID": "20240530101000-alu1ygl", "ID": "20240530101000-alu1ygl",
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"ID": "20240530101000-cznhpu3",
"id": "20240530101000-alu1ygl", "id": "20240530101000-alu1ygl",
"updated": "20240530101000" "updated": "20250903163001"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".docx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".docx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -121,21 +435,30 @@
}, },
"Properties": { "Properties": {
"ID": "20240530101000-0t3jtob", "ID": "20240530101000-0t3jtob",
"id": "20240530101000-t8ewu5o" "id": "20240530101000-t8ewu5o",
"updated": "20250903163002"
}, },
"Children": [ "Children": [
{ {
"ID": "20240530101000-afub9kt", "ID": "20240530101000-afub9kt",
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"ID": "20240530101000-isl867u",
"id": "20240530101000-afub9kt", "id": "20240530101000-afub9kt",
"updated": "20240530101000" "updated": "20250903163002"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pptx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pptx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -150,21 +473,30 @@
}, },
"Properties": { "Properties": {
"ID": "20240530101000-79w2hmi", "ID": "20240530101000-79w2hmi",
"id": "20240530101000-6c3or97" "id": "20240530101000-6c3or97",
"updated": "20250903163003"
}, },
"Children": [ "Children": [
{ {
"ID": "20240530101000-p5qs8ir", "ID": "20240530101000-p5qs8ir",
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"ID": "20240530101000-zo7jhc4",
"id": "20240530101000-p5qs8ir", "id": "20240530101000-p5qs8ir",
"updated": "20240530101000" "updated": "20250903163003"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".xlsx" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".xlsx"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }
@ -179,20 +511,30 @@
}, },
"Properties": { "Properties": {
"ID": "20240530101000-nm831gm", "ID": "20240530101000-nm831gm",
"id": "20240530101000-napqxcr" "id": "20240530101000-napqxcr",
"updated": "20250903163004"
}, },
"Children": [ "Children": [
{ {
"ID": "20240530101000-vknnawk", "ID": "20240530101000-vknnawk",
"Type": "NodeParagraph", "Type": "NodeParagraph",
"Properties": { "Properties": {
"ID": "20240530101000-l05rbi9", "id": "20240530101000-vknnawk",
"id": "20240530101000-vknnawk" "updated": "20250903163004"
}, },
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": ".pdf" "Data": ""
},
{
"Type": "NodeTextMark",
"TextMarkType": "code",
"TextMarkTextContent": ".pdf"
},
{
"Type": "NodeText",
"Data": ""
} }
] ]
} }

View file

@ -3775,7 +3775,7 @@
"Children": [ "Children": [
{ {
"Type": "NodeText", "Type": "NodeText",
"Data": "コードブロックではコードのみが選択されます" "Data": "文書内のすべてのロード済みコンテンツブロックを選択するにはダブルプレスしてください;コードブロックではコードのみが選択されます"
} }
] ]
} }

View file

@ -1,10 +1,10 @@
{ {
"name": "SiYuan", "name": "SiYuan",
"version": "3.3.1", "version": "3.3.2",
"description": "Refactor your thinking", "description": "Refactor your thinking",
"homepage": "https://b3log.org/siyuan", "homepage": "https://b3log.org/siyuan",
"main": "./electron/main.js", "main": "./electron/main.js",
"packageManager": "pnpm@10.15.0", "packageManager": "pnpm@10.15.1",
"scripts": { "scripts": {
"lint": "eslint . --fix --cache", "lint": "eslint . --fix --cache",
"dev": "webpack --mode development", "dev": "webpack --mode development",

264
app/pnpm-lock.yaml generated
View file

@ -17,16 +17,16 @@ importers:
version: 3.3.1 version: 3.3.1
'@eslint/js': '@eslint/js':
specifier: ^9.24.0 specifier: ^9.24.0
version: 9.34.0 version: 9.35.0
'@types/node': '@types/node':
specifier: ^18.13.0 specifier: ^18.13.0
version: 18.19.123 version: 18.19.124
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^8.15.0 specifier: ^8.15.0
version: 8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@4.9.5))(eslint@9.34.0)(typescript@4.9.5) version: 8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0)(typescript@4.9.5))(eslint@9.35.0)(typescript@4.9.5)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^8.15.0 specifier: ^8.15.0
version: 8.41.0(eslint@9.34.0)(typescript@4.9.5) version: 8.42.0(eslint@9.35.0)(typescript@4.9.5)
blueimp-md5: blueimp-md5:
specifier: ^2.19.0 specifier: ^2.19.0
version: 2.19.0 version: 2.19.0
@ -38,7 +38,7 @@ importers:
version: 7.1.2(webpack@5.101.3) version: 7.1.2(webpack@5.101.3)
dayjs: dayjs:
specifier: ^1.11.5 specifier: ^1.11.5
version: 1.11.15 version: 1.11.18
electron: electron:
specifier: 37.4.0 specifier: 37.4.0
version: 37.4.0 version: 37.4.0
@ -53,7 +53,7 @@ importers:
version: 3.2.0(webpack@5.101.3) version: 3.2.0(webpack@5.101.3)
eslint: eslint:
specifier: ^9.15.0 specifier: ^9.15.0
version: 9.34.0 version: 9.35.0
file-loader: file-loader:
specifier: ^6.2.0 specifier: ^6.2.0
version: 6.2.0(webpack@5.101.3) version: 6.2.0(webpack@5.101.3)
@ -83,10 +83,10 @@ importers:
version: 2.1.2 version: 2.1.2
sass: sass:
specifier: ^1.89.2 specifier: ^1.89.2
version: 1.91.0 version: 1.92.1
sass-loader: sass-loader:
specifier: ^16.0.5 specifier: ^16.0.5
version: 16.0.5(sass@1.91.0)(webpack@5.101.3) version: 16.0.5(sass@1.92.1)(webpack@5.101.3)
typescript: typescript:
specifier: ^4.7.4 specifier: ^4.7.4
version: 4.9.5 version: 4.9.5
@ -303,8 +303,8 @@ packages:
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@eslint-community/eslint-utils@4.7.0': '@eslint-community/eslint-utils@4.8.0':
resolution: {integrity: sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==} resolution: {integrity: sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
@ -329,8 +329,8 @@ packages:
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/js@9.34.0': '@eslint/js@9.35.0':
resolution: {integrity: sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==} resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6': '@eslint/object-schema@2.1.6':
@ -348,18 +348,14 @@ packages:
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'} engines: {node: '>=18.18.0'}
'@humanfs/node@0.16.6': '@humanfs/node@0.16.7':
resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
engines: {node: '>=18.18.0'} engines: {node: '>=18.18.0'}
'@humanwhocodes/module-importer@1.0.1': '@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'} engines: {node: '>=12.22'}
'@humanwhocodes/retry@0.3.1':
resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
engines: {node: '>=18.18'}
'@humanwhocodes/retry@0.4.3': '@humanwhocodes/retry@0.4.3':
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'} engines: {node: '>=18.18'}
@ -568,11 +564,11 @@ packages:
'@types/ms@2.1.0': '@types/ms@2.1.0':
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
'@types/node@18.19.123': '@types/node@18.19.124':
resolution: {integrity: sha512-K7DIaHnh0mzVxreCR9qwgNxp3MH9dltPNIEddW9MYUlcKAzm+3grKNSTe2vCJHI1FaLpvpL5JGJrz1UZDKYvDg==} resolution: {integrity: sha512-hY4YWZFLs3ku6D2Gqo3RchTd9VRCcrjqp/I0mmohYeUVA5Y8eCXKJEasHxLAJVZRJuQogfd1GiJ9lgogBgKeuQ==}
'@types/node@22.18.0': '@types/node@22.18.1':
resolution: {integrity: sha512-m5ObIqwsUp6BZzyiy4RdZpzWGub9bqLJMvZDD0QMXhxjqMHMENlj+SqF5QxoUwaQNFe+8kz8XM8ZQhqkQPTgMQ==} resolution: {integrity: sha512-rzSDyhn4cYznVG+PCzGe1lwuMYJrcBS1fc3JqSa2PvtABwWo+dZ1ij5OVok3tqfpEBCBoaR4d7upFJk73HRJDw==}
'@types/plist@3.0.5': '@types/plist@3.0.5':
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==} resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
@ -586,63 +582,63 @@ packages:
'@types/yauzl@2.10.3': '@types/yauzl@2.10.3':
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
'@typescript-eslint/eslint-plugin@8.41.0': '@typescript-eslint/eslint-plugin@8.42.0':
resolution: {integrity: sha512-8fz6oa6wEKZrhXWro/S3n2eRJqlRcIa6SlDh59FXJ5Wp5XRZ8B9ixpJDcjadHq47hMx0u+HW6SNa6LjJQ6NLtw==} resolution: {integrity: sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^8.41.0 '@typescript-eslint/parser': ^8.42.0
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/parser@8.41.0': '@typescript-eslint/parser@8.42.0':
resolution: {integrity: sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==} resolution: {integrity: sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/project-service@8.41.0': '@typescript-eslint/project-service@8.42.0':
resolution: {integrity: sha512-b8V9SdGBQzQdjJ/IO3eDifGpDBJfvrNTp2QD9P2BeqWTGrRibgfgIlBSw6z3b6R7dPzg752tOs4u/7yCLxksSQ==} resolution: {integrity: sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/scope-manager@8.41.0': '@typescript-eslint/scope-manager@8.42.0':
resolution: {integrity: sha512-n6m05bXn/Cd6DZDGyrpXrELCPVaTnLdPToyhBoFkLIMznRUQUEQdSp96s/pcWSQdqOhrgR1mzJ+yItK7T+WPMQ==} resolution: {integrity: sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/tsconfig-utils@8.41.0': '@typescript-eslint/tsconfig-utils@8.42.0':
resolution: {integrity: sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw==} resolution: {integrity: sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/type-utils@8.41.0': '@typescript-eslint/type-utils@8.42.0':
resolution: {integrity: sha512-63qt1h91vg3KsjVVonFJWjgSK7pZHSQFKH6uwqxAH9bBrsyRhO6ONoKyXxyVBzG1lJnFAJcKAcxLS54N1ee1OQ==} resolution: {integrity: sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/types@8.41.0': '@typescript-eslint/types@8.42.0':
resolution: {integrity: sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag==} resolution: {integrity: sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/typescript-estree@8.41.0': '@typescript-eslint/typescript-estree@8.42.0':
resolution: {integrity: sha512-D43UwUYJmGhuwHfY7MtNKRZMmfd8+p/eNSfFe6tH5mbVDto+VQCayeAt35rOx3Cs6wxD16DQtIKw/YXxt5E0UQ==} resolution: {integrity: sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/utils@8.41.0': '@typescript-eslint/utils@8.42.0':
resolution: {integrity: sha512-udbCVstxZ5jiPIXrdH+BZWnPatjlYwJuJkDA4Tbo3WyYLh8NvB+h/bKeSZHDOFKfphsZYJQqaFtLeXEqurQn1A==} resolution: {integrity: sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies: peerDependencies:
eslint: ^8.57.0 || ^9.0.0 eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <6.0.0' typescript: '>=4.8.4 <6.0.0'
'@typescript-eslint/visitor-keys@8.41.0': '@typescript-eslint/visitor-keys@8.42.0':
resolution: {integrity: sha512-+GeGMebMCy0elMNg67LRNoVnUFPIm37iu5CmHESVx56/9Jsfdpsvbv605DQ81Pi/x11IdKUsS5nzgTYbCQU9fg==} resolution: {integrity: sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@webassemblyjs/ast@1.14.1': '@webassemblyjs/ast@1.14.1':
@ -918,8 +914,8 @@ packages:
camel-case@4.1.2: camel-case@4.1.2:
resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
caniuse-lite@1.0.30001737: caniuse-lite@1.0.30001741:
resolution: {integrity: sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==} resolution: {integrity: sha512-QGUGitqsc8ARjLdgAfxETDhRbJ0REsP6O3I96TAth/mVjh2cYzN2u+3AzPP3aVSm2FehEItaJw1xd+IGBXWeSw==}
chalk@4.1.2: chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
@ -1073,8 +1069,8 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
dayjs@1.11.15: dayjs@1.11.18:
resolution: {integrity: sha512-MC+DfnSWiM9APs7fpiurHGCoeIx0Gdl6QZBy+5lu8MbYKN5FZEXqOgrundfibdfhGZ15o9hzmZ2xJjZnbvgKXQ==} resolution: {integrity: sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==}
debounce@1.2.1: debounce@1.2.1:
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
@ -1195,8 +1191,8 @@ packages:
electron-publish@26.0.11: electron-publish@26.0.11:
resolution: {integrity: sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==} resolution: {integrity: sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==}
electron-to-chromium@1.5.211: electron-to-chromium@1.5.214:
resolution: {integrity: sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==} resolution: {integrity: sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==}
electron-winstaller@5.4.0: electron-winstaller@5.4.0:
resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==} resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
@ -1298,8 +1294,8 @@ packages:
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint@9.34.0: eslint@9.35.0:
resolution: {integrity: sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==} resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
@ -2002,8 +1998,8 @@ packages:
no-case@3.0.4: no-case@3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
node-abi@3.75.0: node-abi@3.77.0:
resolution: {integrity: sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==} resolution: {integrity: sha512-DSmt0OEcLoK4i3NuscSbGjOf3bqiDEutejqENSplMSFA/gmB8mkED9G4pKWnPl7MDU4rSHebKPHeitpDfyH0cQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
node-addon-api@1.7.2: node-addon-api@1.7.2:
@ -2015,8 +2011,8 @@ packages:
node-api-version@0.2.1: node-api-version@0.2.1:
resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==} resolution: {integrity: sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==}
node-releases@2.0.19: node-releases@2.0.20:
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} resolution: {integrity: sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==}
nopt@6.0.0: nopt@6.0.0:
resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==} resolution: {integrity: sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==}
@ -2377,8 +2373,8 @@ packages:
webpack: webpack:
optional: true optional: true
sass@1.91.0: sass@1.92.1:
resolution: {integrity: sha512-aFOZHGf+ur+bp1bCHZ+u8otKGh77ZtmFyXDo4tlYvT7PWql41Kwd8wdkPqhhT+h2879IVblcHFglIMofsFd1EA==} resolution: {integrity: sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
hasBin: true hasBin: true
@ -2559,8 +2555,8 @@ packages:
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
hasBin: true hasBin: true
terser@5.43.1: terser@5.44.0:
resolution: {integrity: sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==} resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==}
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
@ -2857,7 +2853,7 @@ snapshots:
detect-libc: 2.0.4 detect-libc: 2.0.4
fs-extra: 10.1.0 fs-extra: 10.1.0
got: 11.8.6 got: 11.8.6
node-abi: 3.75.0 node-abi: 3.77.0
node-api-version: 0.2.1 node-api-version: 0.2.1
ora: 5.4.1 ora: 5.4.1
read-binary-file-arch: 1.0.6 read-binary-file-arch: 1.0.6
@ -2964,9 +2960,9 @@ snapshots:
'@esbuild/win32-x64@0.19.12': '@esbuild/win32-x64@0.19.12':
optional: true optional: true
'@eslint-community/eslint-utils@4.7.0(eslint@9.34.0)': '@eslint-community/eslint-utils@4.8.0(eslint@9.35.0)':
dependencies: dependencies:
eslint: 9.34.0 eslint: 9.35.0
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {} '@eslint-community/regexpp@4.12.1': {}
@ -2999,7 +2995,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@eslint/js@9.34.0': {} '@eslint/js@9.35.0': {}
'@eslint/object-schema@2.1.6': {} '@eslint/object-schema@2.1.6': {}
@ -3012,15 +3008,13 @@ snapshots:
'@humanfs/core@0.19.1': {} '@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.6': '@humanfs/node@0.16.7':
dependencies: dependencies:
'@humanfs/core': 0.19.1 '@humanfs/core': 0.19.1
'@humanwhocodes/retry': 0.3.1 '@humanwhocodes/retry': 0.4.3
'@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/module-importer@1.0.1': {}
'@humanwhocodes/retry@0.3.1': {}
'@humanwhocodes/retry@0.4.3': {} '@humanwhocodes/retry@0.4.3': {}
'@isaacs/balanced-match@4.0.1': {} '@isaacs/balanced-match@4.0.1': {}
@ -3170,7 +3164,7 @@ snapshots:
dependencies: dependencies:
'@types/http-cache-semantics': 4.0.4 '@types/http-cache-semantics': 4.0.4
'@types/keyv': 3.1.4 '@types/keyv': 3.1.4
'@types/node': 18.19.123 '@types/node': 18.19.124
'@types/responselike': 1.0.3 '@types/responselike': 1.0.3
'@types/debug@4.1.12': '@types/debug@4.1.12':
@ -3191,12 +3185,12 @@ snapshots:
'@types/fs-extra@9.0.13': '@types/fs-extra@9.0.13':
dependencies: dependencies:
'@types/node': 18.19.123 '@types/node': 18.19.124
'@types/glob@7.2.0': '@types/glob@7.2.0':
dependencies: dependencies:
'@types/minimatch': 6.0.0 '@types/minimatch': 6.0.0
'@types/node': 18.19.123 '@types/node': 18.19.124
'@types/html-minifier-terser@6.1.0': {} '@types/html-minifier-terser@6.1.0': {}
@ -3206,7 +3200,7 @@ snapshots:
'@types/keyv@3.1.4': '@types/keyv@3.1.4':
dependencies: dependencies:
'@types/node': 18.19.123 '@types/node': 18.19.124
'@types/minimatch@6.0.0': '@types/minimatch@6.0.0':
dependencies: dependencies:
@ -3214,41 +3208,41 @@ snapshots:
'@types/ms@2.1.0': {} '@types/ms@2.1.0': {}
'@types/node@18.19.123': '@types/node@18.19.124':
dependencies: dependencies:
undici-types: 5.26.5 undici-types: 5.26.5
'@types/node@22.18.0': '@types/node@22.18.1':
dependencies: dependencies:
undici-types: 6.21.0 undici-types: 6.21.0
'@types/plist@3.0.5': '@types/plist@3.0.5':
dependencies: dependencies:
'@types/node': 18.19.123 '@types/node': 18.19.124
xmlbuilder: 15.1.1 xmlbuilder: 15.1.1
optional: true optional: true
'@types/responselike@1.0.3': '@types/responselike@1.0.3':
dependencies: dependencies:
'@types/node': 18.19.123 '@types/node': 18.19.124
'@types/verror@1.10.11': '@types/verror@1.10.11':
optional: true optional: true
'@types/yauzl@2.10.3': '@types/yauzl@2.10.3':
dependencies: dependencies:
'@types/node': 18.19.123 '@types/node': 18.19.124
optional: true optional: true
'@typescript-eslint/eslint-plugin@8.41.0(@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@4.9.5))(eslint@9.34.0)(typescript@4.9.5)': '@typescript-eslint/eslint-plugin@8.42.0(@typescript-eslint/parser@8.42.0(eslint@9.35.0)(typescript@4.9.5))(eslint@9.35.0)(typescript@4.9.5)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
'@typescript-eslint/parser': 8.41.0(eslint@9.34.0)(typescript@4.9.5) '@typescript-eslint/parser': 8.42.0(eslint@9.35.0)(typescript@4.9.5)
'@typescript-eslint/scope-manager': 8.41.0 '@typescript-eslint/scope-manager': 8.42.0
'@typescript-eslint/type-utils': 8.41.0(eslint@9.34.0)(typescript@4.9.5) '@typescript-eslint/type-utils': 8.42.0(eslint@9.35.0)(typescript@4.9.5)
'@typescript-eslint/utils': 8.41.0(eslint@9.34.0)(typescript@4.9.5) '@typescript-eslint/utils': 8.42.0(eslint@9.35.0)(typescript@4.9.5)
'@typescript-eslint/visitor-keys': 8.41.0 '@typescript-eslint/visitor-keys': 8.42.0
eslint: 9.34.0 eslint: 9.35.0
graphemer: 1.4.0 graphemer: 1.4.0
ignore: 7.0.5 ignore: 7.0.5
natural-compare: 1.4.0 natural-compare: 1.4.0
@ -3257,56 +3251,56 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@8.41.0(eslint@9.34.0)(typescript@4.9.5)': '@typescript-eslint/parser@8.42.0(eslint@9.35.0)(typescript@4.9.5)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 8.41.0 '@typescript-eslint/scope-manager': 8.42.0
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
'@typescript-eslint/typescript-estree': 8.41.0(typescript@4.9.5) '@typescript-eslint/typescript-estree': 8.42.0(typescript@4.9.5)
'@typescript-eslint/visitor-keys': 8.41.0 '@typescript-eslint/visitor-keys': 8.42.0
debug: 4.4.1 debug: 4.4.1
eslint: 9.34.0 eslint: 9.35.0
typescript: 4.9.5 typescript: 4.9.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/project-service@8.41.0(typescript@4.9.5)': '@typescript-eslint/project-service@8.42.0(typescript@4.9.5)':
dependencies: dependencies:
'@typescript-eslint/tsconfig-utils': 8.41.0(typescript@4.9.5) '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@4.9.5)
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
debug: 4.4.1 debug: 4.4.1
typescript: 4.9.5 typescript: 4.9.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/scope-manager@8.41.0': '@typescript-eslint/scope-manager@8.42.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
'@typescript-eslint/visitor-keys': 8.41.0 '@typescript-eslint/visitor-keys': 8.42.0
'@typescript-eslint/tsconfig-utils@8.41.0(typescript@4.9.5)': '@typescript-eslint/tsconfig-utils@8.42.0(typescript@4.9.5)':
dependencies: dependencies:
typescript: 4.9.5 typescript: 4.9.5
'@typescript-eslint/type-utils@8.41.0(eslint@9.34.0)(typescript@4.9.5)': '@typescript-eslint/type-utils@8.42.0(eslint@9.35.0)(typescript@4.9.5)':
dependencies: dependencies:
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
'@typescript-eslint/typescript-estree': 8.41.0(typescript@4.9.5) '@typescript-eslint/typescript-estree': 8.42.0(typescript@4.9.5)
'@typescript-eslint/utils': 8.41.0(eslint@9.34.0)(typescript@4.9.5) '@typescript-eslint/utils': 8.42.0(eslint@9.35.0)(typescript@4.9.5)
debug: 4.4.1 debug: 4.4.1
eslint: 9.34.0 eslint: 9.35.0
ts-api-utils: 2.1.0(typescript@4.9.5) ts-api-utils: 2.1.0(typescript@4.9.5)
typescript: 4.9.5 typescript: 4.9.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/types@8.41.0': {} '@typescript-eslint/types@8.42.0': {}
'@typescript-eslint/typescript-estree@8.41.0(typescript@4.9.5)': '@typescript-eslint/typescript-estree@8.42.0(typescript@4.9.5)':
dependencies: dependencies:
'@typescript-eslint/project-service': 8.41.0(typescript@4.9.5) '@typescript-eslint/project-service': 8.42.0(typescript@4.9.5)
'@typescript-eslint/tsconfig-utils': 8.41.0(typescript@4.9.5) '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@4.9.5)
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
'@typescript-eslint/visitor-keys': 8.41.0 '@typescript-eslint/visitor-keys': 8.42.0
debug: 4.4.1 debug: 4.4.1
fast-glob: 3.3.3 fast-glob: 3.3.3
is-glob: 4.0.3 is-glob: 4.0.3
@ -3317,20 +3311,20 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/utils@8.41.0(eslint@9.34.0)(typescript@4.9.5)': '@typescript-eslint/utils@8.42.0(eslint@9.35.0)(typescript@4.9.5)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.34.0) '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0)
'@typescript-eslint/scope-manager': 8.41.0 '@typescript-eslint/scope-manager': 8.42.0
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
'@typescript-eslint/typescript-estree': 8.41.0(typescript@4.9.5) '@typescript-eslint/typescript-estree': 8.42.0(typescript@4.9.5)
eslint: 9.34.0 eslint: 9.35.0
typescript: 4.9.5 typescript: 4.9.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/visitor-keys@8.41.0': '@typescript-eslint/visitor-keys@8.42.0':
dependencies: dependencies:
'@typescript-eslint/types': 8.41.0 '@typescript-eslint/types': 8.42.0
eslint-visitor-keys: 4.2.1 eslint-visitor-keys: 4.2.1
'@webassemblyjs/ast@1.14.1': '@webassemblyjs/ast@1.14.1':
@ -3598,9 +3592,9 @@ snapshots:
browserslist@4.25.4: browserslist@4.25.4:
dependencies: dependencies:
caniuse-lite: 1.0.30001737 caniuse-lite: 1.0.30001741
electron-to-chromium: 1.5.211 electron-to-chromium: 1.5.214
node-releases: 2.0.19 node-releases: 2.0.20
update-browserslist-db: 1.1.3(browserslist@4.25.4) update-browserslist-db: 1.1.3(browserslist@4.25.4)
buffer-crc32@0.2.13: {} buffer-crc32@0.2.13: {}
@ -3688,7 +3682,7 @@ snapshots:
pascal-case: 3.1.2 pascal-case: 3.1.2
tslib: 2.8.1 tslib: 2.8.1
caniuse-lite@1.0.30001737: {} caniuse-lite@1.0.30001741: {}
chalk@4.1.2: chalk@4.1.2:
dependencies: dependencies:
@ -3828,7 +3822,7 @@ snapshots:
cssesc@3.0.0: {} cssesc@3.0.0: {}
dayjs@1.11.15: {} dayjs@1.11.18: {}
debounce@1.2.1: {} debounce@1.2.1: {}
@ -4001,7 +3995,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
electron-to-chromium@1.5.211: {} electron-to-chromium@1.5.214: {}
electron-winstaller@5.4.0: electron-winstaller@5.4.0:
dependencies: dependencies:
@ -4018,7 +4012,7 @@ snapshots:
electron@37.4.0: electron@37.4.0:
dependencies: dependencies:
'@electron/get': 2.0.3 '@electron/get': 2.0.3
'@types/node': 22.18.0 '@types/node': 22.18.1
extract-zip: 2.0.1 extract-zip: 2.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -4122,17 +4116,17 @@ snapshots:
eslint-visitor-keys@4.2.1: {} eslint-visitor-keys@4.2.1: {}
eslint@9.34.0: eslint@9.35.0:
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.34.0) '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0)
'@eslint-community/regexpp': 4.12.1 '@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.21.0 '@eslint/config-array': 0.21.0
'@eslint/config-helpers': 0.3.1 '@eslint/config-helpers': 0.3.1
'@eslint/core': 0.15.2 '@eslint/core': 0.15.2
'@eslint/eslintrc': 3.3.1 '@eslint/eslintrc': 3.3.1
'@eslint/js': 9.34.0 '@eslint/js': 9.35.0
'@eslint/plugin-kit': 0.3.5 '@eslint/plugin-kit': 0.3.5
'@humanfs/node': 0.16.6 '@humanfs/node': 0.16.7
'@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.3 '@humanwhocodes/retry': 0.4.3
'@types/estree': 1.0.8 '@types/estree': 1.0.8
@ -4479,7 +4473,7 @@ snapshots:
he: 1.2.0 he: 1.2.0
param-case: 3.0.4 param-case: 3.0.4
relateurl: 0.2.7 relateurl: 0.2.7
terser: 5.43.1 terser: 5.44.0
html-webpack-plugin@5.6.4(webpack@5.101.3): html-webpack-plugin@5.6.4(webpack@5.101.3):
dependencies: dependencies:
@ -4651,7 +4645,7 @@ snapshots:
jest-worker@27.5.1: jest-worker@27.5.1:
dependencies: dependencies:
'@types/node': 18.19.123 '@types/node': 18.19.124
merge-stream: 2.0.0 merge-stream: 2.0.0
supports-color: 8.1.1 supports-color: 8.1.1
@ -4882,7 +4876,7 @@ snapshots:
lower-case: 2.0.2 lower-case: 2.0.2
tslib: 2.8.1 tslib: 2.8.1
node-abi@3.75.0: node-abi@3.77.0:
dependencies: dependencies:
semver: 7.7.2 semver: 7.7.2
@ -4896,7 +4890,7 @@ snapshots:
dependencies: dependencies:
semver: 7.7.2 semver: 7.7.2
node-releases@2.0.19: {} node-releases@2.0.20: {}
nopt@6.0.0: nopt@6.0.0:
dependencies: dependencies:
@ -5206,14 +5200,14 @@ snapshots:
dependencies: dependencies:
truncate-utf8-bytes: 1.0.2 truncate-utf8-bytes: 1.0.2
sass-loader@16.0.5(sass@1.91.0)(webpack@5.101.3): sass-loader@16.0.5(sass@1.92.1)(webpack@5.101.3):
dependencies: dependencies:
neo-async: 2.6.2 neo-async: 2.6.2
optionalDependencies: optionalDependencies:
sass: 1.91.0 sass: 1.92.1
webpack: 5.101.3(webpack-cli@4.10.0) webpack: 5.101.3(webpack-cli@4.10.0)
sass@1.91.0: sass@1.92.1:
dependencies: dependencies:
chokidar: 4.0.3 chokidar: 4.0.3
immutable: 5.1.3 immutable: 5.1.3
@ -5389,7 +5383,7 @@ snapshots:
jest-worker: 27.5.1 jest-worker: 27.5.1
schema-utils: 4.3.2 schema-utils: 4.3.2
serialize-javascript: 6.0.2 serialize-javascript: 6.0.2
terser: 5.43.1 terser: 5.44.0
webpack: 5.101.3(webpack-cli@4.10.0) webpack: 5.101.3(webpack-cli@4.10.0)
terser@4.8.1: terser@4.8.1:
@ -5399,7 +5393,7 @@ snapshots:
source-map: 0.6.1 source-map: 0.6.1
source-map-support: 0.5.21 source-map-support: 0.5.21
terser@5.43.1: terser@5.44.0:
dependencies: dependencies:
'@jridgewell/source-map': 0.3.11 '@jridgewell/source-map': 0.3.11
acorn: 8.15.0 acorn: 8.15.0

View file

@ -62,7 +62,7 @@ export const pdfResize = () => {
export const genAssetHTML = (type: string, pathString: string, imgName: string, linkName: string) => { export const genAssetHTML = (type: string, pathString: string, imgName: string, linkName: string) => {
let html = ""; let html = "";
if (Constants.SIYUAN_ASSETS_AUDIO.includes(type)) { if (Constants.SIYUAN_ASSETS_AUDIO.includes(type)) {
html = `<div data-node-id="${Lute.NewNodeID()}" data-type="NodeAudio" class="iframe" updated="${dayjs().format("YYYYMMDDHHmmss")}"><div class="iframe-content"><audio controls="controls" src="${pathString}" data-src="${pathString}"></audio>${Constants.ZWSP}</div><div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`; html = `<div data-node-id="${Lute.NewNodeID()}" data-type="NodeAudio" class="iframe" updated="${dayjs().format("YYYYMMDDHHmmss")}"><div class="iframe-content"><audio controls="controls" src="${pathString}"></audio>${Constants.ZWSP}</div><div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`;
} else if (Constants.SIYUAN_ASSETS_IMAGE.includes(type)) { } else if (Constants.SIYUAN_ASSETS_IMAGE.includes(type)) {
let netHTML = ""; let netHTML = "";
if (!pathString.startsWith("assets/")) { if (!pathString.startsWith("assets/")) {
@ -70,7 +70,7 @@ export const genAssetHTML = (type: string, pathString: string, imgName: string,
} }
html = `<span contenteditable="false" data-type="img" class="img"><span> </span><span><span class="protyle-action protyle-icons"><span class="protyle-icon protyle-icon--only"><svg><use xlink:href="#iconMore"></use></svg></span></span><img src="${pathString}" data-src="${pathString}" alt="${imgName}" /><span class="protyle-action__drag"></span>${netHTML}<span class="protyle-action__title"></span></span><span> </span></span>`; html = `<span contenteditable="false" data-type="img" class="img"><span> </span><span><span class="protyle-action protyle-icons"><span class="protyle-icon protyle-icon--only"><svg><use xlink:href="#iconMore"></use></svg></span></span><img src="${pathString}" data-src="${pathString}" alt="${imgName}" /><span class="protyle-action__drag"></span>${netHTML}<span class="protyle-action__title"></span></span><span> </span></span>`;
} else if (Constants.SIYUAN_ASSETS_VIDEO.includes(type)) { } else if (Constants.SIYUAN_ASSETS_VIDEO.includes(type)) {
html = `<div data-node-id="${Lute.NewNodeID()}" data-type="NodeVideo" class="iframe" updated="${dayjs().format("YYYYMMDDHHmmss")}"><div class="iframe-content">${Constants.ZWSP}<video controls="controls" src="${pathString}" data-src="${pathString}"></video><span class="protyle-action__drag" contenteditable="false"></span></div><div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`; html = `<div data-node-id="${Lute.NewNodeID()}" data-type="NodeVideo" class="iframe" updated="${dayjs().format("YYYYMMDDHHmmss")}"><div class="iframe-content">${Constants.ZWSP}<video controls="controls" src="${pathString}"></video><span class="protyle-action__drag" contenteditable="false"></span></div><div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`;
} else { } else {
html = `<span data-type="a" data-href="${pathString}">${linkName}</span>`; html = `<span data-type="a" data-href="${pathString}">${linkName}</span>`;
} }

View file

@ -67,10 +67,14 @@ export const viewCards = (app: App, deckID: string, title: string, deckType: "Tr
if (response.data.blocks.length > 0) { if (response.data.blocks.length > 0) {
edit = new Protyle(app, dialog.element.querySelector("#cardPreview") as HTMLElement, { edit = new Protyle(app, dialog.element.querySelector("#cardPreview") as HTMLElement, {
blockId: "", blockId: "",
action: [Constants.CB_GET_ALL],
render: { render: {
gutter: true, gutter: true,
breadcrumbDocName: true breadcrumbDocName: true,
title: true,
hideTitleOnZoom: true,
}, },
typewriterMode: false
}); });
if (window.siyuan.mobile) { if (window.siyuan.mobile) {
window.siyuan.mobile.popEditor = edit; window.siyuan.mobile.popEditor = edit;
@ -310,6 +314,10 @@ const getArticle = (edit: Protyle, id: string) => {
data: getResponse, data: getResponse,
protyle: edit.protyle, protyle: edit.protyle,
action: getResponse.data.rootID === getResponse.data.id ? [Constants.CB_GET_HTML] : [Constants.CB_GET_ALL, Constants.CB_GET_HTML], action: getResponse.data.rootID === getResponse.data.id ? [Constants.CB_GET_HTML] : [Constants.CB_GET_ALL, Constants.CB_GET_HTML],
afterCB() {
edit.protyle.title.element.removeAttribute("data-render");
edit.protyle.title.render(edit.protyle, response);
}
}); });
}); });
}); });

View file

@ -6,7 +6,6 @@ import {processSync} from "../dialog/processSystem";
import {getCloudURL} from "./util/about"; import {getCloudURL} from "./util/about";
import {openByMobile} from "../protyle/util/compatibility"; import {openByMobile} from "../protyle/util/compatibility";
import {confirmDialog} from "../dialog/confirmDialog"; import {confirmDialog} from "../dialog/confirmDialog";
import {isKernelInMobile} from "../util/functions";
const renderProvider = (provider: number) => { const renderProvider = (provider: number) => {
if (provider === 0) { if (provider === 0) {
@ -41,7 +40,13 @@ const renderProvider = (provider: number) => {
</div>`; </div>`;
} }
if (!isPaidUser()) { if (!isPaidUser()) {
return `<div class="b3-label b3-label--inner">${window.siyuan.languages["_kernel"][214].replaceAll("${accountServer}", getCloudURL(""))}</div>`; return `<div>
${window.siyuan.languages["_kernel"][214].replaceAll("${accountServer}", getCloudURL(""))}
</div>
<div class="ft__error${provider == 4 ? "" : " fn__none"}">
<div class="fn__hr--b"></div>
${window.siyuan.languages.mobileNotSupport}
</div>`;
} }
if (provider === 2) { if (provider === 2) {
return `<div class="b3-label b3-label--inner"> return `<div class="b3-label b3-label--inner">
@ -180,16 +185,11 @@ const renderProvider = (provider: number) => {
</button> </button>
</div>`; </div>`;
} else if (provider === 4) { } else if (provider === 4) {
if (isKernelInMobile()) {
return `<div class="b3-label b3-label--inner">
${window.siyuan.languages.syncThirdPartyProviderLocalIntro}
<div class="fn__hr"></div>
<em>${window.siyuan.languages.proFeature}</em>
<div class="fn__hr"></div>
${window.siyuan.languages.deviceNotSupport}
</div>`;
}
return `<div class="b3-label b3-label--inner"> return `<div class="b3-label b3-label--inner">
<div class="ft__error">
${window.siyuan.languages.mobileNotSupport}
</div>
<div class="fn__hr"></div>
${window.siyuan.languages.syncThirdPartyProviderLocalIntro} ${window.siyuan.languages.syncThirdPartyProviderLocalIntro}
<div class="fn__hr"></div> <div class="fn__hr"></div>
<em>${window.siyuan.languages.proFeature}</em> <em>${window.siyuan.languages.proFeature}</em>

View file

@ -62,33 +62,31 @@ export const openSnippets = () => {
<div class="fn__flex-1" style="overflow:auto;padding: 16px 24px"> <div class="fn__flex-1" style="overflow:auto;padding: 16px 24px">
<div> <div>
<div class="fn__flex"> <div class="fn__flex">
<div class="fn__flex-1"></div> <div class="b3-form__icon fn__flex-1">
<div class="b3-form__icon">
<svg class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg> <svg class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg>
<input data-type="css" data-action="search" type="text" placeholder="${window.siyuan.languages.search}" class="b3-text-field b3-form__icon-input"> <input data-type="css" data-action="search" type="text" placeholder="${window.siyuan.languages.search}" class="b3-text-field b3-form__icon-input fn__block">
</div> </div>
<div class="fn__space"></div> <div class="fn__space"></div>
<span aria-label="${window.siyuan.languages.addAttr} CSS" id="addCodeSnippetCSS" class="b3-tooltips b3-tooltips__sw block__icon block__icon--show"> <span aria-label="${window.siyuan.languages.addAttr} CSS" id="addCodeSnippetCSS" class="b3-tooltips b3-tooltips__sw block__icon block__icon--show">
<svg><use xlink:href="#iconAdd"></use></svg> <svg><use xlink:href="#iconAdd"></use></svg>
</span> </span>
<div class="fn__space"></div> <div class="fn__space"></div>
<input data-action="toggleCSS" class="b3-switch b3-switch--side fn__flex-center" type="checkbox"${window.siyuan.config.snippet.enabledCSS ? " checked" : ""}> <input data-action="toggleCSS" class="b3-switch fn__flex-center" type="checkbox"${window.siyuan.config.snippet.enabledCSS ? " checked" : ""}>
</div> </div>
${cssHTML} ${cssHTML}
</div> </div>
<div class="fn__none"> <div class="fn__none">
<div class="fn__flex"> <div class="fn__flex">
<div class="fn__flex-1"></div> <div class="b3-form__icon fn__flex-1">
<div class="b3-form__icon">
<svg class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg> <svg class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg>
<input data-type="js" data-action="search" type="text" placeholder="${window.siyuan.languages.search}" class="b3-text-field b3-form__icon-input"> <input data-type="js" data-action="search" type="text" placeholder="${window.siyuan.languages.search}" class="b3-text-field b3-form__icon-input fn__block">
</div> </div>
<div class="fn__space"></div> <div class="fn__space"></div>
<span aria-label="${window.siyuan.languages.addAttr} JS" id="addCodeSnippetJS" class="b3-tooltips b3-tooltips__sw block__icon block__icon--show"> <span aria-label="${window.siyuan.languages.addAttr} JS" id="addCodeSnippetJS" class="b3-tooltips b3-tooltips__sw block__icon block__icon--show">
<svg><use xlink:href="#iconAdd"></use></svg> <svg><use xlink:href="#iconAdd"></use></svg>
</span> </span>
<div class="fn__space"></div> <div class="fn__space"></div>
<input data-action="toggleJS" class="b3-switch b3-switch--side fn__flex-center" type="checkbox"${window.siyuan.config.snippet.enabledJS ? " checked" : ""}> <input data-action="toggleJS" class="b3-switch fn__flex-center" type="checkbox"${window.siyuan.config.snippet.enabledJS ? " checked" : ""}>
</div> </div>
${jsHTML} ${jsHTML}
</div> </div>
@ -120,7 +118,8 @@ export const openSnippets = () => {
type: target.id === "addCodeSnippetCSS" ? "css" : "js", type: target.id === "addCodeSnippetCSS" ? "css" : "js",
name: "", name: "",
content: "", content: "",
enabled: false enabled: false,
disabledInPublish: false,
})); }));
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
@ -195,13 +194,19 @@ const genSnippet = (options: ISnippet) => {
<div class="fn__hr--b"></div> <div class="fn__hr--b"></div>
<div class="fn__flex"> <div class="fn__flex">
<input type="text" class="fn__size200 b3-text-field" placeholder="${window.siyuan.languages.title}"> <input type="text" class="fn__size200 b3-text-field" placeholder="${window.siyuan.languages.title}">
<div class="fn__space"></div>
<label class="fn__flex${window.siyuan.config.publish.enable ? "" : " fn__none"}">
<input data-type="disabledInPublish" type="checkbox" class="b3-switch fn__flex-center" ${options.disabledInPublish ? "" : " checked"}>
<div class="fn__space"></div>
<span class="fn__flex-center">${window.siyuan.languages.publishService}</span>
</label>
<div class="fn__flex-1"></div> <div class="fn__flex-1"></div>
<div class="fn__space"></div> <div class="fn__space"></div>
<span aria-label="${window.siyuan.languages.remove}" data-action="remove" class="b3-tooltips b3-tooltips__sw block__icon block__icon--show"> <span aria-label="${window.siyuan.languages.remove}" data-action="remove" class="b3-tooltips b3-tooltips__sw block__icon block__icon--show">
<svg><use xlink:href="#iconTrashcan"></use></svg> <svg><use xlink:href="#iconTrashcan"></use></svg>
</span> </span>
<div class="fn__space"></div> <div class="fn__space"></div>
<input data-type="snippet" class="b3-switch b3-switch--side fn__flex-center" type="checkbox"${options.enabled ? " checked" : ""}> <input data-type="snippet" class="b3-switch fn__flex-center" type="checkbox"${options.enabled ? " checked" : ""}>
</div> </div>
<div class="fn__hr"></div> <div class="fn__hr"></div>
<textarea class="fn__block b3-text-field" placeholder="${window.siyuan.languages.codeSnippet}" style="resize: vertical;font-family:var(--b3-font-family-code)" spellcheck="false"></textarea> <textarea class="fn__block b3-text-field" placeholder="${window.siyuan.languages.codeSnippet}" style="resize: vertical;font-family:var(--b3-font-family-code)" spellcheck="false"></textarea>
@ -229,11 +234,12 @@ const setSnippet = (dialog: Dialog, oldSnippets: ISnippet[], removeIds: string[]
const snippets: ISnippet[] = []; const snippets: ISnippet[] = [];
dialog.element.querySelectorAll("[data-id]").forEach((item) => { dialog.element.querySelectorAll("[data-id]").forEach((item) => {
snippets.push({ snippets.push({
disabledInPublish: !(item.querySelector('.b3-switch[data-type="disabledInPublish"]') as HTMLInputElement).checked,
id: item.getAttribute("data-id"), id: item.getAttribute("data-id"),
name: item.querySelector("input").value, name: item.querySelector("input").value,
type: item.getAttribute("data-type"), type: item.getAttribute("data-type"),
content: item.querySelector("textarea").value, content: item.querySelector("textarea").value,
enabled: (item.querySelector(".b3-switch") as HTMLInputElement).checked enabled: (item.querySelector('.b3-switch[data-type="snippet"]') as HTMLInputElement).checked
}); });
}); });
if (objEquals(oldSnippets, snippets) && if (objEquals(oldSnippets, snippets) &&

View file

@ -335,7 +335,7 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
<span class="fn__space--small"></span> <span class="fn__space--small"></span>
<input type="date" max="9999-12-31" class="b3-text-field fn__flex-1" value="${dynamicCurrentObj.date}"/> <input type="date" max="9999-12-31" class="b3-text-field fn__flex-1" value="${dynamicCurrentObj.date}"/>
<span class="fn__space--small"></span> <span class="fn__space--small"></span>
<span class="ariaLabel block__icon block__icon--show" aria-label="${window.siyuan.languages.dynamicIconDateEmptyInfo}"><svg><use xlink:href="#iconInfo"></use></svg></span> <span data-action="clearDate" class="ariaLabel block__icon block__icon--show" aria-label="${window.siyuan.languages.dynamicIconDateEmptyInfo}"><svg><use xlink:href="#iconTrashcan"></use></svg></span>
<span class="fn__space"></span> <span class="fn__space"></span>
</div> </div>
<div class="fn__hr"></div> <div class="fn__hr"></div>
@ -630,6 +630,10 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
dynamicTextElements[0].value = target.getAttribute("style").replace("background-color:", ""); dynamicTextElements[0].value = target.getAttribute("style").replace("background-color:", "");
dynamicTextElements[0].dispatchEvent(new CustomEvent("input")); dynamicTextElements[0].dispatchEvent(new CustomEvent("input"));
break; break;
} else if ("clearDate" === target.dataset.action) {
dynamicDateElement.value = "";
dynamicDateElement.dispatchEvent(new CustomEvent("change"));
break;
} }
target = target.parentElement; target = target.parentElement;
} }

View file

@ -866,7 +866,7 @@ data-type="navigation-root" data-path="/">
} }
window.siyuan.storage[Constants.LOCAL_FILESPATHS].forEach((item: IFilesPath) => { window.siyuan.storage[Constants.LOCAL_FILESPATHS].forEach((item: IFilesPath) => {
item.openPaths.forEach((openPath) => { item.openPaths.forEach((openPath) => {
this.selectItem(item.notebookId, openPath, undefined, false); this.selectItem(item.notebookId, openPath, undefined, false, false);
}); });
}); });
if (!init) { if (!init) {
@ -1081,7 +1081,11 @@ data-type="navigation-root" data-path="/">
}, 2); }, 2);
} }
private onLsSelect(data: { files: IFile[], box: string, path: string }, filePath: string, setStorage: boolean) { private async onLsSelect(data: {
files: IFile[],
box: string,
path: string
}, filePath: string, setStorage: boolean, isSetCurrent: boolean) {
let fileHTML = ""; let fileHTML = "";
data.files.forEach((item: IFile) => { data.files.forEach((item: IFile) => {
fileHTML += this.genFileHTML(item); fileHTML += this.genFileHTML(item);
@ -1102,28 +1106,30 @@ data-type="navigation-root" data-path="/">
emojiElement.textContent = unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].folder); emojiElement.textContent = unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].folder);
} }
liElement.insertAdjacentHTML("afterend", `<ul>${fileHTML}</ul>`); liElement.insertAdjacentHTML("afterend", `<ul>${fileHTML}</ul>`);
data.files.forEach((item: IFile) => { let newLiElement;
for (let i = 0; i < data.files.length; i++) {
const item = data.files[i];
if (filePath === item.path) { if (filePath === item.path) {
this.selectItem(data.box, filePath, undefined, setStorage); newLiElement = await this.selectItem(data.box, filePath, undefined, setStorage, isSetCurrent);
} else if (filePath.startsWith(item.path.replace(".sy", ""))) { } else if (filePath.startsWith(item.path.replace(".sy", ""))) {
fetchPost("/api/filetree/listDocsByPath", { const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: data.box, notebook: data.box,
path: item.path path: item.path
}, response => {
this.selectItem(response.data.box, filePath, response.data, setStorage);
}); });
newLiElement = await this.selectItem(response.data.box, filePath, response.data, setStorage, isSetCurrent);
} }
});
if (setStorage) {
this.setCurrent(this.element.querySelector(`ul[data-url="${data.box}"] li[data-path="${filePath}"]`));
} }
if (isSetCurrent) {
this.setCurrent(newLiElement);
}
return newLiElement;
} }
private setCurrent(target: HTMLElement, isScroll = true) { public setCurrent(target: HTMLElement, isScroll = true) {
if (!target) { if (!target) {
return; return;
} }
this.element.querySelectorAll("li").forEach((liItem) => { this.element.querySelectorAll("li.b3-list-item--focus").forEach((liItem) => {
liItem.classList.remove("b3-list-item--focus"); liItem.classList.remove("b3-list-item--focus");
}); });
target.classList.add("b3-list-item--focus"); target.classList.add("b3-list-item--focus");
@ -1147,7 +1153,13 @@ data-type="navigation-root" data-path="/">
path: liElement.getAttribute("data-path"), path: liElement.getAttribute("data-path"),
}, response => { }, response => {
if (response.data.path === "/" && response.data.files.length === 0) { if (response.data.path === "/" && response.data.files.length === 0) {
showMessage(window.siyuan.languages.emptyContent); newFile({
app: this.app,
notebookId,
currentPath: "/",
useSavePath: false,
listDocTree: true,
});
return; return;
} }
this.onLsHTML(response.data); this.onLsHTML(response.data);
@ -1155,11 +1167,11 @@ data-type="navigation-root" data-path="/">
}); });
} }
public selectItem(notebookId: string, filePath: string, data?: { public async selectItem(notebookId: string, filePath: string, data?: {
files: IFile[], files: IFile[],
box: string, box: string,
path: string path: string
}, setStorage = true) { }, setStorage = true, isSetCurrent = true) {
const treeElement = this.element.querySelector(`[data-url="${notebookId}"]`); const treeElement = this.element.querySelector(`[data-url="${notebookId}"]`);
if (!treeElement) { if (!treeElement) {
// 有文件树和编辑器的布局初始化时,文件树还未挂载 // 有文件树和编辑器的布局初始化时,文件树还未挂载
@ -1181,24 +1193,24 @@ data-type="navigation-root" data-path="/">
if (liElement.getAttribute("data-path") === filePath) { if (liElement.getAttribute("data-path") === filePath) {
if (setStorage) { if (setStorage) {
this.setCurrent(liElement);
this.getOpenPaths(); this.getOpenPaths();
} else {
this.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
} }
return; if (isSetCurrent) {
this.setCurrent(liElement);
}
return liElement;
} }
if (data && data.path === currentPath) { if (data && data.path === currentPath) {
this.onLsSelect(data, filePath, setStorage); liElement = await this.onLsSelect(data, filePath, setStorage, isSetCurrent);
} else { } else {
fetchPost("/api/filetree/listDocsByPath", { const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: notebookId, notebook: notebookId,
path: currentPath path: currentPath
}, response => {
this.onLsSelect(response.data, filePath, setStorage);
}); });
liElement = await this.onLsSelect(response.data, filePath, setStorage, isSetCurrent);
} }
return liElement;
} }
private getOpenPaths() { private getOpenPaths() {

View file

@ -4,8 +4,7 @@ import {Model} from "../../layout/Model";
import {Constants} from "../../constants"; import {Constants} from "../../constants";
import {getDisplayName, pathPosix, setNoteBook} from "../../util/pathName"; import {getDisplayName, pathPosix, setNoteBook} from "../../util/pathName";
import {initFileMenu, initNavigationMenu, sortMenu} from "../../menus/navigation"; import {initFileMenu, initNavigationMenu, sortMenu} from "../../menus/navigation";
import {showMessage} from "../../dialog/message"; import {fetchPost, fetchSyncPost} from "../../util/fetch";
import {fetchPost} from "../../util/fetch";
import {genUUID} from "../../util/genID"; import {genUUID} from "../../util/genID";
import {openMobileFileById} from "../editor"; import {openMobileFileById} from "../editor";
import {unicode2Emoji} from "../../emoji"; import {unicode2Emoji} from "../../emoji";
@ -361,7 +360,7 @@ export class MobileFiles extends Model {
} }
window.siyuan.storage[Constants.LOCAL_FILESPATHS].forEach((item: IFilesPath) => { window.siyuan.storage[Constants.LOCAL_FILESPATHS].forEach((item: IFilesPath) => {
item.openPaths.forEach((openPath) => { item.openPaths.forEach((openPath) => {
this.selectItem(item.notebookId, openPath, undefined, false); this.selectItem(item.notebookId, openPath, undefined, false, false);
}); });
}); });
if (!init) { if (!init) {
@ -577,20 +576,14 @@ export class MobileFiles extends Model {
}, 2); }, 2);
} }
private onLsSelect(data: { files: IFile[], box: string, path: string }, filePath: string, setStorage: boolean) { private async onLsSelect(data: {
files: IFile[],
box: string,
path: string
}, filePath: string, setStorage: boolean, isSetCurrent: boolean) {
let fileHTML = ""; let fileHTML = "";
data.files.forEach((item: IFile) => { data.files.forEach((item: IFile) => {
fileHTML += this.genFileHTML(item); fileHTML += this.genFileHTML(item);
if (filePath === item.path) {
this.selectItem(data.box, filePath, undefined, setStorage);
} else if (filePath.startsWith(item.path.replace(".sy", ""))) {
fetchPost("/api/filetree/listDocsByPath", {
notebook: data.box,
path: item.path
}, response => {
this.selectItem(response.data.box, filePath, response.data, setStorage);
});
}
}); });
if (fileHTML === "") { if (fileHTML === "") {
return; return;
@ -600,26 +593,45 @@ export class MobileFiles extends Model {
// 文件展开时,刷新 // 文件展开时,刷新
liElement.nextElementSibling.remove(); liElement.nextElementSibling.remove();
} }
liElement.querySelector(".b3-list-item__arrow").classList.add("b3-list-item__arrow--open"); const arrowElement = liElement.querySelector(".b3-list-item__arrow");
liElement.insertAdjacentHTML("afterend", `<ul>${fileHTML}</ul>`); arrowElement.classList.add("b3-list-item__arrow--open");
if (setStorage) { arrowElement.parentElement.classList.remove("fn__hidden");
this.setCurrent(this.element.querySelector(`ul[data-url="${data.box}"] li[data-path="${filePath}"]`)); const emojiElement = liElement.querySelector(".b3-list-item__icon");
if (emojiElement.textContent === unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].file)) {
emojiElement.textContent = unicode2Emoji(window.siyuan.storage[Constants.LOCAL_IMAGES].folder);
} }
liElement.insertAdjacentHTML("afterend", `<ul>${fileHTML}</ul>`);
let newLiElement;
for (let i = 0; i < data.files.length; i++) {
const item = data.files[i];
if (filePath === item.path) {
newLiElement = await this.selectItem(data.box, filePath, undefined, setStorage, isSetCurrent);
} else if (filePath.startsWith(item.path.replace(".sy", ""))) {
const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: data.box,
path: item.path
});
newLiElement = await this.selectItem(response.data.box, filePath, response.data, setStorage, isSetCurrent);
}
}
if (isSetCurrent) {
this.setCurrent(newLiElement);
}
return newLiElement;
} }
private setCurrent(target: HTMLElement) { public setCurrent(target: HTMLElement, isScroll = true) {
if (!target) { if (!target) {
return; return;
} }
this.element.querySelectorAll("li").forEach((liItem) => { this.element.querySelectorAll("li.b3-list-item--focus").forEach((liItem) => {
liItem.classList.remove("b3-list-item--focus"); liItem.classList.remove("b3-list-item--focus");
}); });
target.classList.add("b3-list-item--focus"); target.classList.add("b3-list-item--focus");
const titleHeight = this.actionsElement.clientHeight;
if (target.offsetTop - titleHeight < this.element.scrollTop) { if (isScroll) {
this.element.scrollTop = target.offsetTop - titleHeight; const elementRect = this.element.getBoundingClientRect();
} else if (target.offsetTop - this.element.clientHeight - titleHeight + target.clientHeight > this.element.scrollTop) { this.element.scrollTop = this.element.scrollTop + (target.getBoundingClientRect().top - (elementRect.top + elementRect.height / 2));
this.element.scrollTop = target.offsetTop - this.element.clientHeight - titleHeight + target.clientHeight;
} }
} }
@ -636,7 +648,13 @@ export class MobileFiles extends Model {
path: liElement.getAttribute("data-path"), path: liElement.getAttribute("data-path"),
}, response => { }, response => {
if (response.data.path === "/" && response.data.files.length === 0) { if (response.data.path === "/" && response.data.files.length === 0) {
showMessage(window.siyuan.languages.emptyContent); newFile({
app: this.app,
notebookId,
currentPath: "/",
useSavePath: false,
listDocTree: true,
});
return; return;
} }
this.onLsHTML(response.data); this.onLsHTML(response.data);
@ -644,11 +662,11 @@ export class MobileFiles extends Model {
}); });
} }
public selectItem(notebookId: string, filePath: string, data?: { public async selectItem(notebookId: string, filePath: string, data?: {
files: IFile[], files: IFile[],
box: string, box: string,
path: string path: string
}, setStorage = true) { }, setStorage = true, isSetCurrent = true) {
const treeElement = this.element.querySelector(`[data-url="${notebookId}"]`); const treeElement = this.element.querySelector(`[data-url="${notebookId}"]`);
if (!treeElement) { if (!treeElement) {
// 有文件树和编辑器的布局初始化时,文件树还未挂载 // 有文件树和编辑器的布局初始化时,文件树还未挂载
@ -670,24 +688,24 @@ export class MobileFiles extends Model {
if (liElement.getAttribute("data-path") === filePath) { if (liElement.getAttribute("data-path") === filePath) {
if (setStorage) { if (setStorage) {
this.setCurrent(liElement);
this.getOpenPaths(); this.getOpenPaths();
} else {
this.element.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
} }
return; if (isSetCurrent) {
this.setCurrent(liElement);
}
return liElement;
} }
if (data && data.path === currentPath) { if (data && data.path === currentPath) {
this.onLsSelect(data, filePath, setStorage); liElement = await this.onLsSelect(data, filePath, setStorage, isSetCurrent);
} else { } else {
fetchPost("/api/filetree/listDocsByPath", { const response = await fetchSyncPost("/api/filetree/listDocsByPath", {
notebook: notebookId, notebook: notebookId,
path: currentPath path: currentPath
}, response => {
this.onLsSelect(response.data, filePath, setStorage);
}); });
liElement = await this.onLsSelect(response.data, filePath, setStorage, isSetCurrent);
} }
return liElement;
} }
private getOpenPaths() { private getOpenPaths() {

View file

@ -59,6 +59,7 @@ export const openMobileFileById = (app: App, id: string, action: TProtyleAction[
render: { render: {
scroll: true, scroll: true,
title: true, title: true,
titleShowTop: true,
background: true, background: true,
gutter: true, gutter: true,
}, },

View file

@ -30,6 +30,7 @@ import {globalCommand} from "../boot/globalEvent/command/global";
import {exportLayout} from "../layout/util"; import {exportLayout} from "../layout/util";
import {saveScroll} from "../protyle/scroll/saveScroll"; import {saveScroll} from "../protyle/scroll/saveScroll";
import {hasClosestByClassName} from "../protyle/util/hasClosest"; import {hasClosestByClassName} from "../protyle/util/hasClosest";
import {Files} from "../layout/dock/Files";
let openTab; let openTab;
let openWindow; let openWindow;
@ -235,19 +236,72 @@ const getActiveEditor = (wndActive = true) => {
if (!editor && !wndActive) { if (!editor && !wndActive) {
let activeTime = 0; let activeTime = 0;
allEditor.forEach(item => { allEditor.forEach(item => {
const headerElement = item.protyle?.model.parent.headElement; let headerElement = item.protyle.model?.parent.headElement;
if (headerElement && headerElement.classList.contains("item--focus") && parseInt(headerElement.dataset.activetime) > activeTime) { if (!headerElement && item.protyle.element.getBoundingClientRect().height > 0) {
activeTime = parseInt(headerElement.dataset.activetime); const tabBodyElement = item.protyle.element.closest(".fn__flex-1[data-id]");
if (tabBodyElement) {
headerElement = document.querySelector(`.layout-tab-bar .item[data-id="${tabBodyElement.getAttribute("data-id")}"]`);
}
}
if (headerElement) {
if (headerElement.classList.contains("item--focus") && parseInt(headerElement.dataset.activetime) > activeTime) {
activeTime = parseInt(headerElement.dataset.activetime);
editor = item;
}
} else if (item.protyle.element.getBoundingClientRect().height > 0) {
editor = item; editor = item;
} }
}); });
} }
/// #else /// #else
editor = window.siyuan.mobile.popEditor || window.siyuan.mobile.editor; editor = window.siyuan.mobile.popEditor || window.siyuan.mobile.editor;
if (editor?.protyle.element.classList.contains("fn__none")) {
return undefined;
}
/// #endif /// #endif
return editor; return editor;
}; };
export const expandDocTree = async (options: {
id: string,
isSetCurrent?: boolean
}) => {
let isNotebook = false;
window.siyuan.notebooks.find(item => {
if (options.id === item.id) {
isNotebook = true;
return true;
}
});
let liElement: HTMLElement;
let notebookId = options.id;
const file = getModelByDockType("file") as Files;
if (typeof options.isSetCurrent === "undefined") {
options.isSetCurrent = true;
}
if (isNotebook) {
liElement = file.element.querySelector(`.b3-list[data-url="${options.id}"]`)?.firstElementChild as HTMLElement;
} else {
const response = await fetchSyncPost("api/block/getBlockInfo", {id: options.id});
if (response.code === -1) {
return;
}
notebookId = response.data.box;
liElement = await file.selectItem(response.data.box, response.data.path, undefined, undefined, options.isSetCurrent);
}
if (!liElement) {
return;
}
if (options.isSetCurrent || typeof options.isSetCurrent === "undefined") {
file.setCurrent(liElement);
}
const toggleElement = liElement.querySelector(".b3-list-item__arrow");
if (toggleElement.classList.contains("b3-list-item__arrow--open")) {
return;
}
file.getLeaf(liElement, notebookId);
};
export const API = { export const API = {
adaptHotkey: updateHotkeyTip, adaptHotkey: updateHotkeyTip,
confirm: confirmDialog, confirm: confirmDialog,
@ -281,4 +335,5 @@ export const API = {
openAttributePanel, openAttributePanel,
saveLayout, saveLayout,
globalCommand, globalCommand,
expandDocTree
}; };

View file

@ -18,7 +18,7 @@ export const openTopBarMenu = (app: App, target?: Element) => {
openSetting(app).element.querySelector('.b3-tab-bar [data-name="bazaar"]').dispatchEvent(new CustomEvent("click")); openSetting(app).element.querySelector('.b3-tab-bar [data-name="bazaar"]').dispatchEvent(new CustomEvent("click"));
} }
}); });
menu.addSeparator({id: "separator_1"}, isHuawei() || window.siyuan.config.readonly); menu.addSeparator({id: "separator_1", ignore: isHuawei() || window.siyuan.config.readonly});
/// #endif /// #endif
let hasPlugin = false; let hasPlugin = false;
app.plugins.forEach((plugin) => { app.plugins.forEach((plugin) => {

View file

@ -1682,7 +1682,7 @@ export class Gutter {
icon: "iconCopy", icon: "iconCopy",
label: `${window.siyuan.languages.copy} ${window.siyuan.languages.headings1}`, label: `${window.siyuan.languages.copy} ${window.siyuan.languages.headings1}`,
click() { click() {
fetchPost("/api/block/getHeadingChildrenDOM", {id}, (response) => { fetchPost("/api/block/getHeadingChildrenDOM", {id, removeFoldAttr: true}, (response) => {
if (isInAndroid()) { if (isInAndroid()) {
window.JSAndroid.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP); window.JSAndroid.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP);
} else if (isInHarmony()) { } else if (isInHarmony()) {
@ -1698,7 +1698,7 @@ export class Gutter {
icon: "iconCut", icon: "iconCut",
label: `${window.siyuan.languages.cut} ${window.siyuan.languages.headings1}`, label: `${window.siyuan.languages.cut} ${window.siyuan.languages.headings1}`,
click() { click() {
fetchPost("/api/block/getHeadingChildrenDOM", {id}, (response) => { fetchPost("/api/block/getHeadingChildrenDOM", {id, removeFoldAttr: true}, (response) => {
if (isInAndroid()) { if (isInAndroid()) {
window.JSAndroid.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP); window.JSAndroid.writeHTMLClipboard(protyle.lute.BlockDOM2StdMd(response.data).trimEnd(), response.data + Constants.ZWSP);
} else if (isInHarmony()) { } else if (isInHarmony()) {

View file

@ -14,7 +14,9 @@ import {Constants} from "../../constants";
import {matchHotKey} from "../util/hotKey"; import {matchHotKey} from "../util/hotKey";
import {isMac, readText} from "../util/compatibility"; import {isMac, readText} from "../util/compatibility";
import * as dayjs from "dayjs"; import * as dayjs from "dayjs";
/// #if !MOBILE
import {openFileById} from "../../editor/util"; import {openFileById} from "../../editor/util";
/// #endif
import {setTitle} from "../../dialog/processSystem"; import {setTitle} from "../../dialog/processSystem";
import {getContenteditableElement, getNoContainerElement} from "../wysiwyg/getBlock"; import {getContenteditableElement, getNoContainerElement} from "../wysiwyg/getBlock";
import {commonHotkey} from "../wysiwyg/commonHotkey"; import {commonHotkey} from "../wysiwyg/commonHotkey";
@ -38,232 +40,68 @@ export class Title {
if (window.siyuan.config.editor.displayBookmarkIcon) { if (window.siyuan.config.editor.displayBookmarkIcon) {
this.element.classList.add("protyle-wysiwyg--attr"); this.element.classList.add("protyle-wysiwyg--attr");
} }
/// #if !MOBILE if (protyle.options.render?.titleShowTop) {
// 标题内需要一个空格,避免首次加载出现`请输入文档名`干扰 this.element.innerHTML = '<div class="protyle-attr"></div>';
this.element.innerHTML = `<span aria-label="${isMac() ? window.siyuan.languages.gutterTip2 : window.siyuan.languages.gutterTip2.replace("⇧", "Shift+")}" data-position="west" class="protyle-title__icon ariaLabel"><svg><use xlink:href="#iconFile"></use></svg></span> } else {
// 标题内需要一个空格,避免首次加载出现`请输入文档名`干扰
this.element.innerHTML = `<span aria-label="${isMac() ? window.siyuan.languages.gutterTip2 : window.siyuan.languages.gutterTip2.replace("⇧", "Shift+")}" data-position="west" class="protyle-title__icon ariaLabel"><svg><use xlink:href="#iconFile"></use></svg></span>
<div contenteditable="true" spellcheck="${window.siyuan.config.editor.spellcheck}" class="protyle-title__input" data-tip="${window.siyuan.languages._kernel[16]}"> </div><div class="protyle-attr"></div>`; <div contenteditable="true" spellcheck="${window.siyuan.config.editor.spellcheck}" class="protyle-title__input" data-tip="${window.siyuan.languages._kernel[16]}"> </div><div class="protyle-attr"></div>`;
this.editElement = this.element.querySelector(".protyle-title__input"); this.editElement = this.element.querySelector(".protyle-title__input");
this.editElement.addEventListener("paste", (event: ClipboardEvent) => { this.editElement.addEventListener("paste", (event: ClipboardEvent) => {
event.stopPropagation();
event.preventDefault();
// 不能使用 range.insertNode否则无法撤销
let text = event.clipboardData.getData("text/siyuan");
if (text) {
try {
JSON.parse(text);
text = event.clipboardData.getData("text/plain");
} catch (e) {
// 不为数据库,保持 text 不变
}
text = protyle.lute.BlockDOM2Content(text);
} else {
text = event.clipboardData.getData("text/plain");
}
// 阻止右键复制菜单报错
setTimeout(function () {
document.execCommand("insertText", false, replaceFileName(text));
}, 0);
this.rename(protyle);
});
this.editElement.addEventListener("click", () => {
protyle.toolbar?.element.classList.add("fn__none");
});
this.editElement.addEventListener("input", (event: InputEvent) => {
if (event.isComposing) {
return;
}
if (this.editElement.textContent === "") {
this.editElement.querySelectorAll("br").forEach(item => {
item.remove();
});
}
this.rename(protyle);
});
this.editElement.addEventListener("compositionend", () => {
this.rename(protyle);
});
this.editElement.addEventListener("drop", (event: DragEvent) => {
// https://ld246.com/article/1661911210429
event.stopPropagation();
event.preventDefault();
});
this.editElement.addEventListener("keydown", (event: KeyboardEvent) => {
if (event.isComposing) {
return;
}
if (commonHotkey(protyle, event)) {
return true;
}
if (matchHotKey("⇧⌘V", event)) {
navigator.clipboard.readText().then(textPlain => {
// 对 HTML 标签进行内部转义,避免被 Lute 解析以后变为小写 https://github.com/siyuan-note/siyuan/issues/10620
textPlain = textPlain.replace(/</g, ";;;lt;;;").replace(/>/g, ";;;gt;;;");
enableLuteMarkdownSyntax(protyle);
let content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
restoreLuteMarkdownSyntax(protyle);
// 移除 ;;;lt;;; 和 ;;;gt;;; 转义及其包裹的内容
content = content.replace(/;;;lt;;;[^;]+;;;gt;;;/g, "");
document.execCommand("insertText", false, replaceFileName(content));
this.rename(protyle);
});
event.preventDefault();
event.stopPropagation(); event.stopPropagation();
} event.preventDefault();
if (matchHotKey(window.siyuan.config.keymap.general.enterBack.custom, event)) { // 不能使用 range.insertNode否则无法撤销
const ids = protyle.path.split("/"); let text = event.clipboardData.getData("text/siyuan");
if (ids.length > 2) { if (text) {
openFileById({ try {
app: protyle.app, JSON.parse(text);
id: ids[ids.length - 2], text = event.clipboardData.getData("text/plain");
action: [Constants.CB_GET_FOCUS, Constants.CB_GET_SCROLL] } catch (e) {
// 不为数据库,保持 text 不变
}
text = protyle.lute.BlockDOM2Content(text);
} else {
text = event.clipboardData.getData("text/plain");
}
// 阻止右键复制菜单报错
setTimeout(function () {
document.execCommand("insertText", false, replaceFileName(text));
}, 0);
this.rename(protyle);
});
this.editElement.addEventListener("click", () => {
protyle.toolbar?.element.classList.add("fn__none");
});
this.editElement.addEventListener("input", (event: InputEvent) => {
if (event.isComposing) {
return;
}
if (this.editElement.textContent === "") {
this.editElement.querySelectorAll("br").forEach(item => {
item.remove();
}); });
} }
event.preventDefault(); this.rename(protyle);
});
this.editElement.addEventListener("compositionend", () => {
this.rename(protyle);
});
this.editElement.addEventListener("drop", (event: DragEvent) => {
// https://ld246.com/article/1661911210429
event.stopPropagation(); event.stopPropagation();
return; event.preventDefault();
} });
if (electronUndo(event)) { this.editElement.addEventListener("keydown", (event: KeyboardEvent) => {
return; if (event.isComposing) {
} return;
if (event.key === "ArrowDown") {
const rects = getSelection().getRangeAt(0).getClientRects();
// https://github.com/siyuan-note/siyuan/issues/11729
if (rects.length === 0 // 标题为空时时
|| this.editElement.getBoundingClientRect().bottom - rects[rects.length - 1].bottom < 25) {
const noContainerElement = getNoContainerElement(protyle.wysiwyg.element.firstElementChild);
// https://github.com/siyuan-note/siyuan/issues/4923
if (noContainerElement) {
focusBlock(noContainerElement, protyle.wysiwyg.element);
}
event.preventDefault();
event.stopPropagation();
} }
} else if (event.key === "Enter") {
const editElement = getContenteditableElement(protyle.wysiwyg.element.firstElementChild); if (commonHotkey(protyle, event)) {
if (editElement && editElement.textContent === "" && editElement.getAttribute("placeholder")) { return true;
// 配合提示文本使用,避免提示文本挤压到第二个块中
focusBlock(protyle.wysiwyg.element.firstElementChild, protyle.wysiwyg.element);
} else {
const newId = Lute.NewNodeID();
const newElement = genEmptyElement(false, true, newId);
protyle.wysiwyg.element.insertAdjacentElement("afterbegin", newElement);
focusByWbr(newElement, protyle.toolbar.range || getEditorRange(newElement));
transaction(protyle, [{
action: "insert",
data: newElement.outerHTML,
id: newId,
parentID: protyle.block.parentID
}], [{
action: "delete",
id: newId,
}]);
} }
event.preventDefault(); if (matchHotKey("⇧⌘V", event)) {
event.stopPropagation();
} else if (matchHotKey(window.siyuan.config.keymap.editor.general.attr.custom, event)) {
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
openFileAttr(response.data.ial, "bookmark", protyle);
});
event.preventDefault();
event.stopPropagation();
} else if (matchHotKey("⌘A", event)) {
getEditorRange(this.editElement).selectNodeContents(this.editElement);
event.preventDefault();
event.stopPropagation();
}
});
const iconElement = this.element.querySelector(".protyle-title__icon");
iconElement.addEventListener("click", () => {
if (window.siyuan.shiftIsPressed) {
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
openFileAttr(response.data.ial, "bookmark", protyle);
});
} else {
const iconRect = iconElement.getBoundingClientRect();
openTitleMenu(protyle, {x: iconRect.left, y: iconRect.bottom});
}
});
this.element.addEventListener("contextmenu", (event) => {
if (event.shiftKey) {
return;
}
if (getSelection().rangeCount === 0) {
openTitleMenu(protyle, {x: event.clientX, y: event.clientY});
return;
}
protyle.toolbar?.element.classList.add("fn__none");
window.siyuan.menus.menu.remove();
const range = getEditorRange(this.editElement);
if (range.toString() !== "") {
window.siyuan.menus.menu.append(new MenuItem({
id: "copy",
icon: "iconCopy",
accelerator: "⌘C",
label: window.siyuan.languages.copy,
click: () => {
focusByRange(getEditorRange(this.editElement));
document.execCommand("copy");
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "cut",
icon: "iconCut",
accelerator: "⌘X",
label: window.siyuan.languages.cut,
click: () => {
focusByRange(getEditorRange(this.editElement));
document.execCommand("cut");
setTimeout(() => {
this.rename(protyle);
}, Constants.TIMEOUT_INPUT);
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "delete",
icon: "iconTrashcan",
accelerator: "⌫",
label: window.siyuan.languages.delete,
click: () => {
const range = getEditorRange(this.editElement);
range.extractContents();
focusByRange(range);
setTimeout(() => {
this.rename(protyle);
}, Constants.TIMEOUT_INPUT);
}
}).element);
}
window.siyuan.menus.menu.append(new MenuItem({
id: "paste",
label: window.siyuan.languages.paste,
icon: "iconPaste",
accelerator: "⌘V",
click: async () => {
focusByRange(getEditorRange(this.editElement));
if (document.queryCommandSupported("paste")) {
document.execCommand("paste");
} else {
try {
const text = await readText();
document.execCommand("insertText", false, replaceFileName(text));
this.rename(protyle);
} catch (e) {
console.log(e);
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "pasteAsPlainText",
label: window.siyuan.languages.pasteAsPlainText,
accelerator: "⇧⌘V",
click: async () => {
navigator.clipboard.readText().then(textPlain => { navigator.clipboard.readText().then(textPlain => {
// 对 HTML 标签进行内部转义,避免被 Lute 解析以后变为小写 https://github.com/siyuan-note/siyuan/issues/10620
textPlain = textPlain.replace(/</g, ";;;lt;;;").replace(/>/g, ";;;gt;;;"); textPlain = textPlain.replace(/</g, ";;;lt;;;").replace(/>/g, ";;;gt;;;");
enableLuteMarkdownSyntax(protyle); enableLuteMarkdownSyntax(protyle);
let content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain)); let content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
@ -273,23 +111,189 @@ export class Title {
document.execCommand("insertText", false, replaceFileName(content)); document.execCommand("insertText", false, replaceFileName(content));
this.rename(protyle); this.rename(protyle);
}); });
event.preventDefault();
event.stopPropagation();
} }
}).element); if (matchHotKey(window.siyuan.config.keymap.general.enterBack.custom, event)) {
window.siyuan.menus.menu.append(new MenuItem({ const ids = protyle.path.split("/");
id: "selectAll", if (ids.length > 2) {
label: window.siyuan.languages.selectAll, /// #if !MOBILE
icon: "iconSelect", openFileById({
accelerator: "⌘A", app: protyle.app,
click: () => { id: ids[ids.length - 2],
range.selectNodeContents(this.editElement); action: [Constants.CB_GET_FOCUS, Constants.CB_GET_SCROLL]
focusByRange(range); });
/// #endif
}
event.preventDefault();
event.stopPropagation();
return;
} }
}).element); if (electronUndo(event)) {
window.siyuan.menus.menu.popup({x: event.clientX, y: event.clientY}); return;
}); }
/// #else if (event.key === "ArrowDown") {
this.element.innerHTML = '<div class="protyle-attr"></div>'; const rects = getSelection().getRangeAt(0).getClientRects();
/// #endif // https://github.com/siyuan-note/siyuan/issues/11729
if (rects.length === 0 // 标题为空时时
|| this.editElement.getBoundingClientRect().bottom - rects[rects.length - 1].bottom < 25) {
const noContainerElement = getNoContainerElement(protyle.wysiwyg.element.firstElementChild);
// https://github.com/siyuan-note/siyuan/issues/4923
if (noContainerElement) {
focusBlock(noContainerElement, protyle.wysiwyg.element);
}
event.preventDefault();
event.stopPropagation();
}
} else if (event.key === "Enter") {
const editElement = getContenteditableElement(protyle.wysiwyg.element.firstElementChild);
if (editElement && editElement.textContent === "" && editElement.getAttribute("placeholder")) {
// 配合提示文本使用,避免提示文本挤压到第二个块中
focusBlock(protyle.wysiwyg.element.firstElementChild, protyle.wysiwyg.element);
} else {
const newId = Lute.NewNodeID();
const newElement = genEmptyElement(false, true, newId);
protyle.wysiwyg.element.insertAdjacentElement("afterbegin", newElement);
focusByWbr(newElement, protyle.toolbar.range || getEditorRange(newElement));
transaction(protyle, [{
action: "insert",
data: newElement.outerHTML,
id: newId,
parentID: protyle.block.parentID
}], [{
action: "delete",
id: newId,
}]);
}
event.preventDefault();
event.stopPropagation();
} else if (matchHotKey(window.siyuan.config.keymap.editor.general.attr.custom, event)) {
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
openFileAttr(response.data.ial, "bookmark", protyle);
});
event.preventDefault();
event.stopPropagation();
} else if (matchHotKey("⌘A", event)) {
getEditorRange(this.editElement).selectNodeContents(this.editElement);
event.preventDefault();
event.stopPropagation();
}
});
const iconElement = this.element.querySelector(".protyle-title__icon");
iconElement.addEventListener("click", () => {
if (window.siyuan.shiftIsPressed) {
fetchPost("/api/block/getDocInfo", {
id: protyle.block.rootID
}, (response) => {
openFileAttr(response.data.ial, "bookmark", protyle);
});
} else {
const iconRect = iconElement.getBoundingClientRect();
openTitleMenu(protyle, {x: iconRect.left, y: iconRect.bottom});
}
});
this.element.addEventListener("contextmenu", (event) => {
if (event.shiftKey) {
return;
}
if (getSelection().rangeCount === 0) {
openTitleMenu(protyle, {x: event.clientX, y: event.clientY});
return;
}
protyle.toolbar?.element.classList.add("fn__none");
window.siyuan.menus.menu.remove();
const range = getEditorRange(this.editElement);
if (range.toString() !== "") {
window.siyuan.menus.menu.append(new MenuItem({
id: "copy",
icon: "iconCopy",
accelerator: "⌘C",
label: window.siyuan.languages.copy,
click: () => {
focusByRange(getEditorRange(this.editElement));
document.execCommand("copy");
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "cut",
icon: "iconCut",
accelerator: "⌘X",
label: window.siyuan.languages.cut,
click: () => {
focusByRange(getEditorRange(this.editElement));
document.execCommand("cut");
setTimeout(() => {
this.rename(protyle);
}, Constants.TIMEOUT_INPUT);
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "delete",
icon: "iconTrashcan",
accelerator: "⌫",
label: window.siyuan.languages.delete,
click: () => {
const range = getEditorRange(this.editElement);
range.extractContents();
focusByRange(range);
setTimeout(() => {
this.rename(protyle);
}, Constants.TIMEOUT_INPUT);
}
}).element);
}
window.siyuan.menus.menu.append(new MenuItem({
id: "paste",
label: window.siyuan.languages.paste,
icon: "iconPaste",
accelerator: "⌘V",
click: async () => {
focusByRange(getEditorRange(this.editElement));
if (document.queryCommandSupported("paste")) {
document.execCommand("paste");
} else {
try {
const text = await readText();
document.execCommand("insertText", false, replaceFileName(text));
this.rename(protyle);
} catch (e) {
console.log(e);
}
}
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "pasteAsPlainText",
label: window.siyuan.languages.pasteAsPlainText,
accelerator: "⇧⌘V",
click: async () => {
navigator.clipboard.readText().then(textPlain => {
textPlain = textPlain.replace(/</g, ";;;lt;;;").replace(/>/g, ";;;gt;;;");
enableLuteMarkdownSyntax(protyle);
let content = protyle.lute.BlockDOM2EscapeMarkerContent(protyle.lute.Md2BlockDOM(textPlain));
restoreLuteMarkdownSyntax(protyle);
// 移除 ;;;lt;;; 和 ;;;gt;;; 转义及其包裹的内容
content = content.replace(/;;;lt;;;[^;]+;;;gt;;;/g, "");
document.execCommand("insertText", false, replaceFileName(content));
this.rename(protyle);
});
}
}).element);
window.siyuan.menus.menu.append(new MenuItem({
id: "selectAll",
label: window.siyuan.languages.selectAll,
icon: "iconSelect",
accelerator: "⌘A",
click: () => {
range.selectNodeContents(this.editElement);
focusByRange(range);
}
}).element);
window.siyuan.menus.menu.popup({x: event.clientX, y: event.clientY});
});
}
this.element.querySelector(".protyle-attr").addEventListener("click", (event: MouseEvent & { this.element.querySelector(".protyle-attr").addEventListener("click", (event: MouseEvent & {
target: HTMLElement target: HTMLElement
}) => { }) => {
@ -329,9 +333,15 @@ export class Title {
public setTitle(title: string) { public setTitle(title: string) {
/// #if MOBILE /// #if MOBILE
const inputElement = document.getElementById("toolbarName") as HTMLInputElement; if (this.editElement) {
if (code160to32(title) !== code160to32(inputElement.value)) { if (code160to32(title) !== code160to32(this.editElement.textContent)) {
inputElement.value = title === window.siyuan.languages.untitled ? "" : title; this.editElement.textContent = title === window.siyuan.languages.untitled ? "" : title;
}
} else {
const inputElement = document.getElementById("toolbarName") as HTMLInputElement;
if (code160to32(title) !== code160to32(inputElement.value)) {
inputElement.value = title === window.siyuan.languages.untitled ? "" : title;
}
} }
/// #else /// #else
if (code160to32(title) !== code160to32(this.editElement.textContent)) { if (code160to32(title) !== code160to32(this.editElement.textContent)) {

View file

@ -6,6 +6,8 @@ import {updateHotkeyTip} from "../util/compatibility";
/// #if !MOBILE /// #if !MOBILE
import {openBacklink, openGraph, openOutline} from "../../layout/dock/util"; import {openBacklink, openGraph, openOutline} from "../../layout/dock/util";
import * as path from "path"; import * as path from "path";
/// #else
import {openMobileFileById} from "../../mobile/editor";
/// #endif /// #endif
import {Constants} from "../../constants"; import {Constants} from "../../constants";
import {openCardByData} from "../../card/openCard"; import {openCardByData} from "../../card/openCard";
@ -214,22 +216,24 @@ export const openTitleMenu = (protyle: IProtyle, position: IPosition) => {
transferBlockRef(protyle.block.rootID); transferBlockRef(protyle.block.rootID);
} }
window.siyuan.menus.menu.append(new MenuItem({id: "separator_3", type: "separator"}).element); window.siyuan.menus.menu.append(new MenuItem({id: "separator_3", type: "separator"}).element);
/// #if !MOBILE
if (!protyle.model) { if (!protyle.model) {
window.siyuan.menus.menu.append(new MenuItem({ window.siyuan.menus.menu.append(new MenuItem({
id: "openBy", id: "openBy",
label: window.siyuan.languages.openBy, label: window.siyuan.languages.openBy,
icon: "iconOpen", icon: "iconOpen",
click() { click() {
/// #if !MOBILE
openFileById({ openFileById({
app: protyle.app, app: protyle.app,
id: protyle.block.id, id: protyle.block.id,
action: protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_CONTEXT], action: protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_CONTEXT],
}); });
/// #else
openMobileFileById(protyle.app, protyle.block.id, protyle.block.rootID !== protyle.block.id ? [Constants.CB_GET_ALL] : [Constants.CB_GET_CONTEXT]);
/// #endif
} }
}).element); }).element);
} }
/// #endif
/// #if !BROWSER /// #if !BROWSER
window.siyuan.menus.menu.append(new MenuItem({ window.siyuan.menus.menu.append(new MenuItem({
id: "openByNewWindow", id: "openByNewWindow",

View file

@ -6,7 +6,7 @@ import {
focusByWbr, focusByWbr,
getEditorRange, getEditorRange,
getSelectionOffset, getSelectionOffset,
getSelectionPosition, setLastNodeRange getSelectionPosition,
} from "../util/selection"; } from "../util/selection";
import {genHintItemHTML, hintEmbed, hintRef, hintSlash} from "./extend"; import {genHintItemHTML, hintEmbed, hintRef, hintSlash} from "./extend";
import {getSavePath, newFile} from "../../util/newFile"; import {getSavePath, newFile} from "../../util/newFile";
@ -559,16 +559,12 @@ ${genHintItemHTML(item)}
}, response => { }, response => {
// https://github.com/siyuan-note/siyuan/issues/10133 // https://github.com/siyuan-note/siyuan/issues/10133
protyle.toolbar.range = range; protyle.toolbar.range = range;
protyle.toolbar.setInlineMark(protyle, "block-ref", "range", { const refElement = protyle.toolbar.setInlineMark(protyle, "block-ref", "range", {
type: "id", type: "id",
color: `${response.data}${Constants.ZWSP}${refIsS ? "s" : "d"}${Constants.ZWSP}${(refIsS ? fileNames[0] : realFileName).substring(0, window.siyuan.config.editor.blockRefDynamicAnchorTextMaxLen)}` color: `${response.data}${Constants.ZWSP}${refIsS ? "s" : "d"}${Constants.ZWSP}${(refIsS ? fileNames[0] : realFileName).substring(0, window.siyuan.config.editor.blockRefDynamicAnchorTextMaxLen)}`
}); });
if (protyle.toolbar.range.endContainer.nodeType === 1 && if (refElement[0]) {
protyle.toolbar.range.endContainer.childNodes[protyle.toolbar.range.endOffset]) { protyle.toolbar.range.setEnd(refElement[0].lastChild, refElement[0].lastChild.textContent.length);
const refElement = hasPreviousSibling(protyle.toolbar.range.endContainer.childNodes[protyle.toolbar.range.endOffset]) as HTMLElement;
if (refElement && refElement.nodeType === 1 && refElement.getAttribute("data-type") === "block-ref") {
setLastNodeRange(refElement as HTMLElement, protyle.toolbar.range, false);
}
} }
protyle.toolbar.range.collapse(false); protyle.toolbar.range.collapse(false);
}); });
@ -600,16 +596,12 @@ ${genHintItemHTML(item)}
tempElement.innerText = dynamicTexts[1]; tempElement.innerText = dynamicTexts[1];
} }
} }
protyle.toolbar.setInlineMark(protyle, "block-ref", "range", { const refElement = protyle.toolbar.setInlineMark(protyle, "block-ref", "range", {
type: "id", type: "id",
color: `${tempElement.getAttribute("data-id")}${Constants.ZWSP}${tempElement.getAttribute("data-subtype")}${Constants.ZWSP}${tempElement.textContent}` color: `${tempElement.getAttribute("data-id")}${Constants.ZWSP}${tempElement.getAttribute("data-subtype")}${Constants.ZWSP}${tempElement.textContent}`
}); });
if (protyle.toolbar.range.endContainer.nodeType === 1 && if (refElement[0]) {
protyle.toolbar.range.endContainer.childNodes[protyle.toolbar.range.endOffset]) { protyle.toolbar.range.setEnd(refElement[0].lastChild, refElement[0].lastChild.textContent.length);
const refElement = hasPreviousSibling(protyle.toolbar.range.endContainer.childNodes[protyle.toolbar.range.endOffset]) as HTMLElement;
if (refElement && refElement.nodeType === 1 && refElement.getAttribute("data-type") === "block-ref") {
setLastNodeRange(refElement as HTMLElement, protyle.toolbar.range, false);
}
} }
protyle.toolbar.range.collapse(false); protyle.toolbar.range.collapse(false);
return; return;

View file

@ -290,6 +290,9 @@ export class Protyle {
data.data[0].doOperations.find((item: IOperation) => { data.data[0].doOperations.find((item: IOperation) => {
if (!this.protyle.preview.element.classList.contains("fn__none")) { if (!this.protyle.preview.element.classList.contains("fn__none")) {
this.protyle.preview.render(this.protyle); this.protyle.preview.render(this.protyle);
if (item.action === "updateAttrs") {
onTransaction(this.protyle, item, false);
}
} else if (this.protyle.options.backlinkData && ["delete", "move"].includes(item.action)) { } else if (this.protyle.options.backlinkData && ["delete", "move"].includes(item.action)) {
// 只对特定情况刷新,否则展开、编辑等操作刷新会频繁 // 只对特定情况刷新,否则展开、编辑等操作刷新会频繁
/// #if !MOBILE /// #if !MOBILE

View file

@ -309,7 +309,7 @@ export const genCellValue = (colType: TAVCol, value: string | any) => {
content2: dateObj2.valueOf() || 0, content2: dateObj2.valueOf() || 0,
isNotEmpty2: !isNaN(dateObj2.valueOf()), isNotEmpty2: !isNaN(dateObj2.valueOf()),
hasEndDate: !isNaN(dateObj2.valueOf()), hasEndDate: !isNaN(dateObj2.valueOf()),
isNotTime: dateObj1.hour() === 0, isNotTime: dateObj1.hour() === 0 && values[0].split(":").length === 1,
formattedContent: "", formattedContent: "",
} }
}; };
@ -517,6 +517,9 @@ export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type
html = `<input type="number" spellcheck="false" value="${cellElements[0].firstElementChild.getAttribute("data-content")}" ${style} class="b3-text-field">`; html = `<input type="number" spellcheck="false" value="${cellElements[0].firstElementChild.getAttribute("data-content")}" ${style} class="b3-text-field">`;
} else { } else {
if (["select", "mSelect"].includes(type)) { if (["select", "mSelect"].includes(type)) {
if (blockElement.getAttribute("data-rendering") === "true") {
return;
}
openMenuPanel({protyle, blockElement, type: "select", cellElements}); openMenuPanel({protyle, blockElement, type: "select", cellElements});
} else if (type === "mAsset") { } else if (type === "mAsset") {
openMenuPanel({protyle, blockElement, type: "asset", cellElements}); openMenuPanel({protyle, blockElement, type: "asset", cellElements});

View file

@ -192,11 +192,7 @@ export const getEditHTML = (options: {
<input type="checkbox" data-type="wrap" class="b3-switch b3-switch--menu"${colData.wrap ? " checked" : ""}> <input type="checkbox" data-type="wrap" class="b3-switch b3-switch--menu"${colData.wrap ? " checked" : ""}>
</label>`; </label>`;
if (colData.type !== "block") { if (colData.type !== "block") {
html += `<button class="b3-menu__item" data-type="${colData.hidden ? "showCol" : "hideCol"}"> html += `<button class="b3-menu__item${colData.type === "relation" ? " fn__none" : ""}" data-type="duplicateCol">
<svg class="b3-menu__icon" style=""><use xlink:href="#icon${colData.hidden ? "Eye" : "Eyeoff"}"></use></svg>
<span class="b3-menu__label">${colData.hidden ? window.siyuan.languages.showCol : window.siyuan.languages.hideCol}</span>
</button>
<button class="b3-menu__item${colData.type === "relation" ? " fn__none" : ""}" data-type="duplicateCol">
<svg class="b3-menu__icon" style=""><use xlink:href="#iconCopy"></use></svg> <svg class="b3-menu__icon" style=""><use xlink:href="#iconCopy"></use></svg>
<span class="b3-menu__label">${window.siyuan.languages.duplicate}</span> <span class="b3-menu__label">${window.siyuan.languages.duplicate}</span>
</button> </button>
@ -877,8 +873,88 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
}); });
} }
}); });
menu.addSeparator({id: "separator_2"});
} }
const isPin = cellElement.dataset.pin === "true";
menu.addItem({
id: isPin ? "unfreezeCol" : "freezeCol",
icon: isPin ? "iconUnpin" : "iconPin",
label: isPin ? window.siyuan.languages.unfreezeCol : window.siyuan.languages.freezeCol,
click() {
transaction(protyle, [{
action: "setAttrViewColPin",
id: colId,
avID,
data: !isPin,
blockID
}], [{
action: "setAttrViewColPin",
id: colId,
avID,
data: isPin,
blockID
}]);
updateAttrViewCellAnimation(blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {pin: !isPin});
}
});
if (type !== "block") {
menu.addItem({
id: "hide",
icon: "iconEyeoff",
label: window.siyuan.languages.hide,
click() {
transaction(protyle, [{
action: "setAttrViewColHidden",
id: colId,
avID,
data: true,
blockID
}], [{
action: "setAttrViewColHidden",
id: colId,
avID,
data: false,
blockID
}]);
}
});
}
menu.addItem({
icon: "iconRefresh",
label: window.siyuan.languages.syncColWidth,
click() {
transaction(protyle, [{
action: "syncAttrViewTableColWidth",
keyID: colId,
avID,
id: blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW),
}]);
}
});
menu.addItem({
icon: "iconSoftWrap",
label: `<label class="fn__flex" style="margin-bottom: 4px"><span>${window.siyuan.languages.wrap}</span><span class="fn__space fn__flex-1"></span>
<input type="checkbox" class="b3-switch b3-switch--menu"${cellElement.dataset.wrap === "true" ? " checked" : ""}></label>`,
bind(element) {
const wrapElement = element.querySelector(".b3-switch") as HTMLInputElement;
wrapElement.addEventListener("change", () => {
transaction(protyle, [{
action: "setAttrViewColWrap",
id: colId,
avID,
data: wrapElement.checked,
blockID
}], [{
action: "setAttrViewColWrap",
id: colId,
avID,
data: !wrapElement.checked,
blockID
}]);
menu.close();
});
}
});
menu.addSeparator({id: "separator_2"});
menu.addItem({ menu.addItem({
id: "insertColumnLeft", id: "insertColumnLeft",
icon: "iconInsertLeft", icon: "iconInsertLeft",
@ -913,62 +989,6 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
}); });
} }
}); });
if (type !== "block") {
menu.addItem({
id: "hide",
icon: "iconEyeoff",
label: window.siyuan.languages.hide,
click() {
transaction(protyle, [{
action: "setAttrViewColHidden",
id: colId,
avID,
data: true,
blockID
}], [{
action: "setAttrViewColHidden",
id: colId,
avID,
data: false,
blockID
}]);
}
});
}
const isPin = cellElement.dataset.pin === "true";
menu.addItem({
id: isPin ? "unfreezeCol" : "freezeCol",
icon: isPin ? "iconUnpin" : "iconPin",
label: isPin ? window.siyuan.languages.unfreezeCol : window.siyuan.languages.freezeCol,
click() {
transaction(protyle, [{
action: "setAttrViewColPin",
id: colId,
avID,
data: !isPin,
blockID
}], [{
action: "setAttrViewColPin",
id: colId,
avID,
data: isPin,
blockID
}]);
updateAttrViewCellAnimation(blockElement.querySelector(`.av__row--header .av__cell[data-col-id="${colId}"]`), undefined, {pin: !isPin});
}
});
menu.addItem({
icon: "iconRefresh",
label: window.siyuan.languages.syncColWidth,
click() {
transaction(protyle, [{
action: "syncAttrViewTableColWidth",
keyID: colId,
avID,
id: blockElement.getAttribute(Constants.CUSTOM_SY_AV_VIEW),
}]);
}
});
if (type !== "block") { if (type !== "block") {
if (type !== "relation") { if (type !== "relation") {
menu.addItem({ menu.addItem({
@ -1006,9 +1026,11 @@ export const showColMenu = (protyle: IProtyle, blockElement: Element, cellElemen
title: window.siyuan.languages.removeColConfirm, title: window.siyuan.languages.removeColConfirm,
content: `<div class="b3-dialog__content"> content: `<div class="b3-dialog__content">
${window.siyuan.languages.confirmRemoveRelationField ${window.siyuan.languages.confirmRemoveRelationField
.replace("${x}", colData.key.name || window.siyuan.languages._kernel[272]) .replace("${x}", colData.key.name || window.siyuan.languages._kernel[272])
.replace("${y}", relResponse.data.av.name || window.siyuan.languages._kernel[267]) .replace("${y}", relResponse.data.av.name || window.siyuan.languages._kernel[267])
.replace("${z}", relResponse.data.av.keyValues.find((item: {key: {id: string}}) => item.key.id === colData.key.relation.backKeyID).key.name || window.siyuan.languages._kernel[272])} .replace("${z}", relResponse.data.av.keyValues.find((item: {
key: { id: string }
}) => item.key.id === colData.key.relation.backKeyID).key.name || window.siyuan.languages._kernel[272])}
<div class="fn__hr--b"></div> <div class="fn__hr--b"></div>
<button class="fn__block b3-button b3-button--remove" data-action="delete">${window.siyuan.languages.removeBothRelationField}</button> <button class="fn__block b3-button b3-button--remove" data-action="delete">${window.siyuan.languages.removeBothRelationField}</button>
<div class="fn__hr"></div> <div class="fn__hr"></div>

View file

@ -18,9 +18,9 @@ export const getDateHTML = (cellElements: HTMLElement[]) => {
let value2 = ""; let value2 = "";
if (cellValue.isNotEmpty2) { if (cellValue.isNotEmpty2) {
value2 = dayjs(cellValue.content2).format(isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm"); value2 = dayjs(cellValue.content2).format(isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm");
const year = value.split("-")[0]; const year = value2.split("-")[0];
if (year.length !== 4) { if (year.length !== 4) {
value = new Array(4 - year.length).fill(0).join("") + value; value2 = new Array(4 - year.length).fill(0).join("") + value2;
} }
} else if (cellValue.hasEndDate) { } else if (cellValue.hasEndDate) {
value2 = dayjs(currentDate).format(isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm"); value2 = dayjs(currentDate).format(isNotTime ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm");
@ -94,6 +94,8 @@ export const bindDateEvent = (options: {
} }
}); });
inputElements[3].addEventListener("change", () => { inputElements[3].addEventListener("change", () => {
inputElements[0].value = "";
inputElements[1].value = "";
if (inputElements[3].checked) { if (inputElements[3].checked) {
inputElements[0].setAttribute("type", "datetime-local"); inputElements[0].setAttribute("type", "datetime-local");
inputElements[1].setAttribute("type", "datetime-local"); inputElements[1].setAttribute("type", "datetime-local");

View file

@ -83,10 +83,10 @@ export const setFilter = async (options: {
rectTarget = options.protyle.wysiwyg.element.querySelector(`[data-col-id="${options.target.dataset.colId}"]`).getBoundingClientRect(); rectTarget = options.protyle.wysiwyg.element.querySelector(`[data-col-id="${options.target.dataset.colId}"]`).getBoundingClientRect();
} }
const blockID = options.blockElement.getAttribute("data-node-id"); const blockID = options.blockElement.getAttribute("data-node-id");
let operationElement: HTMLSelectElement = undefined;
const menu = new Menu("set-filter-" + options.filter.column, () => { const menu = new Menu("set-filter-" + options.filter.column, () => {
const oldFilters = JSON.parse(JSON.stringify(options.data.view.filters)); const oldFilters = JSON.parse(JSON.stringify(options.data.view.filters));
const selectElement = menu.element.querySelector(".b3-select") as HTMLSelectElement; if (!operationElement || !operationElement.value) {
if (!selectElement || !selectElement.value) {
return; return;
} }
const newFilter: IAVFilter = { const newFilter: IAVFilter = {
@ -94,7 +94,7 @@ export const setFilter = async (options: {
value: { value: {
type: options.filter.value.type type: options.filter.value.type
}, },
operator: selectElement.value as TAVFilterOperator operator: operationElement.value as TAVFilterOperator
}; };
let hasMatch = false; let hasMatch = false;
let newValue; let newValue;
@ -132,8 +132,8 @@ export const setFilter = async (options: {
newValue = genCellValue(filterValue.type, { newValue = genCellValue(filterValue.type, {
isNotEmpty2: textElements[2].value !== "", isNotEmpty2: textElements[2].value !== "",
isNotEmpty: textElements[0].value !== "", isNotEmpty: textElements[0].value !== "",
content: textElements[0].value ? new Date(textElements[0].value + " 00:00").getTime() : null, content: textElements[0].value ? new Date(textElements[0].value + " 00:00").getTime() : 0,
content2: textElements[2].value ? new Date(textElements[2].value + " 00:00").getTime() : null, content2: textElements[2].value ? new Date(textElements[2].value + " 00:00").getTime() : 0,
hasEndDate: newFilter.operator === "Is between", hasEndDate: newFilter.operator === "Is between",
isNotTime: true, isNotTime: true,
}); });
@ -156,6 +156,7 @@ export const setFilter = async (options: {
}, },
type: "rollup" type: "rollup"
}; };
newFilter.quantifier = (menu.element.querySelector('.b3-select[data-type="quantifier"]') as HTMLSelectElement).value;
} else { } else {
newFilter.value = newValue; newFilter.value = newValue;
} }
@ -211,6 +212,7 @@ export const setFilter = async (options: {
if (colData.type === "rollup") { if (colData.type === "rollup") {
if (!colData.rollup || !colData.rollup.relationKeyID || !colData.rollup.keyID) { if (!colData.rollup || !colData.rollup.relationKeyID || !colData.rollup.keyID) {
showMessage(window.siyuan.languages.plsChoose); showMessage(window.siyuan.languages.plsChoose);
document.querySelector(".av__panel")?.remove();
openMenuPanel({ openMenuPanel({
protyle: options.protyle, protyle: options.protyle,
blockElement: options.blockElement, blockElement: options.blockElement,
@ -219,33 +221,46 @@ export const setFilter = async (options: {
}); });
return; return;
} }
let targetAVId = ""; if (colData.rollup.calc?.operator && colData.rollup.calc.operator !== "Range") {
fields.find((column) => { if (["Count all", "Count empty", "Count not empty", "Count values", "Count unique values", "Percent empty",
if (column.id === colData.rollup.relationKeyID) { "Percent not empty", "Percent unique values", "Percent checked", "Percent unchecked", "Sum", "Average", "Median",
targetAVId = column.relation.avID; "Min", "Max"].includes(colData.rollup.calc.operator)) {
return true; filterValue.type = "number";
} else if (["Checked", "Unchecked"].includes(colData.rollup.calc.operator)) {
filterValue.type = "checkbox";
} else if (["Earliest", "Latest"].includes(colData.rollup.calc.operator)) {
filterValue.type = "date";
} }
}); } else {
const response = await fetchSyncPost("/api/av/getAttributeView", {id: targetAVId}); let targetAVId = "";
response.data.av.keyValues.find((item: { fields.find((column) => {
key: { if (column.id === colData.rollup.relationKeyID) {
id: string, targetAVId = column.relation.avID;
name: string, return true;
type: TAVCol,
options: {
name: string,
color: string,
}[]
}
}) => {
if (item.key.id === colData.rollup.keyID) {
filterValue.type = item.key.type;
if (item.key.type === "select") {
colData.options = item.key.options;
} }
return true; });
} const response = await fetchSyncPost("/api/av/getAttributeView", {id: targetAVId});
}); response.data.av.keyValues.find((item: {
key: {
id: string,
name: string,
type: TAVCol,
options: {
name: string,
color: string,
}[]
}
}) => {
if (item.key.id === colData.rollup.keyID) {
filterValue.type = item.key.type;
if (item.key.type === "select") {
colData.options = item.key.options;
}
return true;
}
});
}
options.data.view.filters.find(item => { options.data.view.filters.find(item => {
if (item.column === colData.id && item.value.type === "rollup") { if (item.column === colData.id && item.value.type === "rollup") {
if (!item.value.rollup || !item.value.rollup.contents || item.value.rollup.contents.length === 0) { if (!item.value.rollup || !item.value.rollup.contents || item.value.rollup.contents.length === 0) {
@ -336,10 +351,21 @@ export const setFilter = async (options: {
<option ${"Is not empty" === options.filter.operator ? "selected" : ""} value="Is not empty">${window.siyuan.languages.filterOperatorIsNotEmpty}</option>`; <option ${"Is not empty" === options.filter.operator ? "selected" : ""} value="Is not empty">${window.siyuan.languages.filterOperatorIsNotEmpty}</option>`;
break; break;
} }
if (options.filter.value.type === "rollup") {
menu.addItem({
iconHTML: "",
type: "readonly",
label: ` <select style="margin: 4px 0" class="b3-select fn__size200" data-type="quantifier">
<option ${(options.filter.quantifier === "" || options.filter.quantifier === "Any") ? "selected" : ""} value="Any">${window.siyuan.languages.filterQuantifierAny}</option>
<option ${"All" === options.filter.quantifier ? "selected" : ""} value="All">${window.siyuan.languages.filterQuantifierAll}</option>
<option ${"None" === options.filter.quantifier ? "selected" : ""} value="None">${window.siyuan.languages.filterQuantifierNone}</option>
</select>`
});
}
menu.addItem({ menu.addItem({
iconHTML: "", iconHTML: "",
type: "readonly", type: "readonly",
label: `<select style="margin: 4px 0" class="b3-select fn__size200">${selectHTML}</select>` label: `<select style="margin: 4px 0" class="b3-select fn__size200" data-type="operation">${selectHTML}</select>`
}); });
if (filterValue.type === "select" || filterValue.type === "mSelect") { if (filterValue.type === "select" || filterValue.type === "mSelect") {
if (colData.options?.length > 0) { if (colData.options?.length > 0) {
@ -506,9 +532,9 @@ export const setFilter = async (options: {
} }
} }
}); });
const selectElement = (menu.element.querySelector(".b3-select") as HTMLSelectElement); operationElement = (menu.element.querySelector('.b3-select[data-type="operation"]') as HTMLSelectElement);
selectElement.addEventListener("change", () => { operationElement?.addEventListener("change", () => {
toggleEmpty(selectElement, selectElement.value, filterValue.type); toggleEmpty(operationElement, operationElement.value, filterValue.type);
}); });
const dateTypeElement = menu.element.querySelector('.b3-select[data-type="dateType"]') as HTMLSelectElement; const dateTypeElement = menu.element.querySelector('.b3-select[data-type="dateType"]') as HTMLSelectElement;
dateTypeElement?.addEventListener("change", () => { dateTypeElement?.addEventListener("change", () => {
@ -557,7 +583,7 @@ export const setFilter = async (options: {
}); });
}); });
} }
toggleEmpty(selectElement, selectElement.value, filterValue.type); toggleEmpty(operationElement, operationElement.value, filterValue.type);
menu.open({x: rectTarget.left, y: rectTarget.bottom}); menu.open({x: rectTarget.left, y: rectTarget.bottom});
if (textElements.length > 0) { if (textElements.length > 0) {
textElements[0].select(); textElements[0].select();
@ -625,18 +651,27 @@ export const getFiltersHTML = (data: IAV) => {
fields.find((item) => { fields.find((item) => {
if (item.id === filter.column && item.type === filter.value.type) { if (item.id === filter.column && item.type === filter.value.type) {
let filterText = ""; let filterText = "";
if (item.type === "rollup") {
if (filter.quantifier === "" || filter.quantifier === "Any") {
filterText = window.siyuan.languages.filterQuantifierAny + " ";
} else if (filter.quantifier === "All") {
filterText = window.siyuan.languages.filterQuantifierAll + " ";
} else if (filter.quantifier === "None") {
filterText = window.siyuan.languages.filterQuantifierNone + " ";
}
}
const filterValue = item.type === "rollup" ? (filter.value.rollup?.contents?.length > 0 ? filter.value.rollup.contents[0] : {type: "rollup"} as IAVCellValue) : filter.value; const filterValue = item.type === "rollup" ? (filter.value.rollup?.contents?.length > 0 ? filter.value.rollup.contents[0] : {type: "rollup"} as IAVCellValue) : filter.value;
if (filter.operator === "Is empty") { if (filter.operator === "Is empty") {
filterText = ": " + window.siyuan.languages.filterOperatorIsEmpty; filterText = ": " + filterText + window.siyuan.languages.filterOperatorIsEmpty;
} else if (filter.operator === "Is not empty") { } else if (filter.operator === "Is not empty") {
filterText = ": " + window.siyuan.languages.filterOperatorIsNotEmpty; filterText = ": " + filterText + window.siyuan.languages.filterOperatorIsNotEmpty;
} else if (filter.operator === "Is false") { } else if (filter.operator === "Is false") {
if (filterValue.type !== "checkbox" || typeof filterValue.checkbox.checked === "boolean") { if (filterValue.type !== "checkbox" || typeof filterValue.checkbox.checked === "boolean") {
filterText = ": " + window.siyuan.languages.unchecked; filterText = ": " + filterText + window.siyuan.languages.unchecked;
} }
} else if (filter.operator === "Is true") { } else if (filter.operator === "Is true") {
if (filterValue.type !== "checkbox" || typeof filterValue.checkbox.checked === "boolean") { if (filterValue.type !== "checkbox" || typeof filterValue.checkbox.checked === "boolean") {
filterText = ": " + window.siyuan.languages.checked; filterText = ": " + filterText + window.siyuan.languages.checked;
} }
} else if (["created", "updated", "date"].includes(filterValue.type)) { } else if (["created", "updated", "date"].includes(filterValue.type)) {
let dateValue = ""; let dateValue = "";
@ -660,15 +695,15 @@ export const getFiltersHTML = (data: IAV) => {
} }
if (dateValue) { if (dateValue) {
if (filter.operator === "Is between" && dateValue2) { if (filter.operator === "Is between" && dateValue2) {
filterText = ` ${window.siyuan.languages.filterOperatorIsBetween} ${dateValue} ${dateValue2}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorIsBetween} ${dateValue} ${dateValue2}`;
} else if ("=" === filter.operator) { } else if ("=" === filter.operator) {
filterText = `: ${dateValue}`; filterText = `: ${filterText}${dateValue}`;
} else if ([">", "<"].includes(filter.operator)) { } else if ([">", "<"].includes(filter.operator)) {
filterText = ` ${filter.operator} ${dateValue}`; filterText = ` ${filterText}${filter.operator} ${dateValue}`;
} else if (">=" === filter.operator) { } else if (">=" === filter.operator) {
filterText = ` ${dateValue}`; filterText = ` ${filterText}${dateValue}`;
} else if ("<=" === filter.operator) { } else if ("<=" === filter.operator) {
filterText = ` ${dateValue}`; filterText = ` ${filterText}${dateValue}`;
} }
} }
} else if (["mSelect", "select"].includes(filterValue.type) && filterValue.mSelect?.length > 0) { } else if (["mSelect", "select"].includes(filterValue.type) && filterValue.mSelect?.length > 0) {
@ -680,41 +715,41 @@ export const getFiltersHTML = (data: IAV) => {
} }
}); });
if ("Contains" === filter.operator) { if ("Contains" === filter.operator) {
filterText = `: ${selectContent}`; filterText = `: ${filterText}${selectContent}`;
} else if (filter.operator === "Does not contains") { } else if (filter.operator === "Does not contains") {
filterText = ` ${window.siyuan.languages.filterOperatorDoesNotContain} ${selectContent}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorDoesNotContain} ${selectContent}`;
} else if (filter.operator === "=") { } else if (filter.operator === "=") {
filterText = `: ${selectContent}`; filterText = `: ${filterText}${selectContent}`;
} else if (filter.operator === "!=") { } else if (filter.operator === "!=") {
filterText = ` ${window.siyuan.languages.filterOperatorIsNot} ${selectContent}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorIsNot} ${selectContent}`;
} }
} else if (filterValue.type === "number" && filterValue.number && filterValue.number.isNotEmpty) { } else if (filterValue.type === "number" && filterValue.number && filterValue.number.isNotEmpty) {
if (["=", "!=", ">", "<"].includes(filter.operator)) { if (["=", "!=", ">", "<"].includes(filter.operator)) {
filterText = ` ${filter.operator} ${filterValue.number.content}`; filterText = ` ${filterText}${filter.operator} ${filterValue.number.content}`;
} else if (">=" === filter.operator) { } else if (">=" === filter.operator) {
filterText = ` ${filterValue.number.content}`; filterText = ` ${filterText}${filterValue.number.content}`;
} else if ("<=" === filter.operator) { } else if ("<=" === filter.operator) {
filterText = ` ${filterValue.number.content}`; filterText = ` ${filterText}${filterValue.number.content}`;
} }
} else if (["text", "block", "url", "phone", "email", "relation", "template"].includes(filterValue.type) && filterValue[filterValue.type as "text"]) { } else if (["text", "block", "url", "phone", "email", "relation", "template"].includes(filterValue.type) && filterValue[filterValue.type as "text"]) {
const content = filterValue[filterValue.type as "text"].content || filterValue.relation?.blockIDs[0] || ""; const content = filterValue[filterValue.type as "text"].content || filterValue.relation?.blockIDs[0] || "";
if (content) { if (content) {
if (["=", "Contains"].includes(filter.operator)) { if (["=", "Contains"].includes(filter.operator)) {
filterText = `: ${content}`; filterText = `: ${filterText}${content}`;
} else if (filter.operator === "Does not contains") { } else if (filter.operator === "Does not contains") {
filterText = ` ${window.siyuan.languages.filterOperatorDoesNotContain} ${content}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorDoesNotContain} ${content}`;
} else if (filter.operator === "!=") { } else if (filter.operator === "!=") {
filterText = ` ${window.siyuan.languages.filterOperatorIsNot} ${content}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorIsNot} ${content}`;
} else if ("Starts with" === filter.operator) { } else if ("Starts with" === filter.operator) {
filterText = ` ${window.siyuan.languages.filterOperatorStartsWith} ${content}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorStartsWith} ${content}`;
} else if ("Ends with" === filter.operator) { } else if ("Ends with" === filter.operator) {
filterText = ` ${window.siyuan.languages.filterOperatorEndsWith} ${content}`; filterText = ` ${filterText}${window.siyuan.languages.filterOperatorEndsWith} ${content}`;
} else if ([">", "<"].includes(filter.operator)) { } else if ([">", "<"].includes(filter.operator)) {
filterText = ` ${filter.operator} ${content}`; filterText = ` ${filterText}${filter.operator} ${content}`;
} else if (">=" === filter.operator) { } else if (">=" === filter.operator) {
filterText = ` ${content}`; filterText = ` ${filterText}${content}`;
} else if ("<=" === filter.operator) { } else if ("<=" === filter.operator) {
filterText = ` ${content}`; filterText = ` ${filterText}${content}`;
} }
} }
} }

View file

@ -264,7 +264,7 @@ const renderGroupTable = (options: ITableOptions) => {
options.data.view.groups.forEach((group: IAVTable) => { options.data.view.groups.forEach((group: IAVTable) => {
if (group.groupHidden === 0) { if (group.groupHidden === 0) {
avBodyHTML += `${getGroupTitleHTML(group, group.rows.length)} avBodyHTML += `${getGroupTitleHTML(group, group.rows.length)}
<div data-group-id="${group.id}" data-page-size="${group.pageSize}" data-dtype="${group.groupKey.type}" data-content="${group.groupValue.text?.content}" style="float: left" class="av__body${group.groupFolded ? " fn__none" : ""}">${getTableHTMLs(group, options.blockElement)}</div>`; <div data-group-id="${group.id}" data-page-size="${group.pageSize}" data-dtype="${group.groupKey.type}" data-content="${Lute.EscapeHTMLStr(group.groupValue.text?.content)}" style="float: left" class="av__body${group.groupFolded ? " fn__none" : ""}">${getTableHTMLs(group, options.blockElement)}</div>`;
} }
}); });
if (options.renderAll) { if (options.renderAll) {
@ -451,6 +451,7 @@ export const avRender = (element: Element, protyle: IProtyle, cb?: (data: IAV) =
} }
if (avElements.length > 0) { if (avElements.length > 0) {
avElements.forEach((e: HTMLElement) => { avElements.forEach((e: HTMLElement) => {
e.removeAttribute("data-rendering");
if (e.getAttribute("data-render") === "true" || hasClosestByClassName(e, "av__gallery-content")) { if (e.getAttribute("data-render") === "true" || hasClosestByClassName(e, "av__gallery-content")) {
return; return;
} }
@ -784,7 +785,8 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
} }
} }
if (popCellElement && popCellElement.getAttribute("data-detached") === "true" && if (popCellElement && popCellElement.getAttribute("data-detached") === "true" &&
popCellElement.querySelector(".av__celltext").textContent === "") { popCellElement.querySelector(".av__celltext").textContent === "" &&
popCellElement.getBoundingClientRect().height !== 0) {
popTextCell(protyle, [popCellElement], "block"); popTextCell(protyle, [popCellElement], "block");
} }
} }

View file

@ -633,6 +633,7 @@ export const addColOptionOrCell = (protyle: IProtyle, data: IAV, cellElements: H
transaction(protyle, cellDoOperations, cellUndoOperations); transaction(protyle, cellDoOperations, cellUndoOperations);
} }
if (colData.type === "select") { if (colData.type === "select") {
blockElement.setAttribute("data-rendering", "true");
menuElement.parentElement.dispatchEvent(new CustomEvent("click", {detail: "close"})); menuElement.parentElement.dispatchEvent(new CustomEvent("click", {detail: "close"}));
} else { } else {
const oldScroll = menuElement.querySelector(".b3-menu__items").scrollTop; const oldScroll = menuElement.querySelector(".b3-menu__items").scrollTop;

View file

@ -1273,23 +1273,25 @@ export class Toolbar {
let html = ""; let html = "";
// sort // sort
let matchInput = false; let matchInput = false;
matchLanguages.sort((a, b) => { if (lowerCaseValue) {
if (a.startsWith(lowerCaseValue) && b.startsWith(lowerCaseValue)) { matchLanguages.sort((a, b) => {
if (a.length < b.length) { if (a.startsWith(lowerCaseValue) && b.startsWith(lowerCaseValue)) {
if (a.length < b.length) {
return -1;
} else if (a.length === b.length) {
return 0;
} else {
return 1;
}
} else if (a.startsWith(lowerCaseValue)) {
return -1; return -1;
} else if (a.length === b.length) { } else if (b.startsWith(lowerCaseValue)) {
return 0;
} else {
return 1; return 1;
} else {
return 0;
} }
} else if (a.startsWith(lowerCaseValue)) { });
return -1; }
} else if (b.startsWith(lowerCaseValue)) {
return 1;
} else {
return 0;
}
});
const eventDetail = {languages: matchLanguages}; const eventDetail = {languages: matchLanguages};
if (protyle.app && protyle.app.plugins) { if (protyle.app && protyle.app.plugins) {

View file

@ -11,11 +11,12 @@ export class Options {
render: { render: {
background: false, background: false,
title: false, title: false,
titleShowTop: false,
hideTitleOnZoom: false,
gutter: true, gutter: true,
scroll: false, scroll: false,
breadcrumb: true, breadcrumb: true,
breadcrumbDocName: false, breadcrumbDocName: false,
hideTitleOnZoom: false,
}, },
action: [], action: [],
after: undefined, after: undefined,

View file

@ -23,24 +23,30 @@ export const encodeBase64 = (text: string): string => {
} }
}; };
const getSiyuanHTML = (text: IClipboardData) => { export const getTextSiyuanFromTextHTML = (html: string) => {
const siyuanMatch = text.textHTML.match(/<!--data-siyuan='([^']+)'-->/); const siyuanMatch = html.match(/<!--data-siyuan='([^']+)'-->/);
let textSiyuan = "";
let textHtml = html;
if (siyuanMatch) { if (siyuanMatch) {
try { try {
if (typeof Buffer !== "undefined") { if (typeof Buffer !== "undefined") {
const decodedBytes = Buffer.from(siyuanMatch[1], "base64"); const decodedBytes = Buffer.from(siyuanMatch[1], "base64");
text.siyuanHTML = decodedBytes.toString("utf8"); textSiyuan = decodedBytes.toString("utf8");
} else { } else {
const decoder = new TextDecoder(); const decoder = new TextDecoder();
const bytes = Uint8Array.from(atob(siyuanMatch[1]), char => char.charCodeAt(0)); const bytes = Uint8Array.from(atob(siyuanMatch[1]), char => char.charCodeAt(0));
text.siyuanHTML = decoder.decode(bytes); textSiyuan = decoder.decode(bytes);
} }
// 移除注释节点,保持原有的 text/html 内容 // 移除注释节点,保持原有的 text/html 内容
text.textHTML = text.textHTML.replace(/<!--data-siyuan='[^']+'-->/, ""); textHtml = html.replace(/<!--data-siyuan='[^']+'-->/, "");
} catch (e) { } catch (e) {
console.log("Failed to decode siyuan data from HTML comment:", e); console.log("Failed to decode siyuan data from HTML comment:", e);
} }
} }
return {
textSiyuan,
textHtml
};
}; };
export const openByMobile = (uri: string) => { export const openByMobile = (uri: string) => {
@ -124,7 +130,9 @@ export const readClipboard = async () => {
if (item.types.includes("text/html")) { if (item.types.includes("text/html")) {
const blob = await item.getType("text/html"); const blob = await item.getType("text/html");
text.textHTML = await blob.text(); text.textHTML = await blob.text();
getSiyuanHTML(text); const textObj = getTextSiyuanFromTextHTML(text.textHTML);
text.textHTML = textObj.textHtml;
text.siyuanHTML = textObj.textSiyuan;
} }
if (item.types.includes("text/plain")) { if (item.types.includes("text/plain")) {
const blob = await item.getType("text/plain"); const blob = await item.getType("text/plain");
@ -145,11 +153,15 @@ export const readClipboard = async () => {
if (isInAndroid()) { if (isInAndroid()) {
text.textPlain = window.JSAndroid.readClipboard(); text.textPlain = window.JSAndroid.readClipboard();
text.textHTML = window.JSAndroid.readHTMLClipboard(); text.textHTML = window.JSAndroid.readHTMLClipboard();
getSiyuanHTML(text); const textObj = getTextSiyuanFromTextHTML(text.textHTML);
text.textHTML = textObj.textHtml;
text.siyuanHTML = textObj.textSiyuan;
} else if (isInHarmony()) { } else if (isInHarmony()) {
text.textPlain = window.JSHarmony.readClipboard(); text.textPlain = window.JSHarmony.readClipboard();
text.textHTML = window.JSHarmony.readHTMLClipboard(); text.textHTML = window.JSHarmony.readHTMLClipboard();
getSiyuanHTML(text); const textObj = getTextSiyuanFromTextHTML(text.textHTML);
text.textHTML = textObj.textHtml;
text.siyuanHTML = textObj.textSiyuan;
} }
return text; return text;
} }

View file

@ -1418,6 +1418,7 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
targetElement.classList.remove("dragover__bottom", "dragover__top", "dragover__left", "dragover__right"); targetElement.classList.remove("dragover__bottom", "dragover__top", "dragover__left", "dragover__right");
} }
} else if (!window.siyuan.dragElement && (event.dataTransfer.types[0] === "Files" || event.dataTransfer.types.includes("text/html"))) { } else if (!window.siyuan.dragElement && (event.dataTransfer.types[0] === "Files" || event.dataTransfer.types.includes("text/html"))) {
event.preventDefault();
// 外部文件拖入编辑器中或者编辑器内选中文字拖拽 // 外部文件拖入编辑器中或者编辑器内选中文字拖拽
// https://github.com/siyuan-note/siyuan/issues/9544 // https://github.com/siyuan-note/siyuan/issues/9544
const avElement = hasClosestByClassName(event.target, "av"); const avElement = hasClosestByClassName(event.target, "av");

View file

@ -446,12 +446,33 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
insertBefore = true; insertBefore = true;
} }
} }
(insertBefore ? Array.from(tempElement.content.children) : Array.from(tempElement.content.children).reverse()).forEach((item) => { // https://github.com/siyuan-note/siyuan/issues/15768
// https://github.com/siyuan-note/siyuan/issues/13232 if (tempElement.content.firstChild.nodeType === 3 || (tempElement.content.firstChild.nodeType === 1 && tempElement.content.firstElementChild.tagName !== "DIV")) {
if (item.getAttribute("data-type") === "NodeHeading" && item.getAttribute("fold") === "1") { tempElement.innerHTML = protyle.lute.SpinBlockDOM(tempElement.innerHTML);
item.removeAttribute("fold"); }
} // let foldHeadingId = "";
// let foldHTML = "";
// 粘贴内容中包含折叠的子节点需后端插入到原节点中
// Array.from(tempElement.content.children).forEach((item) => {
// if (!item.getAttribute("parent-heading") && foldHeadingId && foldHTML) {
// fetchPost("/api/block/appendHeadingChildren", {id: foldHeadingId, dom: foldHTML});
// foldHeadingId = "";
// foldHTML = "";
// }
// if (item.getAttribute("data-type") === "NodeHeading" && item.getAttribute("fold") === "1") {
// foldHeadingId = item.getAttribute("data-node-id");
// return true;
// }
// if (foldHeadingId && item.getAttribute("parent-heading")) {
// foldHTML += item.outerHTML;
// }
// });
// if (foldHeadingId && foldHTML) {
// fetchPost("/api/block/appendHeadingChildren", {id: foldHeadingId, dom: foldHTML});
// }
(insertBefore ? Array.from(tempElement.content.children) : Array.from(tempElement.content.children).reverse()).find((item) => {
let addId = item.getAttribute("data-node-id"); let addId = item.getAttribute("data-node-id");
const hasParentHeading = item.getAttribute("parent-heading");
if (addId === id) { if (addId === id) {
doOperation.push({ doOperation.push({
action: "update", action: "update",
@ -476,10 +497,12 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
liElement.append(item); liElement.append(item);
item = liElement; item = liElement;
} }
item.removeAttribute("parent-heading");
doOperation.push({ doOperation.push({
action: "insert", action: "insert",
data: item.outerHTML, data: item.outerHTML,
id: addId, id: addId,
context: {ignoreProcess: hasParentHeading ? "true" : "false"},
nextID: insertBefore ? id : undefined, nextID: insertBefore ? id : undefined,
previousID: insertBefore ? undefined : id previousID: insertBefore ? undefined : id
}); });
@ -488,10 +511,12 @@ export const insertHTML = (html: string, protyle: IProtyle, isBlock = false,
id: addId, id: addId,
}); });
} }
if (insertBefore) { if (!hasParentHeading) {
blockElement.before(item); if (insertBefore) {
} else { blockElement.before(item);
blockElement.after(item); } else {
blockElement.after(item);
}
} }
if (!lastElement) { if (!lastElement) {
lastElement = item; lastElement = item;

View file

@ -1,7 +1,7 @@
import {Constants} from "../../constants"; import {Constants} from "../../constants";
import {uploadFiles, uploadLocalFiles} from "../upload"; import {uploadFiles, uploadLocalFiles} from "../upload";
import {processPasteCode, processRender} from "./processCode"; import {processPasteCode, processRender} from "./processCode";
import {getLocalFiles, readText} from "./compatibility"; import {getLocalFiles, getTextSiyuanFromTextHTML, readText} from "./compatibility";
import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "./hasClosest"; import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName} from "./hasClosest";
import {getEditorRange} from "./selection"; import {getEditorRange} from "./selection";
import {blockRender} from "../render/blockRender"; import {blockRender} from "../render/blockRender";
@ -288,6 +288,12 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
if (textPlain.endsWith(Constants.ZWSP) && !textHTML && !siyuanHTML) { if (textPlain.endsWith(Constants.ZWSP) && !textHTML && !siyuanHTML) {
siyuanHTML = textPlain.substr(0, textPlain.length - 1); siyuanHTML = textPlain.substr(0, textPlain.length - 1);
} }
// 复制/剪切折叠标题需获取 siyuanHTML
if (textHTML && textPlain && !siyuanHTML) {
const textObj = getTextSiyuanFromTextHTML(textHTML);
siyuanHTML = textObj.textSiyuan;
textHTML = textObj.textHtml;
}
// 剪切复制中首位包含空格或仅有空格 https://github.com/siyuan-note/siyuan/issues/5667 // 剪切复制中首位包含空格或仅有空格 https://github.com/siyuan-note/siyuan/issues/5667
if (!siyuanHTML) { if (!siyuanHTML) {
// process word // process word
@ -380,10 +386,13 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
} }
if (types.includes("block-ref")) { if (types.includes("block-ref")) {
protyle.toolbar.setInlineMark(protyle, "block-ref", "range", { const refElement = protyle.toolbar.setInlineMark(protyle, "block-ref", "range", {
type: "id", type: "id",
color: `${linkElement.dataset.id}${Constants.ZWSP}s${Constants.ZWSP}${range.toString()}` color: `${linkElement.dataset.id}${Constants.ZWSP}s${Constants.ZWSP}${range.toString()}`
}); });
if (refElement[0]) {
protyle.toolbar.range.selectNodeContents(refElement[0]);
}
return; return;
} }
if (types.includes("a")) { if (types.includes("a")) {
@ -502,11 +511,15 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
} }
if (linkElement) { if (linkElement) {
const selectText = range.toString(); const selectText = range.toString();
protyle.toolbar.setInlineMark(protyle, "a", "range", { const aElements = protyle.toolbar.setInlineMark(protyle, "a", "range", {
type: "a", type: "a",
color: `${linkElement.getAttribute("href")}${Constants.ZWSP}${selectText || linkElement.textContent}` color: `${linkElement.getAttribute("href")}${Constants.ZWSP}${selectText || linkElement.textContent}`
}); });
if (!selectText) { if (!selectText) {
if (aElements[0].lastChild) {
// https://github.com/siyuan-note/siyuan/issues/15801
range.setEnd(aElements[0].lastChild, aElements[0].lastChild.textContent.length);
}
range.collapse(false); range.collapse(false);
} }
return; return;
@ -536,11 +549,14 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
if (range.toString() !== "") { if (range.toString() !== "") {
const firstLine = textPlain.split("\n")[0]; const firstLine = textPlain.split("\n")[0];
if (isDynamicRef(textPlain)) { if (isDynamicRef(textPlain)) {
protyle.toolbar.setInlineMark(protyle, "block-ref", "range", { const refElement = protyle.toolbar.setInlineMark(protyle, "block-ref", "range", {
type: "id", type: "id",
// range 不能 escape否则 https://github.com/siyuan-note/siyuan/issues/8359 // range 不能 escape否则 https://github.com/siyuan-note/siyuan/issues/8359
color: `${textPlain.substring(2, 22 + 2)}${Constants.ZWSP}s${Constants.ZWSP}${range.toString()}` color: `${textPlain.substring(2, 22 + 2)}${Constants.ZWSP}s${Constants.ZWSP}${range.toString()}`
}); });
if (refElement[0]) {
protyle.toolbar.range.selectNodeContents(refElement[0]);
}
return; return;
} else if (isFileAnnotation(firstLine)) { } else if (isFileAnnotation(firstLine)) {
protyle.toolbar.setInlineMark(protyle, "file-annotation-ref", "range", { protyle.toolbar.setInlineMark(protyle, "file-annotation-ref", "range", {

View file

@ -68,7 +68,7 @@ import {popSearch} from "../../mobile/menu/search";
import {BlockPanel} from "../../block/Panel"; import {BlockPanel} from "../../block/Panel";
import {copyPlainText, isInIOS, isMac, isOnlyMeta, readClipboard, encodeBase64} from "../util/compatibility"; import {copyPlainText, isInIOS, isMac, isOnlyMeta, readClipboard, encodeBase64} from "../util/compatibility";
import {MenuItem} from "../../menus/Menu"; import {MenuItem} from "../../menus/Menu";
import {fetchPost} from "../../util/fetch"; import {fetchPost, fetchSyncPost} from "../../util/fetch";
import {onGet} from "../util/onGet"; import {onGet} from "../util/onGet";
import {clearTableCell, isIncludeCell, setTableAlign} from "../util/table"; import {clearTableCell, isIncludeCell, setTableAlign} from "../util/table";
import {countBlockWord, countSelectWord} from "../../layout/status"; import {countBlockWord, countSelectWord} from "../../layout/status";
@ -256,7 +256,7 @@ export class WYSIWYG {
} }
private bindCommonEvent(protyle: IProtyle) { private bindCommonEvent(protyle: IProtyle) {
this.element.addEventListener("copy", (event: ClipboardEvent & { target: HTMLElement }) => { this.element.addEventListener("copy", async (event: ClipboardEvent & { target: HTMLElement }) => {
window.siyuan.ctrlIsPressed = false; // https://github.com/siyuan-note/siyuan/issues/6373 window.siyuan.ctrlIsPressed = false; // https://github.com/siyuan-note/siyuan/issues/6373
// https://github.com/siyuan-note/siyuan/issues/4600 // https://github.com/siyuan-note/siyuan/issues/4600
if (event.target.tagName === "PROTYLE-HTML" || event.target.localName === "input") { if (event.target.tagName === "PROTYLE-HTML" || event.target.localName === "input") {
@ -282,6 +282,8 @@ export class WYSIWYG {
} }
let html = ""; let html = "";
let textPlain = ""; let textPlain = "";
let isInCodeBlock = false;
let needClipboardWrite = false;
if (selectElements.length > 0) { if (selectElements.length > 0) {
const isRefText = selectElements[0].getAttribute("data-reftext") === "true"; const isRefText = selectElements[0].getAttribute("data-reftext") === "true";
if (selectElements[0].getAttribute("data-type") === "NodeListItem" && if (selectElements[0].getAttribute("data-type") === "NodeListItem" &&
@ -293,14 +295,24 @@ export class WYSIWYG {
html = selectElements[0].parentElement.outerHTML; html = selectElements[0].parentElement.outerHTML;
} }
} else { } else {
selectElements.forEach((item: HTMLElement, index) => { for (let i = 0; i < selectElements.length; i++) {
const item = selectElements[i] as HTMLElement;
// 复制列表项中的块会变为复制列表项,因此不能使用 getTopAloneElement https://github.com/siyuan-note/siyuan/issues/8925 // 复制列表项中的块会变为复制列表项,因此不能使用 getTopAloneElement https://github.com/siyuan-note/siyuan/issues/8925
if (isRefText && index === 0) { if (isRefText && i === 0) {
html += getTextStar(item) + "\n\n"; html += getTextStar(item) + "\n\n";
} else { } else {
html += removeEmbed(item); if (item.getAttribute("data-type") === "NodeHeading" && item.getAttribute("fold") === "1") {
needClipboardWrite = true;
const response = await fetchSyncPost("/api/block/getHeadingChildrenDOM", {
id: item.getAttribute("data-node-id"),
removeFoldAttr: false
});
html += response.data;
} else {
html += removeEmbed(item);
}
} }
}); }
} }
if (isRefText) { if (isRefText) {
selectElements[0].removeAttribute("data-reftext"); selectElements[0].removeAttribute("data-reftext");
@ -380,6 +392,8 @@ export class WYSIWYG {
if (matchHeading) { if (matchHeading) {
// 复制标题 https://github.com/siyuan-note/insider/issues/297 // 复制标题 https://github.com/siyuan-note/insider/issues/297
tempElement.append(headingElement.cloneNode(true)); tempElement.append(headingElement.cloneNode(true));
// https://github.com/siyuan-note/siyuan/issues/13232
headingElement.removeAttribute("fold");
} else if (!["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName)) { } else if (!["DIV", "TD", "TH", "TR"].includes(range.startContainer.parentElement.tagName)) {
// 复制行内元素 https://github.com/siyuan-note/insider/issues/191 // 复制行内元素 https://github.com/siyuan-note/insider/issues/191
tempElement.append(range.startContainer.parentElement.cloneNode(true)); tempElement.append(range.startContainer.parentElement.cloneNode(true));
@ -427,7 +441,7 @@ export class WYSIWYG {
if (isEndOfBlock(range)) { if (isEndOfBlock(range)) {
textPlain = textPlain.replace(/\n$/, ""); textPlain = textPlain.replace(/\n$/, "");
} }
html = textPlain; isInCodeBlock = true;
} else if (hasClosestByTag(range.startContainer, "TD") || hasClosestByTag(range.startContainer, "TH")) { } else if (hasClosestByTag(range.startContainer, "TD") || hasClosestByTag(range.startContainer, "TH")) {
tempElement.innerHTML = tempElement.innerHTML.replace(/<br>/g, "\n").replace(/<br\/>/g, "\n"); tempElement.innerHTML = tempElement.innerHTML.replace(/<br>/g, "\n").replace(/<br\/>/g, "\n");
textPlain = tempElement.textContent.endsWith("\n") ? tempElement.textContent.replace(/\n$/, "") : tempElement.textContent; textPlain = tempElement.textContent.endsWith("\n") ? tempElement.textContent.replace(/\n$/, "") : tempElement.textContent;
@ -445,14 +459,25 @@ export class WYSIWYG {
.replace(new RegExp(Constants.ZWSP, "g"), ""); .replace(new RegExp(Constants.ZWSP, "g"), "");
event.clipboardData.setData("text/plain", textPlain); event.clipboardData.setData("text/plain", textPlain);
// 设置 text/siyuan 数据 if (!isInCodeBlock) {
enableLuteMarkdownSyntax(protyle); enableLuteMarkdownSyntax(protyle);
const siyuanHTML = selectTableElement ? protyle.lute.HTML2BlockDOM(html) : html; const textSiyuan = selectTableElement ? protyle.lute.HTML2BlockDOM(html) : html;
event.clipboardData.setData("text/siyuan", siyuanHTML); event.clipboardData.setData("text/siyuan", textSiyuan);
restoreLuteMarkdownSyntax(protyle); restoreLuteMarkdownSyntax(protyle);
// 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据
// 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据 const textHTML = `<!--data-siyuan='${encodeBase64(textSiyuan)}'-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
event.clipboardData.setData("text/html", `<!--data-siyuan='${encodeBase64(siyuanHTML)}'-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html))); event.clipboardData.setData("text/html", textHTML);
if (needClipboardWrite) {
try {
await navigator.clipboard.write([new ClipboardItem({
["text/plain"]: textPlain,
["text/html"]: textHTML,
})]);
} catch (e) {
console.log("Copy write clipboard error:", e);
}
}
}
}); });
this.element.addEventListener("mousedown", (event: MouseEvent) => { this.element.addEventListener("mousedown", (event: MouseEvent) => {
@ -1720,7 +1745,7 @@ export class WYSIWYG {
} }
}); });
this.element.addEventListener("cut", (event: ClipboardEvent & { target: HTMLElement }) => { this.element.addEventListener("cut", async (event: ClipboardEvent & { target: HTMLElement }) => {
window.siyuan.ctrlIsPressed = false; // https://github.com/siyuan-note/siyuan/issues/6373 window.siyuan.ctrlIsPressed = false; // https://github.com/siyuan-note/siyuan/issues/6373
if (protyle.disabled) { if (protyle.disabled) {
return; return;
@ -1758,20 +1783,28 @@ export class WYSIWYG {
} }
let html = ""; let html = "";
let textPlain = ""; let textPlain = "";
let isInCodeBlock = false;
let needClipboardWrite = false;
if (selectElements.length > 0) { if (selectElements.length > 0) {
if (selectElements[0].getAttribute("data-type") === "NodeListItem" && if (selectElements[0].getAttribute("data-type") === "NodeListItem" &&
selectElements[0].parentElement.classList.contains("list") && // 反链复制列表项 https://github.com/siyuan-note/siyuan/issues/6555 selectElements[0].parentElement.classList.contains("list") && // 反链复制列表项 https://github.com/siyuan-note/siyuan/issues/6555
selectElements[0].parentElement.childElementCount - 1 === selectElements.length) { selectElements[0].parentElement.childElementCount - 1 === selectElements.length) {
html = selectElements[0].parentElement.outerHTML; html = selectElements[0].parentElement.outerHTML;
} else { } else {
selectElements.forEach(item => { for (let i = 0; i < selectElements.length; i++) {
const item = selectElements[i];
const topElement = getTopAloneElement(item); const topElement = getTopAloneElement(item);
if (item.getAttribute("data-type") === "NodeHeading" && item.getAttribute("fold") === "1") { if (item.getAttribute("data-type") === "NodeHeading" && item.getAttribute("fold") === "1") {
html += removeEmbed(topElement).replace('fold="1"', ""); needClipboardWrite = true;
const response = await fetchSyncPost("/api/block/getHeadingChildrenDOM", {
id: item.getAttribute("data-node-id"),
removeFoldAttr: false
});
html += response.data;
} else { } else {
html += removeEmbed(topElement); html += removeEmbed(topElement);
} }
}); }
if (selectElements[0].getAttribute("data-type") === "NodeListItem") { if (selectElements[0].getAttribute("data-type") === "NodeListItem") {
html = `<div data-subtype="${selectElements[0].getAttribute("data-subtype")}" data-node-id="${Lute.NewNodeID()}" data-type="NodeList" class="list">${html}<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`; html = `<div data-subtype="${selectElements[0].getAttribute("data-subtype")}" data-node-id="${Lute.NewNodeID()}" data-type="NodeList" class="list">${html}<div class="protyle-attr" contenteditable="false">${Constants.ZWSP}</div></div>`;
} }
@ -1919,6 +1952,7 @@ export class WYSIWYG {
if (hasClosestByAttribute(range.startContainer, "data-type", "NodeCodeBlock") || if (hasClosestByAttribute(range.startContainer, "data-type", "NodeCodeBlock") ||
hasClosestByTag(range.startContainer, "CODE")) { hasClosestByTag(range.startContainer, "CODE")) {
textPlain = tempElement.textContent.replace(Constants.ZWSP, ""); textPlain = tempElement.textContent.replace(Constants.ZWSP, "");
isInCodeBlock = true;
} }
// https://github.com/siyuan-note/siyuan/issues/4321 // https://github.com/siyuan-note/siyuan/issues/4321
if (!nodeElement.classList.contains("table")) { if (!nodeElement.classList.contains("table")) {
@ -1950,14 +1984,25 @@ export class WYSIWYG {
textPlain = textPlain.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382 textPlain = textPlain.replace(/\u00A0/g, " "); // Replace non-breaking spaces with normal spaces when copying https://github.com/siyuan-note/siyuan/issues/9382
event.clipboardData.setData("text/plain", textPlain); event.clipboardData.setData("text/plain", textPlain);
// 设置 text/siyuan 数据 if (!isInCodeBlock) {
enableLuteMarkdownSyntax(protyle); enableLuteMarkdownSyntax(protyle);
const siyuanHTML = selectTableElement ? protyle.lute.HTML2BlockDOM(html) : html; const textSiyuan = selectTableElement ? protyle.lute.HTML2BlockDOM(html) : html;
event.clipboardData.setData("text/siyuan", siyuanHTML); restoreLuteMarkdownSyntax(protyle);
restoreLuteMarkdownSyntax(protyle); event.clipboardData.setData("text/siyuan", textSiyuan);
// 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据
// 在 text/html 中插入注释节点,用于右键菜单粘贴时获取 text/siyuan 数据 const textHTML = `<!--data-siyuan='${encodeBase64(textSiyuan)}'-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html));
event.clipboardData.setData("text/html", `<!--data-siyuan='${encodeBase64(siyuanHTML)}'-->` + (selectTableElement ? html : protyle.lute.BlockDOM2HTML(selectAVElement ? textPlain : html))); event.clipboardData.setData("text/html", textHTML);
if (needClipboardWrite) {
try {
await navigator.clipboard.write([new ClipboardItem({
["text/plain"]: textPlain,
["text/html"]: textHTML,
})]);
} catch (e) {
console.log("Cut write clipboard error:", e);
}
}
}
}); });
let beforeContextmenuRange: Range; let beforeContextmenuRange: Range;

View file

@ -37,6 +37,10 @@ export const input = async (protyle: IProtyle, blockElement: HTMLElement, range:
} else if (type === "NodeBlockQueryEmbed") { } else if (type === "NodeBlockQueryEmbed") {
blockElement.lastElementChild.previousElementSibling.innerHTML = "<wbr>" + Constants.ZWSP; blockElement.lastElementChild.previousElementSibling.innerHTML = "<wbr>" + Constants.ZWSP;
} else if (type === "NodeMathBlock" || type === "NodeHTMLBlock") { } else if (type === "NodeMathBlock" || type === "NodeHTMLBlock") {
// https://github.com/siyuan-note/siyuan/issues/15761
if (blockElement.firstElementChild.firstChild.nodeType === 3) {
blockElement.firstElementChild.firstChild.remove();
}
blockElement.lastElementChild.previousElementSibling.lastElementChild.innerHTML = "<wbr>" + Constants.ZWSP; blockElement.lastElementChild.previousElementSibling.lastElementChild.innerHTML = "<wbr>" + Constants.ZWSP;
} else if (type === "NodeIFrame" || type === "NodeWidget") { } else if (type === "NodeIFrame" || type === "NodeWidget") {
blockElement.innerHTML = "<wbr>" + blockElement.firstElementChild.outerHTML + blockElement.lastElementChild.outerHTML; blockElement.innerHTML = "<wbr>" + blockElement.firstElementChild.outerHTML + blockElement.lastElementChild.outerHTML;

View file

@ -855,15 +855,16 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
const cloneRange = range.cloneRange(); const cloneRange = range.cloneRange();
const nextElement = getNextBlock(getTopAloneElement(nodeElement)); const nextElement = getNextBlock(getTopAloneElement(nodeElement));
if (nextElement) { if (nextElement) {
if (!nodeElement.classList.contains("code-block")) { const nextRange = focusBlock(nextElement);
const nextRange = focusBlock(nextElement); if (nextRange) {
if (nextRange) { const nextBlockElement = hasClosestBlock(nextRange.startContainer);
const nextBlockElement = hasClosestBlock(nextRange.startContainer); if (nextBlockElement &&
if (nextBlockElement) { (!nextBlockElement.classList.contains("code-block") ||
// 反向删除合并为一个块时,光标应保持在尾部 https://github.com/siyuan-note/siyuan/issues/14290#issuecomment-2849810529 (nextBlockElement.classList.contains("code-block") && getContenteditableElement(nextBlockElement).textContent == "\n"))
cloneRange.insertNode(document.createElement("wbr")); ) {
removeBlock(protyle, nextBlockElement, nextRange, "Delete"); // 反向删除合并为一个块时,光标应保持在尾部 https://github.com/siyuan-note/siyuan/issues/14290#issuecomment-2849810529
} cloneRange.insertNode(document.createElement("wbr"));
removeBlock(protyle, nextBlockElement, nextRange, "Delete");
} }
} }
event.stopPropagation(); event.stopPropagation();
@ -912,7 +913,9 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
// 需使用 textContent文本元素没有 innerText // 需使用 textContent文本元素没有 innerText
currentNode.textContent === "") // https://ld246.com/article/1649251218696 currentNode.textContent === "") // https://ld246.com/article/1649251218696
)) { )) {
if (!nodeElement.classList.contains("code-block")) { if (!nodeElement.classList.contains("code-block") ||
(nodeElement.classList.contains("code-block") && editElement.textContent == "\n")
) {
removeBlock(protyle, nodeElement, range, "Backspace"); removeBlock(protyle, nodeElement, range, "Backspace");
} }
event.stopPropagation(); event.stopPropagation();

View file

@ -12,7 +12,7 @@ import {
import {transaction, turnsIntoOneTransaction, turnsIntoTransaction, updateTransaction} from "./transaction"; import {transaction, turnsIntoOneTransaction, turnsIntoTransaction, updateTransaction} from "./transaction";
import {cancelSB, genEmptyElement} from "../../block/util"; import {cancelSB, genEmptyElement} from "../../block/util";
import {listOutdent, updateListOrder} from "./list"; import {listOutdent, updateListOrder} from "./list";
import {setFold, zoomOut} from "../../menus/protyle"; import {zoomOut} from "../../menus/protyle";
import {preventScroll} from "../scroll/preventScroll"; import {preventScroll} from "../scroll/preventScroll";
import {hideElements} from "../ui/hideElements"; import {hideElements} from "../ui/hideElements";
import {Constants} from "../../constants"; import {Constants} from "../../constants";
@ -23,6 +23,7 @@ import {hasClosestByClassName} from "../util/hasClosest";
import {getInstanceById} from "../../layout/util"; import {getInstanceById} from "../../layout/util";
import {Tab} from "../../layout/Tab"; import {Tab} from "../../layout/Tab";
import {Backlink} from "../../layout/dock/Backlink"; import {Backlink} from "../../layout/dock/Backlink";
import {fetchSyncPost} from "../../util/fetch";
export const removeBlock = async (protyle: IProtyle, blockElement: Element, range: Range, type: "Delete" | "Backspace" | "remove") => { export const removeBlock = async (protyle: IProtyle, blockElement: Element, range: Range, type: "Delete" | "Backspace" | "remove") => {
protyle.observerLoad?.disconnect(); protyle.observerLoad?.disconnect();
@ -32,7 +33,7 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang
if (selectElements?.length > 0) { if (selectElements?.length > 0) {
const deletes: IOperation[] = []; const deletes: IOperation[] = [];
const inserts: IOperation[] = []; const inserts: IOperation[] = [];
let sideElement; let sideElement: Element | boolean;
let sideIsNext = false; let sideIsNext = false;
if (type === "Backspace") { if (type === "Backspace") {
sideElement = selectElements[0].previousElementSibling; sideElement = selectElements[0].previousElementSibling;
@ -52,7 +53,8 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang
let topParentElement: Element; let topParentElement: Element;
hideElements(["select"], protyle); hideElements(["select"], protyle);
let foldPreviousId: string; let foldPreviousId: string;
selectElements.find((item: HTMLElement) => { for (let i = 0; i < selectElements.length; i++) {
const item = selectElements[i];
const topElement = getTopAloneElement(item); const topElement = getTopAloneElement(item);
topParentElement = topElement.parentElement; topParentElement = topElement.parentElement;
const id = topElement.getAttribute("data-node-id"); const id = topElement.getAttribute("data-node-id");
@ -79,19 +81,23 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang
sideIsNext = false; sideIsNext = false;
} }
if (topElement.getAttribute("data-type") === "NodeHeading" && topElement.getAttribute("fold") === "1") { if (topElement.getAttribute("data-type") === "NodeHeading" && topElement.getAttribute("fold") === "1") {
// https://github.com/siyuan-note/siyuan/issues/2188 const foldTransaction = await fetchSyncPost("/api/block/getHeadingDeleteTransaction", {
setFold(protyle, topElement, undefined, true); id: topElement.getAttribute("data-node-id"),
});
deletes.push(...foldTransaction.data.doOperations.slice(1));
let previousID = topElement.previousElementSibling ? topElement.previousElementSibling.getAttribute("data-node-id") : ""; let previousID = topElement.previousElementSibling ? topElement.previousElementSibling.getAttribute("data-node-id") : "";
if (typeof foldPreviousId !== "undefined") { if (typeof foldPreviousId !== "undefined") {
previousID = foldPreviousId; previousID = foldPreviousId;
} }
inserts.push({ foldTransaction.data.undoOperations.forEach((operationItem: IOperation, index: number) => {
action: "insert", operationItem.previousID = previousID;
data: topElement.outerHTML, if (index > 0) {
id, operationItem.context = {
previousID: previousID, ignoreProcess: "true"
parentID: topElement.parentElement.getAttribute("data-node-id") || protyle.block.parentID };
}
}); });
inserts.push(...foldTransaction.data.undoOperations);
// 折叠块和非折叠块同时删除时撤销异常 https://github.com/siyuan-note/siyuan/issues/11312 // 折叠块和非折叠块同时删除时撤销异常 https://github.com/siyuan-note/siyuan/issues/11312
let foldPreviousElement = getPreviousBlock(topElement); let foldPreviousElement = getPreviousBlock(topElement);
while (foldPreviousElement && foldPreviousElement.childElementCount === 3) { while (foldPreviousElement && foldPreviousElement.childElementCount === 3) {
@ -104,15 +110,7 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang
} }
// https://github.com/siyuan-note/siyuan/issues/4422 // https://github.com/siyuan-note/siyuan/issues/4422
topElement.firstElementChild.removeAttribute("contenteditable"); topElement.firstElementChild.removeAttribute("contenteditable");
// 在折叠标题后输入文字,然后全选删除再撤销会重建索引。因此不能删除折叠标题后新输入的输入折叠标题下的内容 topElement.remove();
const nextElement = topElement.nextElementSibling;
if (nextElement) {
const nextType = nextElement.getAttribute("data-type");
if (nextType !== "NodeHeading" ||
(nextType === "NodeHeading" && nextElement.getAttribute("data-subtype") > topElement.getAttribute("data-subtype"))) {
return true;
}
}
} else { } else {
let data = topElement.outerHTML; // 不能 spin ,否则 li 会变为 list let data = topElement.outerHTML; // 不能 spin ,否则 li 会变为 list
if (topElement.classList.contains("render-node") || topElement.querySelector("div.render-node")) { if (topElement.classList.contains("render-node") || topElement.querySelector("div.render-node")) {
@ -136,7 +134,7 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang
} }
topElement.remove(); topElement.remove();
} }
}); }
if (sideElement) { if (sideElement) {
if (protyle.block.showAll && sideElement.classList.contains("protyle-wysiwyg") && protyle.wysiwyg.element.childElementCount === 0) { if (protyle.block.showAll && sideElement.classList.contains("protyle-wysiwyg") && protyle.wysiwyg.element.childElementCount === 0) {
setTimeout(() => { setTimeout(() => {
@ -164,11 +162,11 @@ export const removeBlock = async (protyle: IProtyle, blockElement: Element, rang
// https://github.com/siyuan-note/siyuan/issues/10389 // https://github.com/siyuan-note/siyuan/issues/10389
// https://github.com/siyuan-note/siyuan/issues/10899 // https://github.com/siyuan-note/siyuan/issues/10899
if (type !== "Backspace" && sideIsNext) { if (type !== "Backspace" && sideIsNext) {
focusBlock(sideElement); focusBlock(sideElement as Element);
} else { } else {
focusBlock(sideElement, undefined, false); focusBlock(sideElement as Element, undefined, false);
} }
scrollCenter(protyle, sideElement); scrollCenter(protyle, sideElement as Element);
if (listElement) { if (listElement) {
inserts.push({ inserts.push({
action: "update", action: "update",

View file

@ -754,6 +754,9 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo:
return; return;
} }
if (operation.action === "insert") { if (operation.action === "insert") {
if (operation.context?.ignoreProcess === "true") {
return;
}
const cursorElements = []; const cursorElements = [];
if (operation.previousID) { if (operation.previousID) {
const previousElement = protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${operation.previousID}"]`); const previousElement = protyle.wysiwyg.element.querySelectorAll(`[data-node-id="${operation.previousID}"]`);

View file

@ -64,7 +64,7 @@ declare namespace Config {
*/ */
openHelp: boolean; openHelp: boolean;
/** /**
* Publishing service * Publish service
* *
*/ */
publish: IPublish; publish: IPublish;
@ -1078,29 +1078,29 @@ declare namespace Config {
export type TLogLevel = "off" | "trace" | "debug" | "info" | "warn" | "error" | "fatal"; export type TLogLevel = "off" | "trace" | "debug" | "info" | "warn" | "error" | "fatal";
/** /**
* Publishing service * Publish service
*/ */
export interface IPublish { export interface IPublish {
/** /**
* Whether to open the publishing service * Whether to open the publish service
*/ */
enable: boolean; enable: boolean;
/** /**
* The basic authentication settings of publishing service * The basic authentication settings of publish service
*/ */
auth: IPublishAuth; auth: IPublishAuth;
/** /**
* Port on which the publishing service listens * Port on which the publish service listens
*/ */
port: number; port: number;
} }
/** /**
* Publishing service authentication settings * Publish service authentication settings
*/ */
export interface IPublishAuth { export interface IPublishAuth {
/** /**
* Whether to enable basic authentication for publishing services * Whether to enable basic authentication for publish services
*/ */
enable: boolean; enable: boolean;
/** /**

View file

@ -369,6 +369,7 @@ interface ISnippet {
type: string; type: string;
enabled: boolean; enabled: boolean;
content: string; content: string;
disabledInPublish: boolean;
} }
interface IInbox { interface IInbox {
@ -897,6 +898,7 @@ interface IAVGallery extends IAVView {
interface IAVFilter { interface IAVFilter {
column: string, column: string,
operator: TAVFilterOperator, operator: TAVFilterOperator,
quantifier?: string,
value: IAVCellValue, value: IAVCellValue,
relativeDate?: relativeDate relativeDate?: relativeDate
relativeDate2?: relativeDate relativeDate2?: relativeDate

View file

@ -455,6 +455,7 @@ interface IProtyleOptions {
render?: { render?: {
background?: boolean background?: boolean
title?: boolean title?: boolean
titleShowTop?: boolean
gutter?: boolean gutter?: boolean
scroll?: boolean scroll?: boolean
breadcrumb?: boolean breadcrumb?: boolean

View file

@ -104,6 +104,10 @@ export const objEquals = (a: any, b: any): boolean => {
}; };
export const duplicateNameAddOne = (name:string) => { export const duplicateNameAddOne = (name:string) => {
if (!name) {
return "";
}
const nameMatch = name.match(/^(.*) \((\d+)\)$/); const nameMatch = name.match(/^(.*) \((\d+)\)$/);
if (nameMatch) { if (nameMatch) {
name = `${nameMatch[1]} (${parseInt(nameMatch[2]) + 1})`; name = `${nameMatch[1]} (${parseInt(nameMatch[2]) + 1})`;

View file

@ -249,10 +249,13 @@ export const newFileBySelect = (protyle: IProtyle, selectText: string, nodeEleme
}, (idResponse) => { }, (idResponse) => {
const refText = newFileName.substring(0, window.siyuan.config.editor.blockRefDynamicAnchorTextMaxLen); const refText = newFileName.substring(0, window.siyuan.config.editor.blockRefDynamicAnchorTextMaxLen);
if (idResponse.data && idResponse.data.length > 0) { if (idResponse.data && idResponse.data.length > 0) {
protyle.toolbar.setInlineMark(protyle, "block-ref", "range", { const refElement = protyle.toolbar.setInlineMark(protyle, "block-ref", "range", {
type: "id", type: "id",
color: `${idResponse.data[0]}${Constants.ZWSP}d${Constants.ZWSP}${refText}` color: `${idResponse.data[0]}${Constants.ZWSP}d${Constants.ZWSP}${refText}`
}); });
if (refElement[0]) {
protyle.toolbar.range.selectNodeContents(refElement[0]);
}
} else { } else {
fetchPost("/api/filetree/createDocWithMd", { fetchPost("/api/filetree/createDocWithMd", {
notebook: targetNotebookId, notebook: targetNotebookId,
@ -260,10 +263,13 @@ export const newFileBySelect = (protyle: IProtyle, selectText: string, nodeEleme
parentID: protyle.notebookId === targetNotebookId ? protyle.block.rootID : "", parentID: protyle.notebookId === targetNotebookId ? protyle.block.rootID : "",
markdown: "" markdown: ""
}, response => { }, response => {
protyle.toolbar.setInlineMark(protyle, "block-ref", "range", { const refElement = protyle.toolbar.setInlineMark(protyle, "block-ref", "range", {
type: "id", type: "id",
color: `${response.data}${Constants.ZWSP}d${Constants.ZWSP}${refText}` color: `${response.data}${Constants.ZWSP}d${Constants.ZWSP}${refText}`
}); });
if (refElement[0]) {
protyle.toolbar.range.selectNodeContents(refElement[0]);
}
}); });
} }
hideElements(["toolbar"], protyle); hideElements(["toolbar"], protyle);

View file

@ -1,5 +1,5 @@
const isNormalItem = (currentHintElement: HTMLElement, className: string) => { export const isAbnormalItem = (currentHintElement: HTMLElement, className: string) => {
return !currentHintElement.classList.contains(className) || currentHintElement.getBoundingClientRect().height === 0; return !currentHintElement || !currentHintElement.classList.contains(className) || currentHintElement.getBoundingClientRect().height === 0;
}; };
export const upDownHint = (listElement: Element, event: KeyboardEvent, classActiveName = "b3-list-item--focus", defaultElement?: Element) => { export const upDownHint = (listElement: Element, event: KeyboardEvent, classActiveName = "b3-list-item--focus", defaultElement?: Element) => {
@ -19,13 +19,13 @@ export const upDownHint = (listElement: Element, event: KeyboardEvent, classActi
currentHintElement.classList.remove(classActiveName); currentHintElement.classList.remove(classActiveName);
currentHintElement = currentHintElement.nextElementSibling as HTMLElement; currentHintElement = currentHintElement.nextElementSibling as HTMLElement;
while (currentHintElement && isNormalItem(currentHintElement, className)) { while (isAbnormalItem(currentHintElement, className)) {
currentHintElement = currentHintElement.nextElementSibling as HTMLElement; currentHintElement = currentHintElement.nextElementSibling as HTMLElement;
} }
if (!currentHintElement) { if (!currentHintElement) {
currentHintElement = listElement.children[0] as HTMLElement; currentHintElement = listElement.children[0] as HTMLElement;
while (currentHintElement && isNormalItem(currentHintElement, className)) { while (isAbnormalItem(currentHintElement, className)) {
currentHintElement = currentHintElement.nextElementSibling as HTMLElement; currentHintElement = currentHintElement.nextElementSibling as HTMLElement;
} }
} }
@ -44,7 +44,7 @@ export const upDownHint = (listElement: Element, event: KeyboardEvent, classActi
currentHintElement.classList.remove(classActiveName); currentHintElement.classList.remove(classActiveName);
currentHintElement = currentHintElement.previousElementSibling as HTMLElement; currentHintElement = currentHintElement.previousElementSibling as HTMLElement;
while (currentHintElement && isNormalItem(currentHintElement, className)) { while (isAbnormalItem(currentHintElement, className)) {
currentHintElement = currentHintElement.previousElementSibling as HTMLElement; currentHintElement = currentHintElement.previousElementSibling as HTMLElement;
} }
@ -70,7 +70,7 @@ export const upDownHint = (listElement: Element, event: KeyboardEvent, classActi
event.stopPropagation(); event.stopPropagation();
currentHintElement.classList.remove(classActiveName); currentHintElement.classList.remove(classActiveName);
currentHintElement = listElement.children[0] as HTMLElement; currentHintElement = listElement.children[0] as HTMLElement;
while (currentHintElement && isNormalItem(currentHintElement, className)) { while (isAbnormalItem(currentHintElement, className)) {
currentHintElement = currentHintElement.nextElementSibling as HTMLElement; currentHintElement = currentHintElement.nextElementSibling as HTMLElement;
} }
if (!currentHintElement) { if (!currentHintElement) {
@ -84,7 +84,7 @@ export const upDownHint = (listElement: Element, event: KeyboardEvent, classActi
event.stopPropagation(); event.stopPropagation();
currentHintElement.classList.remove(classActiveName); currentHintElement.classList.remove(classActiveName);
currentHintElement = listElement.children[listElement.children.length - 1] as HTMLElement; currentHintElement = listElement.children[listElement.children.length - 1] as HTMLElement;
while (currentHintElement && isNormalItem(currentHintElement, className)) { while (isAbnormalItem(currentHintElement, className)) {
currentHintElement = currentHintElement.previousElementSibling as HTMLElement; currentHintElement = currentHintElement.previousElementSibling as HTMLElement;
} }
if (!currentHintElement) { if (!currentHintElement) {

File diff suppressed because one or more lines are too long

View file

@ -189,6 +189,20 @@ func getHeadingChildrenIDs(c *gin.Context) {
ret.Data = ids ret.Data = ids
} }
func appendHeadingChildren(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
id := arg["id"].(string)
childrenDOM := arg["childrenDOM"].(string)
model.AppendHeadingChildren(id, childrenDOM)
}
func getHeadingChildrenDOM(c *gin.Context) { func getHeadingChildrenDOM(c *gin.Context) {
ret := gulu.Ret.NewResult() ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret) defer c.JSON(http.StatusOK, ret)
@ -199,7 +213,11 @@ func getHeadingChildrenDOM(c *gin.Context) {
} }
id := arg["id"].(string) id := arg["id"].(string)
dom := model.GetHeadingChildrenDOM(id) removeFoldAttr := true
if nil != arg["removeFoldAttr"] {
removeFoldAttr = arg["removeFoldAttr"].(bool)
}
dom := model.GetHeadingChildrenDOM(id, removeFoldAttr)
ret.Data = dom ret.Data = dom
} }

View file

@ -154,7 +154,7 @@ func extensionCopy(c *gin.Context) {
fName += ext fName += ext
} }
fName = util.AssetName(fName) fName = util.AssetName(fName, ast.NewNodeID())
writePath := filepath.Join(assets, fName) writePath := filepath.Join(assets, fName)
if err = filelock.WriteFile(writePath, data); err != nil { if err = filelock.WriteFile(writePath, data); err != nil {
ret.Code = -1 ret.Code = -1

View file

@ -128,7 +128,7 @@ func listDocTree(c *gin.Context) {
doctree = append(doctree, parent) doctree = append(doctree, parent)
subPath := filepath.Join(root, entry.Name()) subPath := filepath.Join(root, entry.Name())
if err = walkDocTree(subPath, parent, &ids); err != nil { if err = walkDocTree(subPath, parent, ids); err != nil {
ret.Code = -1 ret.Code = -1
ret.Msg = err.Error() ret.Msg = err.Error()
return return
@ -152,7 +152,7 @@ type DocFile struct {
Children []*DocFile `json:"children,omitempty"` Children []*DocFile `json:"children,omitempty"`
} }
func walkDocTree(p string, docFile *DocFile, ids *map[string]bool) (err error) { func walkDocTree(p string, docFile *DocFile, ids map[string]bool) (err error) {
dir, err := os.ReadDir(p) dir, err := os.ReadDir(p)
if err != nil { if err != nil {
return return
@ -169,7 +169,7 @@ func walkDocTree(p string, docFile *DocFile, ids *map[string]bool) (err error) {
} }
parent := &DocFile{ID: entry.Name()} parent := &DocFile{ID: entry.Name()}
(*ids)[parent.ID] = true ids[parent.ID] = true
docFile.Children = append(docFile.Children, parent) docFile.Children = append(docFile.Children, parent)
subPath := filepath.Join(p, entry.Name()) subPath := filepath.Join(p, entry.Name())
@ -178,10 +178,10 @@ func walkDocTree(p string, docFile *DocFile, ids *map[string]bool) (err error) {
} }
} else { } else {
doc := &DocFile{ID: strings.TrimSuffix(entry.Name(), ".sy")} doc := &DocFile{ID: strings.TrimSuffix(entry.Name(), ".sy")}
if !(*ids)[doc.ID] { if !ids[doc.ID] {
docFile.Children = append(docFile.Children, doc) docFile.Children = append(docFile.Children, doc)
} }
(*ids)[doc.ID] = true ids[doc.ID] = true
} }
} }
return return

View file

@ -35,9 +35,9 @@ func loadPetals(c *gin.Context) {
} }
frontend := arg["frontend"].(string) frontend := arg["frontend"].(string)
isPublish := model.IsReadOnlyRole(model.GetGinContextRole(c))
petals := model.LoadPetals(frontend) ret.Data = model.LoadPetals(frontend, isPublish)
ret.Data = petals
} }
func setPetalEnabled(c *gin.Context) { func setPetalEnabled(c *gin.Context) {

View file

@ -222,6 +222,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/block/getBlockRelevantIDs", model.CheckAuth, getBlockRelevantIDs) ginServer.Handle("POST", "/api/block/getBlockRelevantIDs", model.CheckAuth, getBlockRelevantIDs)
ginServer.Handle("POST", "/api/block/getBlockTreeInfos", model.CheckAuth, getBlockTreeInfos) ginServer.Handle("POST", "/api/block/getBlockTreeInfos", model.CheckAuth, getBlockTreeInfos)
ginServer.Handle("POST", "/api/block/checkBlockRef", model.CheckAuth, checkBlockRef) ginServer.Handle("POST", "/api/block/checkBlockRef", model.CheckAuth, checkBlockRef)
ginServer.Handle("POST", "/api/block/appendHeadingChildren", model.CheckAuth, appendHeadingChildren)
ginServer.Handle("POST", "/api/file/getFile", model.CheckAuth, getFile) ginServer.Handle("POST", "/api/file/getFile", model.CheckAuth, getFile)
ginServer.Handle("POST", "/api/file/putFile", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, putFile) ginServer.Handle("POST", "/api/file/putFile", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, putFile)

View file

@ -55,11 +55,20 @@ func getSnippet(c *gin.Context) {
return return
} }
isPublish := model.IsReadOnlyRole(model.GetGinContextRole(c))
var snippets []*conf.Snippet var snippets []*conf.Snippet
for _, s := range confSnippets { for _, s := range confSnippets {
if ("all" == typ || s.Type == typ) && (2 == enabledArg || s.Enabled == enabled) { if isPublish && s.DisabledInPublish {
snippets = append(snippets, s) continue
} }
if "all" != typ && s.Type != typ {
continue
}
if 2 != enabledArg && s.Enabled != enabled {
continue
}
snippets = append(snippets, s)
} }
if "" != keyword { if "" != keyword {
@ -101,6 +110,9 @@ func setSnippet(c *gin.Context) {
Content: m["content"].(string), Content: m["content"].(string),
Enabled: m["enabled"].(bool), Enabled: m["enabled"].(bool),
} }
if nil != m["disabledInPublish"] {
snippet.DisabledInPublish = m["disabledInPublish"].(bool)
}
if "" == snippet.ID { if "" == snippet.ID {
snippet.ID = ast.NewNodeID() snippet.ID = ast.NewNodeID()
} }

View file

@ -42,6 +42,8 @@ type AttributeView struct {
KeyIDs []string `json:"keyIDs"` // 属性视图属性键 ID用于排序 KeyIDs []string `json:"keyIDs"` // 属性视图属性键 ID用于排序
ViewID string `json:"viewID"` // 当前视图 ID ViewID string `json:"viewID"` // 当前视图 ID
Views []*View `json:"views"` // 视图 Views []*View `json:"views"` // 视图
RenderedViewables map[string]Viewable `json:"-"` // 已经渲染好的视图
} }
// KeyValues 描述了属性视图属性键值列表的结构。 // KeyValues 描述了属性视图属性键值列表的结构。
@ -428,7 +430,7 @@ func ParseAttributeView(avID string) (ret *AttributeView, err error) {
return return
} }
ret = &AttributeView{} ret = &AttributeView{RenderedViewables: map[string]Viewable{}}
if err = gulu.JSON.UnmarshalJSON(data, ret); err != nil { if err = gulu.JSON.UnmarshalJSON(data, ret); err != nil {
if strings.Contains(err.Error(), ".relation.contents of type av.Value") { if strings.Contains(err.Error(), ".relation.contents of type av.Value") {
mapAv := map[string]interface{}{} mapAv := map[string]interface{}{}

View file

@ -26,11 +26,12 @@ import (
// ViewFilter 描述了视图过滤规则的结构。 // ViewFilter 描述了视图过滤规则的结构。
type ViewFilter struct { type ViewFilter struct {
Column string `json:"column"` // 列字段ID Column string `json:"column"` // 列字段ID
Operator FilterOperator `json:"operator"` // 过滤操作符 Qualifier FilterQuantifier `json:"quantifier,omitempty"` // 量词
Value *Value `json:"value"` // 过滤值 Operator FilterOperator `json:"operator"` // 操作符
RelativeDate *RelativeDate `json:"relativeDate,omitempty"` // 相对时间 Value *Value `json:"value"` // 过滤值
RelativeDate2 *RelativeDate `json:"relativeDate2,omitempty"` // 第二个相对时间,用于某些操作符,比如 FilterOperatorIsBetween RelativeDate *RelativeDate `json:"relativeDate,omitempty"` // 相对时间
RelativeDate2 *RelativeDate `json:"relativeDate2,omitempty"` // 第二个相对时间,用于某些操作符,比如 FilterOperatorIsBetween
} }
type RelativeDateUnit int type RelativeDateUnit int
@ -76,7 +77,16 @@ const (
FilterOperatorIsFalse FilterOperator = "Is false" FilterOperatorIsFalse FilterOperator = "Is false"
) )
func Filter(viewable Viewable, attrView *AttributeView) { type FilterQuantifier string
const (
FilterQuantifierUndefined FilterQuantifier = "" // 等同于 Any
FilterQuantifierAny FilterQuantifier = "Any"
FilterQuantifierAll FilterQuantifier = "All"
FilterQuantifierNone FilterQuantifier = "None"
)
func Filter(viewable Viewable, attrView *AttributeView, rollupFurtherCollections map[string]Collection, cachedAttrViews map[string]*AttributeView) {
collection := viewable.(Collection) collection := viewable.(Collection)
filters := collection.GetFilters() filters := collection.GetFilters()
if 1 > len(filters) { if 1 > len(filters) {
@ -94,8 +104,6 @@ func Filter(viewable Viewable, attrView *AttributeView) {
} }
var items []Item var items []Item
attrViewCache := map[string]*AttributeView{}
attrViewCache[attrView.ID] = attrView
for _, item := range collection.GetItems() { for _, item := range collection.GetItems() {
pass := true pass := true
values := item.GetValues() values := item.GetValues()
@ -116,7 +124,7 @@ func Filter(viewable Viewable, attrView *AttributeView) {
break break
} }
if !values[index].Filter(filters[j], attrView, item.GetID(), &attrViewCache) { if !values[index].Filter(filters[j], attrView, item.GetID(), rollupFurtherCollections, cachedAttrViews) {
pass = false pass = false
break break
} }
@ -128,7 +136,7 @@ func Filter(viewable Viewable, attrView *AttributeView) {
collection.SetItems(items) collection.SetItems(items)
} }
func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, rowID string, attrViewCache *map[string]*AttributeView) bool { func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, itemID string, rollupFurtherCollections map[string]Collection, cachedAttrViews map[string]*AttributeView) bool {
if nil == filter || (nil == filter.Value && nil == filter.RelativeDate) { if nil == filter || (nil == filter.Value && nil == filter.RelativeDate) {
return true return true
} }
@ -149,7 +157,6 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, rowID st
nil != filter.Value.Rollup && 0 < len(filter.Value.Rollup.Contents) { nil != filter.Value.Rollup && 0 < len(filter.Value.Rollup.Contents) {
// 单独处理汇总类型的比较 // 单独处理汇总类型的比较
// 处理值比较
key, _ := attrView.GetKey(value.KeyID) key, _ := attrView.GetKey(value.KeyID)
if nil == key { if nil == key {
return false return false
@ -160,16 +167,16 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, rowID st
return false return false
} }
relVal := attrView.GetValue(relKey.ID, rowID) relVal := attrView.GetValue(relKey.ID, itemID)
if nil == relVal || nil == relVal.Relation { if nil == relVal || nil == relVal.Relation {
return false return false
} }
destAv := (*attrViewCache)[relKey.Relation.AvID] destAv := cachedAttrViews[relKey.Relation.AvID]
if nil == destAv { if nil == destAv {
destAv, _ = ParseAttributeView(relKey.Relation.AvID) destAv, _ = ParseAttributeView(relKey.Relation.AvID)
if nil != destAv { if nil != destAv {
(*attrViewCache)[relKey.Relation.AvID] = destAv cachedAttrViews[relKey.Relation.AvID] = destAv
} }
} }
if nil == destAv { if nil == destAv {
@ -181,32 +188,29 @@ func (value *Value) Filter(filter *ViewFilter, attrView *AttributeView, rowID st
return false return false
} }
value.Rollup.BuildContents(destAv.KeyValues, destKey, relVal, key.Rollup.Calc, nil) value.Rollup.BuildContents(destAv.KeyValues, destKey, relVal, key.Rollup.Calc, rollupFurtherCollections[key.ID])
for _, content := range value.Rollup.Contents {
switch filter.Operator { switch filter.Qualifier {
case FilterOperatorContains: case FilterQuantifierUndefined, FilterQuantifierAny:
if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) { for _, content := range value.Rollup.Contents {
return true
}
case FilterOperatorDoesNotContain:
ret := content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator)
if !ret {
return false
}
default:
if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) { if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
return true return true
} }
} }
} case FilterQuantifierAll:
for _, content := range value.Rollup.Contents {
switch filter.Operator { if !content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
case FilterOperatorContains: return false
return false }
case FilterOperatorDoesNotContain: }
return true
case FilterQuantifierNone:
for _, content := range value.Rollup.Contents {
if content.filter(filter.Value.Rollup.Contents[0], filter.RelativeDate, filter.RelativeDate2, filter.Operator) {
return false
}
}
return true return true
default:
return false
} }
} }
@ -523,17 +527,17 @@ func filterRelativeTime(valueMills int64, valueIsNotEmpty bool, operator FilterO
switch operator { switch operator {
case FilterOperatorIsEqual: case FilterOperatorIsEqual:
return (valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart)) && valueTime.Before(otherValueEnd) return (valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart)) && (valueTime.Before(otherValueEnd) || valueTime.Equal(otherValueEnd))
case FilterOperatorIsNotEqual: case FilterOperatorIsNotEqual:
return valueTime.Before(otherValueStart) || valueTime.After(otherValueEnd) return valueTime.Before(otherValueStart) || valueTime.After(otherValueEnd)
case FilterOperatorIsGreater: case FilterOperatorIsGreater:
return valueTime.After(otherValueStart) return valueTime.After(otherValueEnd)
case FilterOperatorIsGreaterOrEqual: case FilterOperatorIsGreaterOrEqual:
return valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart) return valueTime.After(otherValueStart) || valueTime.Equal(otherValueStart)
case FilterOperatorIsLess: case FilterOperatorIsLess:
return valueTime.Before(otherValueStart) return valueTime.Before(otherValueStart)
case FilterOperatorIsLessOrEqual: case FilterOperatorIsLessOrEqual:
return valueTime.Before(otherValueStart) || valueTime.Equal(otherValueStart) return valueTime.Before(otherValueEnd) || valueTime.Equal(otherValueEnd)
case FilterOperatorIsBetween: case FilterOperatorIsBetween:
if RelativeDateDirectionBefore == direction { if RelativeDateDirectionBefore == direction {
if RelativeDateDirectionBefore == direction2 { if RelativeDateDirectionBefore == direction2 {

View file

@ -673,7 +673,7 @@ func Round(val float64, precision int) float64 {
type ValueSelect struct { type ValueSelect struct {
Content string `json:"content"` Content string `json:"content"`
Color string `json:"color"` Color string `json:"color"` // 1-14
} }
func MSelectExistOption(mSelect []*ValueSelect, opt string) bool { func MSelectExistOption(mSelect []*ValueSelect, opt string) bool {

View file

@ -51,7 +51,7 @@ type DisplayName struct {
ItIT string `json:"it_IT"` ItIT string `json:"it_IT"`
JaJP string `json:"ja_JP"` JaJP string `json:"ja_JP"`
PlPL string `json:"pl_PL"` PlPL string `json:"pl_PL"`
ptBR string `json:"pt_BR"` PtBR string `json:"pt_BR"`
RuRU string `json:"ru_RU"` RuRU string `json:"ru_RU"`
ZhCHT string `json:"zh_CHT"` ZhCHT string `json:"zh_CHT"`
ZhCN string `json:"zh_CN"` ZhCN string `json:"zh_CN"`
@ -68,7 +68,7 @@ type Description struct {
ItIT string `json:"it_IT"` ItIT string `json:"it_IT"`
JaJP string `json:"ja_JP"` JaJP string `json:"ja_JP"`
PlPL string `json:"pl_PL"` PlPL string `json:"pl_PL"`
ptBR string `json:"pt_BR"` PtBR string `json:"pt_BR"`
RuRU string `json:"ru_RU"` RuRU string `json:"ru_RU"`
ZhCHT string `json:"zh_CHT"` ZhCHT string `json:"zh_CHT"`
ZhCN string `json:"zh_CN"` ZhCN string `json:"zh_CN"`
@ -85,7 +85,7 @@ type Readme struct {
ItIT string `json:"it_IT"` ItIT string `json:"it_IT"`
JaJP string `json:"ja_JP"` JaJP string `json:"ja_JP"`
PlPL string `json:"pl_PL"` PlPL string `json:"pl_PL"`
ptBR string `json:"pt_BR"` PtBR string `json:"pt_BR"`
RuRU string `json:"ru_RU"` RuRU string `json:"ru_RU"`
ZhCHT string `json:"zh_CHT"` ZhCHT string `json:"zh_CHT"`
ZhCN string `json:"zh_CN"` ZhCN string `json:"zh_CN"`
@ -99,17 +99,18 @@ type Funding struct {
} }
type Package struct { type Package struct {
Author string `json:"author"` Author string `json:"author"`
URL string `json:"url"` URL string `json:"url"`
Version string `json:"version"` Version string `json:"version"`
MinAppVersion string `json:"minAppVersion"` MinAppVersion string `json:"minAppVersion"`
Backends []string `json:"backends"` DisabledInPublish bool `json:"disabledInPublish"`
Frontends []string `json:"frontends"` Backends []string `json:"backends"`
DisplayName *DisplayName `json:"displayName"` Frontends []string `json:"frontends"`
Description *Description `json:"description"` DisplayName *DisplayName `json:"displayName"`
Readme *Readme `json:"readme"` Description *Description `json:"description"`
Funding *Funding `json:"funding"` Readme *Readme `json:"readme"`
Keywords []string `json:"keywords"` Funding *Funding `json:"funding"`
Keywords []string `json:"keywords"`
PreferredFunding string `json:"preferredFunding"` PreferredFunding string `json:"preferredFunding"`
PreferredName string `json:"preferredName"` PreferredName string `json:"preferredName"`
@ -209,8 +210,8 @@ func getPreferredReadme(readme *Readme) string {
ret = readme.PlPL ret = readme.PlPL
} }
case "pt_BR": case "pt_BR":
if "" != readme.ptBR { if "" != readme.PtBR {
ret = readme.ptBR ret = readme.PtBR
} }
case "ru_RU": case "ru_RU":
if "" != readme.RuRU { if "" != readme.RuRU {
@ -279,8 +280,8 @@ func GetPreferredName(pkg *Package) string {
ret = pkg.DisplayName.PlPL ret = pkg.DisplayName.PlPL
} }
case "pt_BR": case "pt_BR":
if "" != pkg.DisplayName.ptBR { if "" != pkg.DisplayName.PtBR {
ret = pkg.DisplayName.ptBR ret = pkg.DisplayName.PtBR
} }
case "ru_RU": case "ru_RU":
if "" != pkg.DisplayName.RuRU { if "" != pkg.DisplayName.RuRU {
@ -349,8 +350,8 @@ func getPreferredDesc(desc *Description) string {
ret = desc.PlPL ret = desc.PlPL
} }
case "pt_BR": case "pt_BR":
if "" != desc.ptBR { if "" != desc.PtBR {
ret = desc.ptBR ret = desc.PtBR
} }
case "ru_RU": case "ru_RU":
if "" != desc.RuRU { if "" != desc.RuRU {
@ -875,9 +876,10 @@ func getBazaarIndex() map[string]*bazaarPackage {
const defaultMinAppVersion = "2.9.0" const defaultMinAppVersion = "2.9.0"
func disallowDisplayBazaarPackage(pkg *Package) bool { func disallowDisplayBazaarPackage(pkg *Package) bool {
if "" == pkg.MinAppVersion { // TODO: 目前暂时放过所有不带 minAppVersion 的集市包,后续版本会使用 defaultMinAppVersion if "" == pkg.MinAppVersion {
return false pkg.MinAppVersion = defaultMinAppVersion
} }
if 0 < semver.Compare("v"+pkg.MinAppVersion, "v"+util.Ver) { if 0 < semver.Compare("v"+pkg.MinAppVersion, "v"+util.Ver) {
return true return true
} }

View file

@ -134,7 +134,7 @@ func Plugins(frontend string) (plugins []*Plugin) {
return return
} }
func ParseInstalledPlugin(name, frontend string) (found bool, displayName string, incompatible bool) { func ParseInstalledPlugin(name, frontend string) (found bool, displayName string, incompatible, disabledInPublish bool) {
pluginsPath := filepath.Join(util.DataDir, "plugins") pluginsPath := filepath.Join(util.DataDir, "plugins")
if !util.IsPathRegularDirOrSymlinkDir(pluginsPath) { if !util.IsPathRegularDirOrSymlinkDir(pluginsPath) {
return return
@ -163,6 +163,7 @@ func ParseInstalledPlugin(name, frontend string) (found bool, displayName string
found = true found = true
displayName = GetPreferredName(plugin.Package) displayName = GetPreferredName(plugin.Package)
incompatible = isIncompatiblePlugin(plugin, frontend) incompatible = isIncompatiblePlugin(plugin, frontend)
disabledInPublish = plugin.DisabledInPublish
} }
return return
} }

View file

@ -29,9 +29,10 @@ func NewSnpt() *Snpt {
} }
type Snippet struct { type Snippet struct {
ID string `json:"id"` ID string `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Type string `json:"type"` // js/css Type string `json:"type"` // js/css
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
Content string `json:"content"` DisabledInPublish bool `json:"disabledInPublish"`
Content string `json:"content"`
} }

View file

@ -8,7 +8,7 @@ require (
github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48 github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48
github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7 github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7
github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689 github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689
github.com/88250/lute v1.7.7-0.20250828030734-1d304fa491d3 github.com/88250/lute v1.7.7-0.20250907110109-efc34e9d52fa
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4 github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4
github.com/ConradIrwin/font v0.2.1 github.com/ConradIrwin/font v0.2.1
@ -56,9 +56,9 @@ require (
github.com/rqlite/sql v0.0.0-20250623131620-453fa49cad04 github.com/rqlite/sql v0.0.0-20250623131620-453fa49cad04
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/sashabaranov/go-openai v1.40.3 github.com/sashabaranov/go-openai v1.40.3
github.com/shirou/gopsutil/v4 v4.25.7 github.com/shirou/gopsutil/v4 v4.25.8
github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3 github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3
github.com/siyuan-note/dejavu v0.0.0-20250823083709-147ab94b046a github.com/siyuan-note/dejavu v0.0.0-20250903140859-4d1e84e6dc9d
github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec
github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97 github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97
github.com/siyuan-note/filelock v0.0.0-20250227145141-7d111cdf3c57 github.com/siyuan-note/filelock v0.0.0-20250227145141-7d111cdf3c57
@ -94,24 +94,24 @@ require (
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2 v1.38.1 // indirect github.com/aws/aws-sdk-go-v2 v1.38.3 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 // indirect
github.com/aws/aws-sdk-go-v2/config v1.31.2 // indirect github.com/aws/aws-sdk-go-v2/config v1.31.6 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.18.6 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.18.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1 // indirect github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 // indirect
github.com/aws/smithy-go v1.22.5 // indirect github.com/aws/smithy-go v1.23.0 // indirect
github.com/bytedance/sonic v1.13.3 // indirect github.com/bytedance/sonic v1.13.3 // indirect
github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
@ -187,7 +187,7 @@ require (
golang.org/x/tools v0.36.0 // indirect golang.org/x/tools v0.36.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
modernc.org/fileutil v1.3.22 // indirect modernc.org/fileutil v1.3.29 // indirect
) )
replace github.com/mattn/go-sqlite3 => github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950 replace github.com/mattn/go-sqlite3 => github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950

View file

@ -14,8 +14,8 @@ github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950 h1:Pa5hMiBceT
github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689 h1:39y5g7vnFAIcXhTN3IXPk7h2xBhC4a9hBTykDhHJqRY= github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689 h1:39y5g7vnFAIcXhTN3IXPk7h2xBhC4a9hBTykDhHJqRY=
github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689/go.mod h1:c8uVw25vW2W4dhJ/j4iYsX5H1hc19spim266jO5x2hU= github.com/88250/gulu v1.2.3-0.20250227144607-7f4570b0d689/go.mod h1:c8uVw25vW2W4dhJ/j4iYsX5H1hc19spim266jO5x2hU=
github.com/88250/lute v1.7.7-0.20250828030734-1d304fa491d3 h1:Y/ZKnwrgdICSxkXMGJZL7R18FlCrumP9VQQTdyTQZrM= github.com/88250/lute v1.7.7-0.20250907110109-efc34e9d52fa h1:kbvW8LD3yJK5hwbLdJDb+7xqj7i68Rbz47xEqnNqf4I=
github.com/88250/lute v1.7.7-0.20250828030734-1d304fa491d3/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o= github.com/88250/lute v1.7.7-0.20250907110109-efc34e9d52fa/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o=
github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46 h1:Bq1JsDfVbHKUxNL/B2JXd8cC/1h6aFjrlXpGycnh0Hk= github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46 h1:Bq1JsDfVbHKUxNL/B2JXd8cC/1h6aFjrlXpGycnh0Hk=
github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI= github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI=
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY= github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=
@ -56,42 +56,42 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw= github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef h1:2JGTg6JapxP9/R33ZaagQtAM4EkkSYnIAlOG5EI8gkM= github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef h1:2JGTg6JapxP9/R33ZaagQtAM4EkkSYnIAlOG5EI8gkM=
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII= github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII=
github.com/aws/aws-sdk-go-v2 v1.38.1 h1:j7sc33amE74Rz0M/PoCpsZQ6OunLqys/m5antM0J+Z8= github.com/aws/aws-sdk-go-v2 v1.38.3 h1:B6cV4oxnMs45fql4yRH+/Po/YU+597zgWqvDpYMturk=
github.com/aws/aws-sdk-go-v2 v1.38.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg= github.com/aws/aws-sdk-go-v2 v1.38.3/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0 h1:6GMWV6CNpA/6fbFHnoAjrv4+LGfyTqZz2LtCHnspgDg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1 h1:i8p8P4diljCr60PpJp6qZXNlgX4m2yQFpYk+9ZT+J4E=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.0/go.mod h1:/mXlTIVG9jbxkqDnr5UQNQxW1HRYxeGklkM9vAFeabg= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.1/go.mod h1:ddqbooRZYNoJ2dsTwOty16rM+/Aqmk/GOXrK8cg7V00=
github.com/aws/aws-sdk-go-v2/config v1.31.2 h1:NOaSZpVGEH2Np/c1toSeW0jooNl+9ALmsUTZ8YvkJR0= github.com/aws/aws-sdk-go-v2/config v1.31.6 h1:a1t8fXY4GT4xjyJExz4knbuoxSCacB5hT/WgtfPyLjo=
github.com/aws/aws-sdk-go-v2/config v1.31.2/go.mod h1:17ft42Yb2lF6OigqSYiDAiUcX4RIkEMY6XxEMJsrAes= github.com/aws/aws-sdk-go-v2/config v1.31.6/go.mod h1:5ByscNi7R+ztvOGzeUaIu49vkMk2soq5NaH5PYe33MQ=
github.com/aws/aws-sdk-go-v2/credentials v1.18.6 h1:AmmvNEYrru7sYNJnp3pf57lGbiarX4T9qU/6AZ9SucU= github.com/aws/aws-sdk-go-v2/credentials v1.18.10 h1:xdJnXCouCx8Y0NncgoptztUocIYLKeQxrCgN6x9sdhg=
github.com/aws/aws-sdk-go-v2/credentials v1.18.6/go.mod h1:/jdQkh1iVPa01xndfECInp1v1Wnp70v3K4MvtlLGVEc= github.com/aws/aws-sdk-go-v2/credentials v1.18.10/go.mod h1:7tQk08ntj914F/5i9jC4+2HQTAuJirq7m1vZVIhEkWs=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4 h1:lpdMwTzmuDLkgW7086jE94HweHCqG+uOJwHf3LZs7T0= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6 h1:wbjnrrMnKew78/juW7I2BtKQwa1qlf6EjQgS69uYY14=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.4/go.mod h1:9xzb8/SV62W6gHQGC/8rrvgNXU6ZoYM3sAIJCIrXJxY= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.6/go.mod h1:AtiqqNrDioJXuUgz3+3T0mBWN7Hro2n9wll2zRUc0ww=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 h1:IdCLsiiIj5YJ3AFevsewURCPV+YWUlOW8JiPhoAy8vg= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6 h1:uF68eJA6+S9iVr9WgX1NaRGyQ/6MdIyc4JNUo6TN1FA=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4/go.mod h1:l4bdfCD7XyyZA9BolKBo1eLqgaJxl0/x91PL4Yqe0ao= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.6/go.mod h1:qlPeVZCGPiobx8wb1ft0GHT5l+dc6ldnwInDFaMvC7Y=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 h1:j7vjtr1YIssWQOMeOWRbh3z8g2oY/xPjnZH2gLY4sGw= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6 h1:pa1DEC6JoI0zduhZePp3zmhWvk/xxm4NB8Hy/Tlsgos=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4/go.mod h1:yDmJgqOiH4EA8Hndnv4KwAo8jCGTSnM5ASG1nBI+toA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.6/go.mod h1:gxEjPebnhWGJoaDdtDkA0JX46VRg1wcTHYe63OfX5pE=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4 h1:BE/MNQ86yzTINrfxPPFS86QCBNQeLKY2A0KhDh47+wI= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6 h1:R0tNFJqfjHL3900cqhXuwQ+1K4G0xc9Yf8EDbFXCKEw=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.4/go.mod h1:SPBBhkJxjcrzJBc+qY85e83MQ2q3qdra8fghhkkyrJg= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.6/go.mod h1:y/7sDdu+aJvPtGXr4xYosdpq9a6T9Z0jkXfugmti0rI=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0 h1:6+lZi2JeGKtCraAj1rpoZfKqnQ9SptseRZioejfUOLM= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.0/go.mod h1:eb3gfbVIxIoGgJsi9pGne19dhCBpK6opTYpQqAmdy44= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4 h1:Beh9oVgtQnBgR4sKKzkUBRQpf1GnL4wt0l4s8h2VCJ0= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6 h1:hncKj/4gR+TPauZgTAsxOxNcvBayhUlYZ6LO/BYiQ30=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.4/go.mod h1:b17At0o8inygF+c6FOD3rNyYZufPw62o9XJbSfQPgbo= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.8.6/go.mod h1:OiIh45tp6HdJDDJGnja0mw8ihQGz3VGrUflLqSL0SmM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4 h1:ueB2Te0NacDMnaC+68za9jLwkjzxGWm0KB5HTUHjLTI= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6 h1:LHS1YAIJXJ4K9zS+1d/xa9JAA9sL2QyXIQCQFQW/X08=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.4/go.mod h1:nLEfLnVMmLvyIG58/6gsSA03F1voKGaCfHV7+lR8S7s= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.6/go.mod h1:c9PCiTEuh0wQID5/KqA32J+HAgZxN9tOGXKCiYJjTZI=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4 h1:HVSeukL40rHclNcUqVcBwE1YoZhOkoLeBfhUqR3tjIU= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6 h1:nEXUSAwyUfLTgnc9cxlDWy637qsq4UWwp3sNAfl0Z3Y=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.4/go.mod h1:DnbBOv4FlIXHj2/xmrUQYtawRFC9L9ZmQPz+DBc6X5I= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.6/go.mod h1:HGzIULx4Ge3Do2V0FaiYKcyKzOqwrhUZgCI77NisswQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1 h1:2n6Pd67eJwAb/5KCX62/8RTU0aFAAW7V5XIGSghiHrw= github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3 h1:ETkfWcXP2KNPLecaDa++5bsQhCRa5M5sLUJa5DWYIIg=
github.com/aws/aws-sdk-go-v2/service/s3 v1.87.1/go.mod h1:w5PC+6GHLkvMJKasYGVloB3TduOtROEMqm15HSuIbw4= github.com/aws/aws-sdk-go-v2/service/s3 v1.87.3/go.mod h1:+/3ZTqoYb3Ur7DObD00tarKMLMuKg8iqz5CHEanqTnw=
github.com/aws/aws-sdk-go-v2/service/sso v1.28.2 h1:ve9dYBB8CfJGTFqcQ3ZLAAb/KXWgYlgu/2R2TZL2Ko0= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1 h1:8OLZnVJPvjnrxEwHFg9hVUof/P4sibH+Ea4KKuqAGSg=
github.com/aws/aws-sdk-go-v2/service/sso v1.28.2/go.mod h1:n9bTZFZcBa9hGGqVz3i/a6+NG0zmZgtkB9qVVFDqPA8= github.com/aws/aws-sdk-go-v2/service/sso v1.29.1/go.mod h1:27M3BpVi0C02UiQh1w9nsBEit6pLhlaH3NHna6WUbDE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2 h1:pd9G9HQaM6UZAZh19pYOkpKSQkyQQ9ftnl/LttQOcGI= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2 h1:gKWSTnqudpo8dAxqBqZnDoDWCiEh/40FziUjr/mo6uA=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.33.2/go.mod h1:eknndR9rU8UpE/OmFpqU78V1EcXPKFTTm5l/buZYgvM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.34.2/go.mod h1:x7+rkNmRoEN1U13A6JE2fXne9EWyJy54o3n6d4mGaXQ=
github.com/aws/aws-sdk-go-v2/service/sts v1.38.0 h1:iV1Ko4Em/lkJIsoKyGfc0nQySi+v0Udxr6Igq+y9JZc= github.com/aws/aws-sdk-go-v2/service/sts v1.38.2 h1:YZPjhyaGzhDQEvsffDEcpycq49nl7fiGcfJTIo8BszI=
github.com/aws/aws-sdk-go-v2/service/sts v1.38.0/go.mod h1:bEPcjW7IbolPfK67G1nilqWyoxYMSPrDiIQ3RdIdKgo= github.com/aws/aws-sdk-go-v2/service/sts v1.38.2/go.mod h1:2dIN8qhQfv37BdUYGgEC8Q3tteM3zFxTI1MLO2O3J3c=
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw= github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE=
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0= github.com/bytedance/sonic v1.13.3 h1:MS8gmaH16Gtirygw7jV91pDCN33NyMrPbN7qiYhEsF0=
github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4= github.com/bytedance/sonic v1.13.3/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
@ -363,8 +363,8 @@ github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+e
github.com/sashabaranov/go-openai v1.40.3 h1:PkOw0SK34wrvYVOuXF1HZzuTBRh992qRZHil4kG3eYE= github.com/sashabaranov/go-openai v1.40.3 h1:PkOw0SK34wrvYVOuXF1HZzuTBRh992qRZHil4kG3eYE=
github.com/sashabaranov/go-openai v1.40.3/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sashabaranov/go-openai v1.40.3/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg= github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM= github.com/shirou/gopsutil/v4 v4.25.8 h1:NnAsw9lN7587WHxjJA9ryDnqhJpFH6A+wagYWTOH970=
github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U= github.com/shirou/gopsutil/v4 v4.25.8/go.mod h1:q9QdMmfAOVIw7a+eF86P7ISEU6ka+NLgkUxlopV4RwI=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d h1:lvCTyBbr36+tqMccdGMwuEU+hjux/zL6xSmf5S9ITaA= github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d h1:lvCTyBbr36+tqMccdGMwuEU+hjux/zL6xSmf5S9ITaA=
@ -372,8 +372,8 @@ github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d/go.mod h1:05Ut
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8= github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3 h1:EH063L0HD1f82DvddurUmEXS0obXypv8pQrcaC/zNgI= github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3 h1:EH063L0HD1f82DvddurUmEXS0obXypv8pQrcaC/zNgI=
github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3/go.mod h1:8lb+SsWAPQblGbjmwEBsBdJszMCcLeECtB95fv6mReg= github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3/go.mod h1:8lb+SsWAPQblGbjmwEBsBdJszMCcLeECtB95fv6mReg=
github.com/siyuan-note/dejavu v0.0.0-20250823083709-147ab94b046a h1:VBsNIc1MGVvHbHl1NMe4RMg+VVyCC4qVYtjpP2cC9hQ= github.com/siyuan-note/dejavu v0.0.0-20250903140859-4d1e84e6dc9d h1:QRYzJHKG020eN1O8o8GxkxPQbJnA58y9OIfDoo2+KH0=
github.com/siyuan-note/dejavu v0.0.0-20250823083709-147ab94b046a/go.mod h1:9u6fFkH30VBjtozHDjNA/MZCULOuDtiPfGhV7DbYzww= github.com/siyuan-note/dejavu v0.0.0-20250903140859-4d1e84e6dc9d/go.mod h1:OEWx8aZaDWv8pIY3mCbVMoYzH7at/o2rXo5hCnt8gmQ=
github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec h1:D8Sjwa+7WxP3XrIBscT4PxBZZddZ83/O+5nX1sq6g6g= github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec h1:D8Sjwa+7WxP3XrIBscT4PxBZZddZ83/O+5nX1sq6g6g=
github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec/go.mod h1:6iAxXPOOAG3+M4bCiKQZTQ+n4gSUx/OyHhsP57dJlS8= github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec/go.mod h1:6iAxXPOOAG3+M4bCiKQZTQ+n4gSUx/OyHhsP57dJlS8=
github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97 h1:lM5v8BfNtbOL5jYwhCdMYBcYtr06IYBKjjSLAPMKTM8= github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97 h1:lM5v8BfNtbOL5jYwhCdMYBcYtr06IYBKjjSLAPMKTM8=
@ -402,8 +402,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/studio-b12/gowebdav v0.10.0 h1:Yewz8FFiadcGEu4hxS/AAJQlHelndqln1bns3hcJIYc= github.com/studio-b12/gowebdav v0.10.0 h1:Yewz8FFiadcGEu4hxS/AAJQlHelndqln1bns3hcJIYc=
github.com/studio-b12/gowebdav v0.10.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE= github.com/studio-b12/gowebdav v0.10.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/teambition/rrule-go v1.8.2 h1:lIjpjvWTj9fFUZCmuoVDrKVOtdiyzbzc93qTmRVe/J8= github.com/teambition/rrule-go v1.8.2 h1:lIjpjvWTj9fFUZCmuoVDrKVOtdiyzbzc93qTmRVe/J8=
@ -571,6 +571,6 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
modernc.org/fileutil v1.3.22 h1:2gf4hOBPsb2LBudv5wUzBAf6OlJEW3/rrhl9kTofh0Y= modernc.org/fileutil v1.3.29 h1:2HcUXxp2OuKCvHDGE/O92Tv3rX28fRRi9g+wVz4k5cA=
modernc.org/fileutil v1.3.22/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/fileutil v1.3.29/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

View file

@ -26,6 +26,7 @@ import (
"time" "time"
"github.com/88250/gulu" "github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/siyuan-note/filelock" "github.com/siyuan-note/filelock"
"github.com/siyuan-note/httpclient" "github.com/siyuan-note/httpclient"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
@ -289,5 +290,5 @@ func FilterUploadFileName(name string) string {
} }
func AssetName(name string) string { func AssetName(name string) string {
return util.AssetName(name) return util.AssetName(name, ast.NewNodeID())
} }

View file

@ -201,7 +201,7 @@ func NetAssets2LocalAssets(rootID string, onlyImg bool, originalURL string) (err
name := filepath.Base(u) name := filepath.Base(u)
name = util.FilterUploadFileName(name) name = util.FilterUploadFileName(name)
name = "network-asset-" + name name = "network-asset-" + name
name = util.AssetName(name) name = util.AssetName(name, ast.NewNodeID())
writePath := filepath.Join(assetsDirPath, name) writePath := filepath.Join(assetsDirPath, name)
if err = filelock.Copy(u, writePath); err != nil { if err = filelock.Copy(u, writePath); err != nil {
logging.LogErrorf("copy [%s] to [%s] failed: %s", u, writePath, err) logging.LogErrorf("copy [%s] to [%s] failed: %s", u, writePath, err)
@ -303,7 +303,7 @@ func NetAssets2LocalAssets(rootID string, onlyImg bool, originalURL string) (err
name += ext name += ext
} }
} }
name = util.AssetName(name) name = util.AssetName(name, ast.NewNodeID())
name = "network-asset-" + name name = "network-asset-" + name
writePath := filepath.Join(assetsDirPath, name) writePath := filepath.Join(assetsDirPath, name)
if err = filelock.WriteFile(writePath, data); err != nil { if err = filelock.WriteFile(writePath, data); err != nil {
@ -737,7 +737,7 @@ func RenameAsset(oldPath, newName string) (newPath string, err error) {
return return
} }
newName = util.AssetName(newName + filepath.Ext(oldPath)) newName = util.AssetName(newName+filepath.Ext(oldPath), ast.NewNodeID())
parentDir := path.Dir(oldPath) parentDir := path.Dir(oldPath)
newPath = path.Join(parentDir, newName) newPath = path.Join(parentDir, newName)
oldAbsPath, getErr := GetAssetAbsPath(oldPath) oldAbsPath, getErr := GetAssetAbsPath(oldPath)

View file

@ -199,6 +199,7 @@ func getAttrViewAddingBlockDefaultValues(attrView *av.AttributeView, view, group
if nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow { if nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow {
newValue.Date.Content = time.Now().UnixMilli() newValue.Date.Content = time.Now().UnixMilli()
newValue.Date.IsNotEmpty = true
} }
} }
@ -270,6 +271,7 @@ func getAttrViewAddingBlockDefaultValues(attrView *av.AttributeView, view, group
if nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow { if nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow {
newValue.Date.Content = time.Now().UnixMilli() newValue.Date.Content = time.Now().UnixMilli()
newValue.Date.IsNotEmpty = true
} }
return return
} }
@ -308,6 +310,7 @@ func getAttrViewAddingBlockDefaultValues(attrView *av.AttributeView, view, group
if nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow { if nil != keyValues.Key.Date && keyValues.Key.Date.AutoFillNow {
newValue.Date.Content = time.Now().UnixMilli() newValue.Date.Content = time.Now().UnixMilli()
newValue.Date.IsNotEmpty = true
} }
} }
return return
@ -1091,7 +1094,9 @@ func DuplicateDatabaseBlock(avID string) (newAvID, newBlockID string, err error)
return return
} }
newAv.Name = oldAv.Name + " (Duplicated " + time.Now().Format("2006-01-02 15:04:05") + ")" if "" != newAv.Name {
newAv.Name = oldAv.Name + " (Duplicated " + time.Now().Format("2006-01-02 15:04:05") + ")"
}
for _, keyValues := range newAv.KeyValues { for _, keyValues := range newAv.KeyValues {
if nil != keyValues.Key.Relation && keyValues.Key.Relation.IsTwoWay { if nil != keyValues.Key.Relation && keyValues.Key.Relation.IsTwoWay {
@ -1465,16 +1470,16 @@ func GetBlockAttributeViewKeys(nodeID string) (ret []*BlockAttributeViewKeys) {
return return
} }
attrViewCache := map[string]*av.AttributeView{} cachedAttrViews := map[string]*av.AttributeView{}
avIDs := strings.Split(avs, ",") avIDs := strings.Split(avs, ",")
for _, avID := range avIDs { for _, avID := range avIDs {
attrView := attrViewCache[avID] attrView := cachedAttrViews[avID]
if nil == attrView { if nil == attrView {
attrView, _ = av.ParseAttributeView(avID) attrView, _ = av.ParseAttributeView(avID)
if nil == attrView { if nil == attrView {
return return
} }
attrViewCache[avID] = attrView cachedAttrViews[avID] = attrView
} }
if !attrView.ExistBoundBlock(nodeID) { if !attrView.ExistBoundBlock(nodeID) {
@ -1572,42 +1577,7 @@ func GetBlockAttributeViewKeys(nodeID string) (ret []*BlockAttributeViewKeys) {
// 再渲染关联和汇总 // 再渲染关联和汇总
rollupFurtherCollections := map[string]av.Collection{} rollupFurtherCollections := sql.GetFurtherCollections(attrView, cachedAttrViews)
for _, kv := range keyValues {
if av.KeyTypeRollup != kv.Key.Type {
continue
}
relKey, _ := attrView.GetKey(kv.Key.Rollup.RelationKeyID)
if nil == relKey {
continue
}
destAv := attrViewCache[relKey.Relation.AvID]
if nil == destAv {
destAv, _ = av.ParseAttributeView(relKey.Relation.AvID)
if nil == destAv {
continue
}
attrViewCache[relKey.Relation.AvID] = destAv
}
destKey, _ := destAv.GetKey(kv.Key.Rollup.KeyID)
if nil == destKey {
continue
}
isSameAv := destAv.ID == attrView.ID
var furtherCollection av.Collection
if av.KeyTypeTemplate == destKey.Type || (!isSameAv && (av.KeyTypeUpdated == destKey.Type || av.KeyTypeCreated == destKey.Type)) {
viewable := sql.RenderView(destAv, destAv.Views[0], "")
if nil != viewable {
furtherCollection = viewable.(av.Collection)
}
}
rollupFurtherCollections[kv.Key.ID] = furtherCollection
}
for _, kv := range keyValues { for _, kv := range keyValues {
switch kv.Key.Type { switch kv.Key.Type {
case av.KeyTypeRollup: case av.KeyTypeRollup:
@ -1622,13 +1592,13 @@ func GetBlockAttributeViewKeys(nodeID string) (ret []*BlockAttributeViewKeys) {
relVal := attrView.GetValue(kv.Key.Rollup.RelationKeyID, kv.Values[0].BlockID) relVal := attrView.GetValue(kv.Key.Rollup.RelationKeyID, kv.Values[0].BlockID)
if nil != relVal && nil != relVal.Relation { if nil != relVal && nil != relVal.Relation {
destAv := attrViewCache[relKey.Relation.AvID] destAv := cachedAttrViews[relKey.Relation.AvID]
if nil == destAv { if nil == destAv {
destAv, _ = av.ParseAttributeView(relKey.Relation.AvID) destAv, _ = av.ParseAttributeView(relKey.Relation.AvID)
if nil == destAv { if nil == destAv {
break break
} }
attrViewCache[relKey.Relation.AvID] = destAv cachedAttrViews[relKey.Relation.AvID] = destAv
} }
destKey, _ := destAv.GetKey(kv.Key.Rollup.KeyID) destKey, _ := destAv.GetKey(kv.Key.Rollup.KeyID)
@ -1642,14 +1612,14 @@ func GetBlockAttributeViewKeys(nodeID string) (ret []*BlockAttributeViewKeys) {
break break
} }
destAv := attrViewCache[kv.Key.Relation.AvID] destAv := cachedAttrViews[kv.Key.Relation.AvID]
if nil == destAv { if nil == destAv {
destAv, _ = av.ParseAttributeView(kv.Key.Relation.AvID) destAv, _ = av.ParseAttributeView(kv.Key.Relation.AvID)
if nil == destAv { if nil == destAv {
break break
} }
attrViewCache[kv.Key.Relation.AvID] = destAv cachedAttrViews[kv.Key.Relation.AvID] = destAv
} }
blocks := map[string]*av.Value{} blocks := map[string]*av.Value{}
@ -2070,8 +2040,10 @@ func GetCurrentAttributeViewImages(avID, viewID, query string) (ret []string, er
view = attrView.GetView(attrView.ViewID) view = attrView.GetView(attrView.ViewID)
} }
cachedAttrViews := map[string]*av.AttributeView{}
rollupFurtherCollections := sql.GetFurtherCollections(attrView, cachedAttrViews)
table := getAttrViewTable(attrView, view, query) table := getAttrViewTable(attrView, view, query)
av.Filter(table, attrView) av.Filter(table, attrView, rollupFurtherCollections, cachedAttrViews)
av.Sort(table, attrView) av.Sort(table, attrView)
ids := map[string]bool{} ids := map[string]bool{}
@ -2566,6 +2538,7 @@ func (tx *Transaction) doDuplicateAttrViewView(operation *Operation) (ret *TxErr
for _, filter := range masterView.Filters { for _, filter := range masterView.Filters {
view.Filters = append(view.Filters, &av.ViewFilter{ view.Filters = append(view.Filters, &av.ViewFilter{
Column: filter.Column, Column: filter.Column,
Qualifier: filter.Qualifier,
Operator: filter.Operator, Operator: filter.Operator,
Value: filter.Value, Value: filter.Value,
RelativeDate: filter.RelativeDate, RelativeDate: filter.RelativeDate,
@ -3284,8 +3257,10 @@ func getNewValueByNearItem(nearItem av.Item, key *av.Key, addingBlockID string)
} }
func getNearItem(attrView *av.AttributeView, view, groupView *av.View, previousItemID string) (ret av.Item) { func getNearItem(attrView *av.AttributeView, view, groupView *av.View, previousItemID string) (ret av.Item) {
cachedAttrViews := map[string]*av.AttributeView{}
rollupFurtherCollections := sql.GetFurtherCollections(attrView, cachedAttrViews)
viewable := sql.RenderGroupView(attrView, view, groupView, "") viewable := sql.RenderGroupView(attrView, view, groupView, "")
av.Filter(viewable, attrView) av.Filter(viewable, attrView, rollupFurtherCollections, cachedAttrViews)
av.Sort(viewable, attrView) av.Sort(viewable, attrView)
items := viewable.(av.Collection).GetItems() items := viewable.(av.Collection).GetItems()
if 0 < len(items) { if 0 < len(items) {
@ -3785,10 +3760,7 @@ func sortAttributeViewRow(operation *Operation) (err error) {
targetGroupView.GroupItemIDs = util.InsertElem(targetGroupView.GroupItemIDs, previousIndex, itemID) targetGroupView.GroupItemIDs = util.InsertElem(targetGroupView.GroupItemIDs, previousIndex, itemID)
} }
if av.KeyTypeMSelect == groupKey.Type || av.KeyTypeRelation == groupKey.Type { regenAttrViewGroups(attrView)
// 跨多选分组时一个项目可能会同时存在于多个分组中,需要重新生成分组
regenAttrViewGroups(attrView)
}
} else { // 同分组内排序 } else { // 同分组内排序
for i, r := range groupView.GroupItemIDs { for i, r := range groupView.GroupItemIDs {
if r == operation.PreviousID { if r == operation.PreviousID {

View file

@ -110,16 +110,9 @@ func renderAttributeViewGroups(viewable av.Viewable, attrView *av.AttributeView,
// 如果存在分组的话渲染分组视图 // 如果存在分组的话渲染分组视图
fixDev := false
for _, groupView := range view.Groups { for _, groupView := range view.Groups {
if (nil == groupView.GroupVal || nil == groupView.GroupKey) && !fixDev { groupView.Name = groupView.GetGroupValue()
// TODO 分组上线后删除,预计 2025 年 9 月后可以删除 switch groupView.Name {
regenAttrViewGroups(attrView)
av.SaveAttributeView(attrView)
fixDev = true
}
switch groupView.GetGroupValue() {
case groupValueDefault: case groupValueDefault:
groupView.Name = fmt.Sprintf(Conf.language(264), groupKey.Name) groupView.Name = fmt.Sprintf(Conf.language(264), groupKey.Name)
case groupValueNotInRange: case groupValueNotInRange:
@ -138,8 +131,6 @@ func renderAttributeViewGroups(viewable av.Viewable, attrView *av.AttributeView,
groupView.Name = fmt.Sprintf(Conf.language(263), 7) groupView.Name = fmt.Sprintf(Conf.language(263), 7)
case groupValueNext30Days: case groupValueNext30Days:
groupView.Name = fmt.Sprintf(Conf.language(263), 30) groupView.Name = fmt.Sprintf(Conf.language(263), 30)
default:
groupView.Name = groupView.GetGroupValue()
} }
} }
@ -377,7 +368,9 @@ func renderViewableInstance(viewable av.Viewable, view *av.View, attrView *av.At
return return
} }
av.Filter(viewable, attrView) cachedAttrViews := map[string]*av.AttributeView{}
rollupFurtherCollections := sql.GetFurtherCollections(attrView, cachedAttrViews)
av.Filter(viewable, attrView, rollupFurtherCollections, cachedAttrViews)
av.Sort(viewable, attrView) av.Sort(viewable, attrView)
av.Calc(viewable, attrView) av.Calc(viewable, attrView)
@ -482,7 +475,7 @@ func RenderRepoSnapshotAttributeView(indexID, avID string) (viewable av.Viewable
return return
} }
attrView = &av.AttributeView{} attrView = &av.AttributeView{RenderedViewables: map[string]av.Viewable{}}
if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil { if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil {
logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err) logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
return return
@ -525,7 +518,7 @@ func RenderHistoryAttributeView(avID, created string) (viewable av.Viewable, att
return return
} }
attrView = &av.AttributeView{} attrView = &av.AttributeView{RenderedViewables: map[string]av.Viewable{}}
if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil { if err = gulu.JSON.UnmarshalJSON(data, attrView); err != nil {
logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err) logging.LogErrorf("unmarshal attribute view [%s] failed: %s", avID, err)
return return

View file

@ -20,6 +20,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"slices"
"strings" "strings"
"time" "time"
@ -629,7 +630,35 @@ func GetHeadingChildrenIDs(id string) (ret []string) {
return return
} }
func GetHeadingChildrenDOM(id string) (ret string) { func AppendHeadingChildren(id, childrenDOM string) {
tree, err := LoadTreeByBlockID(id)
if err != nil {
return
}
heading := treenode.GetNodeInTree(tree, id)
if nil == heading || ast.NodeHeading != heading.Type {
return
}
luteEngine := util.NewLute()
subTree := luteEngine.BlockDOM2Tree(childrenDOM)
var nodes []*ast.Node
for n := subTree.Root.FirstChild; nil != n; n = n.Next {
nodes = append(nodes, n)
}
slices.Reverse(nodes)
for _, n := range nodes {
heading.InsertAfter(n)
}
if err = indexWriteTreeUpsertQueue(tree); err != nil {
return
}
}
func GetHeadingChildrenDOM(id string, removeFoldAttr bool) (ret string) {
tree, err := LoadTreeByBlockID(id) tree, err := LoadTreeByBlockID(id)
if err != nil { if err != nil {
return return
@ -643,20 +672,26 @@ func GetHeadingChildrenDOM(id string) (ret string) {
children := treenode.HeadingChildren(heading) children := treenode.HeadingChildren(heading)
nodes = append(nodes, children...) nodes = append(nodes, children...)
// 取消折叠 https://github.com/siyuan-note/siyuan/issues/13232#issuecomment-2535955152
for _, child := range children { for _, child := range children {
ast.Walk(child, func(n *ast.Node, entering bool) ast.WalkStatus { ast.Walk(child, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering { if !entering {
return ast.WalkContinue return ast.WalkContinue
} }
n.RemoveIALAttr("heading-fold") if removeFoldAttr {
n.RemoveIALAttr("fold") n.RemoveIALAttr("heading-fold")
n.RemoveIALAttr("fold")
}
return ast.WalkContinue return ast.WalkContinue
}) })
child.SetIALAttr("parent-heading", id)
}
if removeFoldAttr {
heading.RemoveIALAttr("fold")
heading.RemoveIALAttr("heading-fold")
} }
heading.RemoveIALAttr("fold")
heading.RemoveIALAttr("heading-fold")
luteEngine := util.NewLute() luteEngine := util.NewLute()
ret = renderBlockDOMByNodes(nodes, luteEngine) ret = renderBlockDOMByNodes(nodes, luteEngine)

View file

@ -28,6 +28,7 @@ import (
"sync" "sync"
"github.com/88250/gulu" "github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/emersion/go-vcard" "github.com/emersion/go-vcard"
"github.com/emersion/go-webdav/carddav" "github.com/emersion/go-webdav/carddav"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
@ -640,7 +641,7 @@ func (b *AddressBook) load() error {
addressesWaitGroup.Add(1) addressesWaitGroup.Add(1)
go func() { go func() {
defer addressesWaitGroup.Done() defer addressesWaitGroup.Done()
filename_ := util.AssetName(filename) filename_ := util.AssetName(filename, ast.NewNodeID())
address := &AddressObject{ address := &AddressObject{
FilePath: path.Join(b.DirectoryPath, filename_), FilePath: path.Join(b.DirectoryPath, filename_),
BookPath: b.MetaData.Path, BookPath: b.MetaData.Path,

View file

@ -83,7 +83,9 @@ func ExportAv2CSV(avID, blockID string) (zipPath string, err error) {
table := getAttrViewTable(attrView, view, "") table := getAttrViewTable(attrView, view, "")
// 遵循视图过滤和排序规则 Use filtering and sorting of current view settings when exporting database blocks https://github.com/siyuan-note/siyuan/issues/10474 // 遵循视图过滤和排序规则 Use filtering and sorting of current view settings when exporting database blocks https://github.com/siyuan-note/siyuan/issues/10474
av.Filter(table, attrView) cachedAttrViews := map[string]*av.AttributeView{}
rollupFurtherCollections := sql.GetFurtherCollections(attrView, cachedAttrViews)
av.Filter(table, attrView, rollupFurtherCollections, cachedAttrViews)
av.Sort(table, attrView) av.Sort(table, attrView)
exportFolder := filepath.Join(util.TempDir, "export", "csv", name) exportFolder := filepath.Join(util.TempDir, "export", "csv", name)
@ -273,7 +275,7 @@ func Export2Liandi(id string) (err error) {
".md", 3, 1, 1, ".md", 3, 1, 1,
"#", "#", "#", "#",
"", "", "", "",
false, false, nil, true, false, &map[string]*parse.Tree{}) false, false, nil, true, false, map[string]*parse.Tree{})
result := gulu.Ret.NewResult() result := gulu.Ret.NewResult()
request := httpclient.NewCloudRequest30s() request := httpclient.NewCloudRequest30s()
request = request. request = request.
@ -584,7 +586,7 @@ func Preview(id string, fillCSSVar bool) (retStdHTML string) {
blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode, blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
"#", "#", // 这里固定使用 # 包裹标签,否则无法正确解析标签 https://github.com/siyuan-note/siyuan/issues/13857 "#", "#", // 这里固定使用 # 包裹标签,否则无法正确解析标签 https://github.com/siyuan-note/siyuan/issues/13857
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight, Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
Conf.Export.AddTitle, Conf.Export.InlineMemo, true, true, &map[string]*parse.Tree{}) Conf.Export.AddTitle, Conf.Export.InlineMemo, true, true, map[string]*parse.Tree{})
luteEngine := NewLute() luteEngine := NewLute()
enableLuteInlineSyntax(luteEngine) enableLuteInlineSyntax(luteEngine)
luteEngine.SetFootnotes(true) luteEngine.SetFootnotes(true)
@ -722,7 +724,7 @@ func ExportMarkdownHTML(id, savePath string, docx, merge bool) (name, dom string
blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode, blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker, Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight, Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
Conf.Export.AddTitle, Conf.Export.InlineMemo, true, true, &map[string]*parse.Tree{}) Conf.Export.AddTitle, Conf.Export.InlineMemo, true, true, map[string]*parse.Tree{})
name = path.Base(tree.HPath) name = path.Base(tree.HPath)
name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614 name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614
savePath = strings.TrimSpace(savePath) savePath = strings.TrimSpace(savePath)
@ -884,7 +886,7 @@ func ExportHTML(id, savePath string, pdf, image, keepFold, merge bool) (name, do
blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode, blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker, Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight, Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
Conf.Export.AddTitle, Conf.Export.InlineMemo, true, true, &map[string]*parse.Tree{}) Conf.Export.AddTitle, Conf.Export.InlineMemo, true, true, map[string]*parse.Tree{})
adjustHeadingLevel(bt, tree) adjustHeadingLevel(bt, tree)
name = path.Base(tree.HPath) name = path.Base(tree.HPath)
name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614 name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614
@ -1518,7 +1520,7 @@ func ExportStdMarkdown(id string, assetsDestSpace2Underscore, fillCSSVar, adjust
".md", Conf.Export.BlockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode, ".md", Conf.Export.BlockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker, Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight, Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
Conf.Export.AddTitle, Conf.Export.InlineMemo, defBlockIDs, true, fillCSSVar, &map[string]*parse.Tree{}) Conf.Export.AddTitle, Conf.Export.InlineMemo, defBlockIDs, true, fillCSSVar, map[string]*parse.Tree{})
} }
func ExportPandocConvertZip(ids []string, pandocTo, ext string) (name, zipPath string) { func ExportPandocConvertZip(ids []string, pandocTo, ext string) (name, zipPath string) {
@ -1684,7 +1686,7 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
util.PushEndlessProgress(Conf.language(65) + " " + fmt.Sprintf(Conf.language(70), fmt.Sprintf("%d/%d %s", count, len(docPaths), tree.Root.IALAttr("title")))) util.PushEndlessProgress(Conf.language(65) + " " + fmt.Sprintf(Conf.language(70), fmt.Sprintf("%d/%d %s", count, len(docPaths), tree.Root.IALAttr("title"))))
refs := map[string]*parse.Tree{} refs := map[string]*parse.Tree{}
exportRefTrees(tree, &[]string{}, &refs, &treeCache) exportRefTrees(tree, &[]string{}, refs, treeCache)
for refTreeID, refTree := range refs { for refTreeID, refTree := range refs {
if nil == trees[refTreeID] { if nil == trees[refTreeID] {
refTrees[refTreeID] = refTree refTrees[refTreeID] = refTree
@ -2012,7 +2014,7 @@ func ExportMarkdownContent(id string, refMode, embedMode int, addYfm, fillCSSVar
".md", refMode, embedMode, Conf.Export.FileAnnotationRefMode, ".md", refMode, embedMode, Conf.Export.FileAnnotationRefMode,
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker, Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight, Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
Conf.Export.AddTitle, Conf.Export.InlineMemo, nil, true, fillCSSVar, &map[string]*parse.Tree{}) Conf.Export.AddTitle, Conf.Export.InlineMemo, nil, true, fillCSSVar, map[string]*parse.Tree{})
docIAL := parse.IAL2Map(tree.Root.KramdownIAL) docIAL := parse.IAL2Map(tree.Root.KramdownIAL)
if addYfm { if addYfm {
exportedMd = yfm(docIAL) + exportedMd exportedMd = yfm(docIAL) + exportedMd
@ -2020,7 +2022,7 @@ func ExportMarkdownContent(id string, refMode, embedMode int, addYfm, fillCSSVar
return return
} }
func exportMarkdownContent(id, ext string, exportRefMode int, defBlockIDs []string, singleFile bool, treeCache *map[string]*parse.Tree) (tree *parse.Tree, exportedMd string, isEmpty bool) { func exportMarkdownContent(id, ext string, exportRefMode int, defBlockIDs []string, singleFile bool, treeCache map[string]*parse.Tree) (tree *parse.Tree, exportedMd string, isEmpty bool) {
tree, err := loadTreeWithCache(id, treeCache) tree, err := loadTreeWithCache(id, treeCache)
if err != nil { if err != nil {
logging.LogErrorf("load tree by block id [%s] failed: %s", id, err) logging.LogErrorf("load tree by block id [%s] failed: %s", id, err)
@ -2055,7 +2057,7 @@ func exportMarkdownContent(id, ext string, exportRefMode int, defBlockIDs []stri
func exportMarkdownContent0(id string, tree *parse.Tree, cloudAssetsBase string, assetsDestSpace2Underscore, adjustHeadingLv, imgTag bool, func exportMarkdownContent0(id string, tree *parse.Tree, cloudAssetsBase string, assetsDestSpace2Underscore, adjustHeadingLv, imgTag bool,
ext string, blockRefMode, blockEmbedMode, fileAnnotationRefMode int, ext string, blockRefMode, blockEmbedMode, fileAnnotationRefMode int,
tagOpenMarker, tagCloseMarker string, blockRefTextLeft, blockRefTextRight string, tagOpenMarker, tagCloseMarker string, blockRefTextLeft, blockRefTextRight string,
addTitle, inlineMemo bool, defBlockIDs []string, singleFile, fillCSSVar bool, treeCache *map[string]*parse.Tree) (ret string) { addTitle, inlineMemo bool, defBlockIDs []string, singleFile, fillCSSVar bool, treeCache map[string]*parse.Tree) (ret string) {
tree = exportTree(tree, false, false, false, tree = exportTree(tree, false, false, false,
blockRefMode, blockEmbedMode, fileAnnotationRefMode, blockRefMode, blockEmbedMode, fileAnnotationRefMode,
tagOpenMarker, tagCloseMarker, tagOpenMarker, tagCloseMarker,
@ -2182,11 +2184,11 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
blockRefMode, blockEmbedMode, fileAnnotationRefMode int, blockRefMode, blockEmbedMode, fileAnnotationRefMode int,
tagOpenMarker, tagCloseMarker string, tagOpenMarker, tagCloseMarker string,
blockRefTextLeft, blockRefTextRight string, blockRefTextLeft, blockRefTextRight string,
addTitle, inlineMemo, addDocAnchorSpan, singleFile bool, treeCache *map[string]*parse.Tree) (ret *parse.Tree) { addTitle, inlineMemo, addDocAnchorSpan, singleFile bool, treeCache map[string]*parse.Tree) (ret *parse.Tree) {
luteEngine := NewLute() luteEngine := NewLute()
ret = tree ret = tree
id := tree.Root.ID id := tree.Root.ID
(*treeCache)[tree.ID] = tree treeCache[tree.ID] = tree
// 解析查询嵌入节点 // 解析查询嵌入节点
depth := 0 depth := 0
@ -2544,7 +2546,9 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
table := getAttrViewTable(attrView, view, "") table := getAttrViewTable(attrView, view, "")
// 遵循视图过滤和排序规则 Use filtering and sorting of current view settings when exporting database blocks https://github.com/siyuan-note/siyuan/issues/10474 // 遵循视图过滤和排序规则 Use filtering and sorting of current view settings when exporting database blocks https://github.com/siyuan-note/siyuan/issues/10474
av.Filter(table, attrView) cachedAttrViews := map[string]*av.AttributeView{}
rollupFurtherCollections := sql.GetFurtherCollections(attrView, cachedAttrViews)
av.Filter(table, attrView, rollupFurtherCollections, cachedAttrViews)
av.Sort(table, attrView) av.Sort(table, attrView)
var aligns []int var aligns []int
@ -2821,7 +2825,7 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
return ret return ret
} }
func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, currentTree *parse.Tree, currentTreeNodeIDs map[string]bool, blockRefTextLeft, blockRefTextRight string, treeCache *map[string]*parse.Tree) (footnotesDefBlock *ast.Node) { func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, currentTree *parse.Tree, currentTreeNodeIDs map[string]bool, blockRefTextLeft, blockRefTextRight string, treeCache map[string]*parse.Tree) (footnotesDefBlock *ast.Node) {
if 1 > len(*refFootnotes) { if 1 > len(*refFootnotes) {
return nil return nil
} }
@ -2955,7 +2959,7 @@ func resolveFootnotesDefs(refFootnotes *[]*refAsFootnotes, currentTree *parse.Tr
return return
} }
func blockLink2Ref(currentTree *parse.Tree, id string, treeCache *map[string]*parse.Tree, depth *int) { func blockLink2Ref(currentTree *parse.Tree, id string, treeCache map[string]*parse.Tree, depth *int) {
*depth++ *depth++
if 4096 < *depth { if 4096 < *depth {
return return
@ -2985,7 +2989,7 @@ func blockLink2Ref(currentTree *parse.Tree, id string, treeCache *map[string]*pa
return return
} }
func blockLink2Ref0(currentTree *parse.Tree, node *ast.Node, treeCache *map[string]*parse.Tree, depth *int) { func blockLink2Ref0(currentTree *parse.Tree, node *ast.Node, treeCache map[string]*parse.Tree, depth *int) {
ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus { ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering { if !entering {
return ast.WalkContinue return ast.WalkContinue
@ -3006,7 +3010,7 @@ func blockLink2Ref0(currentTree *parse.Tree, node *ast.Node, treeCache *map[stri
}) })
} }
func collectFootnotesDefs(currentTree *parse.Tree, id string, refFootnotes *[]*refAsFootnotes, treeCache *map[string]*parse.Tree, depth *int) { func collectFootnotesDefs(currentTree *parse.Tree, id string, refFootnotes *[]*refAsFootnotes, treeCache map[string]*parse.Tree, depth *int) {
*depth++ *depth++
if 4096 < *depth { if 4096 < *depth {
return return
@ -3035,7 +3039,7 @@ func collectFootnotesDefs(currentTree *parse.Tree, id string, refFootnotes *[]*r
return return
} }
func collectFootnotesDefs0(currentTree *parse.Tree, node *ast.Node, refFootnotes *[]*refAsFootnotes, treeCache *map[string]*parse.Tree, depth *int) { func collectFootnotesDefs0(currentTree *parse.Tree, node *ast.Node, refFootnotes *[]*refAsFootnotes, treeCache map[string]*parse.Tree, depth *int) {
ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus { ast.Walk(node, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering { if !entering {
return ast.WalkContinue return ast.WalkContinue
@ -3143,7 +3147,7 @@ func processFileAnnotationRef(refID string, n *ast.Node, fileAnnotationRefMode i
} }
func exportPandocConvertZip(baseFolderName string, docPaths, defBlockIDs []string, func exportPandocConvertZip(baseFolderName string, docPaths, defBlockIDs []string,
pandocFrom, pandocTo, ext string, treeCache *map[string]*parse.Tree) (zipPath string) { pandocFrom, pandocTo, ext string, treeCache map[string]*parse.Tree) (zipPath string) {
defer util.ClearPushProgress(100) defer util.ClearPushProgress(100)
dir, name := path.Split(baseFolderName) dir, name := path.Split(baseFolderName)
@ -3296,9 +3300,9 @@ func getExportBlockRefLinkText(blockRef *ast.Node, blockRefTextLeft, blockRefTex
return return
} }
func prepareExportTrees(docPaths []string) (defBlockIDs []string, trees *map[string]*parse.Tree, relatedDocPaths []string) { func prepareExportTrees(docPaths []string) (defBlockIDs []string, trees map[string]*parse.Tree, relatedDocPaths []string) {
trees = &map[string]*parse.Tree{} trees = map[string]*parse.Tree{}
treeCache := &map[string]*parse.Tree{} treeCache := map[string]*parse.Tree{}
defBlockIDs = []string{} defBlockIDs = []string{}
for i, p := range docPaths { for i, p := range docPaths {
rootID := strings.TrimSuffix(path.Base(p), ".sy") rootID := strings.TrimSuffix(path.Base(p), ".sy")
@ -3315,18 +3319,18 @@ func prepareExportTrees(docPaths []string) (defBlockIDs []string, trees *map[str
util.PushEndlessProgress(Conf.language(65) + " " + fmt.Sprintf(Conf.language(70), fmt.Sprintf("%d/%d %s", i+1, len(docPaths), tree.Root.IALAttr("title")))) util.PushEndlessProgress(Conf.language(65) + " " + fmt.Sprintf(Conf.language(70), fmt.Sprintf("%d/%d %s", i+1, len(docPaths), tree.Root.IALAttr("title"))))
} }
for _, tree := range *trees { for _, tree := range trees {
relatedDocPaths = append(relatedDocPaths, tree.Path) relatedDocPaths = append(relatedDocPaths, tree.Path)
} }
relatedDocPaths = gulu.Str.RemoveDuplicatedElem(relatedDocPaths) relatedDocPaths = gulu.Str.RemoveDuplicatedElem(relatedDocPaths)
return return
} }
func exportRefTrees(tree *parse.Tree, defBlockIDs *[]string, retTrees, treeCache *map[string]*parse.Tree) { func exportRefTrees(tree *parse.Tree, defBlockIDs *[]string, retTrees, treeCache map[string]*parse.Tree) {
if nil != (*retTrees)[tree.ID] { if nil != retTrees[tree.ID] {
return return
} }
(*retTrees)[tree.ID] = tree retTrees[tree.ID] = tree
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus { ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering { if !entering {
@ -3345,14 +3349,14 @@ func exportRefTrees(tree *parse.Tree, defBlockIDs *[]string, retTrees, treeCache
var defTree *parse.Tree var defTree *parse.Tree
var err error var err error
if (*treeCache)[defBlock.RootID] != nil { if treeCache[defBlock.RootID] != nil {
defTree = (*treeCache)[defBlock.RootID] defTree = treeCache[defBlock.RootID]
} else { } else {
defTree, err = loadTreeWithCache(defBlock.RootID, treeCache) defTree, err = loadTreeWithCache(defBlock.RootID, treeCache)
if err != nil { if err != nil {
return ast.WalkSkipChildren return ast.WalkSkipChildren
} }
(*treeCache)[defBlock.RootID] = defTree treeCache[defBlock.RootID] = defTree
} }
*defBlockIDs = append(*defBlockIDs, defID) *defBlockIDs = append(*defBlockIDs, defID)
@ -3369,14 +3373,14 @@ func exportRefTrees(tree *parse.Tree, defBlockIDs *[]string, retTrees, treeCache
var defTree *parse.Tree var defTree *parse.Tree
var err error var err error
if (*treeCache)[defBlock.RootID] != nil { if treeCache[defBlock.RootID] != nil {
defTree = (*treeCache)[defBlock.RootID] defTree = treeCache[defBlock.RootID]
} else { } else {
defTree, err = loadTreeWithCache(defBlock.RootID, treeCache) defTree, err = loadTreeWithCache(defBlock.RootID, treeCache)
if err != nil { if err != nil {
return ast.WalkSkipChildren return ast.WalkSkipChildren
} }
(*treeCache)[defBlock.RootID] = defTree treeCache[defBlock.RootID] = defTree
} }
*defBlockIDs = append(*defBlockIDs, defID) *defBlockIDs = append(*defBlockIDs, defID)
@ -3412,14 +3416,14 @@ func exportRefTrees(tree *parse.Tree, defBlockIDs *[]string, retTrees, treeCache
var defTree *parse.Tree var defTree *parse.Tree
var err error var err error
if (*treeCache)[defBlock.RootID] != nil { if treeCache[defBlock.RootID] != nil {
defTree = (*treeCache)[defBlock.RootID] defTree = treeCache[defBlock.RootID]
} else { } else {
defTree, err = loadTreeWithCache(defBlock.RootID, treeCache) defTree, err = loadTreeWithCache(defBlock.RootID, treeCache)
if err != nil { if err != nil {
continue continue
} }
(*treeCache)[defBlock.RootID] = defTree treeCache[defBlock.RootID] = defTree
} }
*defBlockIDs = append(*defBlockIDs, val.BlockID) *defBlockIDs = append(*defBlockIDs, val.BlockID)
@ -3432,13 +3436,13 @@ func exportRefTrees(tree *parse.Tree, defBlockIDs *[]string, retTrees, treeCache
*defBlockIDs = gulu.Str.RemoveDuplicatedElem(*defBlockIDs) *defBlockIDs = gulu.Str.RemoveDuplicatedElem(*defBlockIDs)
} }
func loadTreeWithCache(id string, treeCache *map[string]*parse.Tree) (tree *parse.Tree, err error) { func loadTreeWithCache(id string, treeCache map[string]*parse.Tree) (tree *parse.Tree, err error) {
if tree = (*treeCache)[id]; nil != tree { if tree = treeCache[id]; nil != tree {
return return
} }
tree, err = LoadTreeByBlockID(id) tree, err = LoadTreeByBlockID(id)
if nil == err && nil != tree { if nil == err && nil != tree {
(*treeCache)[id] = tree treeCache[id] = tree
} }
return return
} }

View file

@ -187,7 +187,7 @@ func SearchDocsByKeyword(keyword string, flashcard bool) (ret []map[string]strin
} }
} }
rootBlocks = sql.QueryRootBlockByCondition(condition) rootBlocks = sql.QueryRootBlockByCondition(condition, Conf.Search.Limit)
} else { } else {
for _, box := range boxes { for _, box := range boxes {
if flashcard { if flashcard {

View file

@ -981,7 +981,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
if "" == existName { if "" == existName {
name = filepath.Base(absolutePath) name = filepath.Base(absolutePath)
name = util.FilterUploadFileName(name) name = util.FilterUploadFileName(name)
name = util.AssetName(name) name = util.AssetName(name, ast.NewNodeID())
assetTargetPath := filepath.Join(assetDirPath, name) assetTargetPath := filepath.Join(assetDirPath, name)
if err = filelock.Copy(absolutePath, assetTargetPath); err != nil { if err = filelock.Copy(absolutePath, assetTargetPath); err != nil {
logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", absolutePath, assetTargetPath, err) logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", absolutePath, assetTargetPath, err)
@ -1104,7 +1104,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
if "" == existName { if "" == existName {
name = filepath.Base(absolutePath) name = filepath.Base(absolutePath)
name = util.FilterUploadFileName(name) name = util.FilterUploadFileName(name)
name = util.AssetName(name) name = util.AssetName(name, ast.NewNodeID())
assetTargetPath := filepath.Join(assetDirPath, name) assetTargetPath := filepath.Join(assetDirPath, name)
if err = filelock.Copy(absolutePath, assetTargetPath); err != nil { if err = filelock.Copy(absolutePath, assetTargetPath); err != nil {
logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", absolutePath, assetTargetPath, err) logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", absolutePath, assetTargetPath, err)
@ -1249,7 +1249,7 @@ func processBase64Img(n *ast.Node, dest string, assetDirPath string) {
name = alt.TokensStr() + ext name = alt.TokensStr() + ext
} }
name = util.FilterUploadFileName(name) name = util.FilterUploadFileName(name)
name = util.AssetName(name) name = util.AssetName(name, ast.NewNodeID())
tmp := filepath.Join(base64TmpDir, name) tmp := filepath.Join(base64TmpDir, name)
tmpFile, openErr := os.OpenFile(tmp, os.O_RDWR|os.O_CREATE, 0644) tmpFile, openErr := os.OpenFile(tmp, os.O_RDWR|os.O_CREATE, 0644)

View file

@ -203,6 +203,12 @@ func Mount(boxID string) (alreadyMount bool, err error) {
return return
} }
boxes, _ := ListNotebooks()
var sort int
if len(boxes) > 0 {
sort = boxes[0].Sort - 1
}
p := filepath.Join(util.WorkingDir, "guide", boxID) p := filepath.Join(util.WorkingDir, "guide", boxID)
if err = filelock.Copy(p, localPath); err != nil { if err = filelock.Copy(p, localPath); err != nil {
return return
@ -218,6 +224,7 @@ func Mount(boxID string) (alreadyMount bool, err error) {
if box := Conf.Box(boxID); nil != box { if box := Conf.Box(boxID); nil != box {
boxConf := box.GetConf() boxConf := box.GetConf()
boxConf.Closed = true boxConf.Closed = true
boxConf.Sort = sort
box.SaveConf(boxConf) box.SaveConf(boxConf)
} }

View file

@ -31,10 +31,11 @@ import (
// Petal represents a plugin's management status. // Petal represents a plugin's management status.
type Petal struct { type Petal struct {
Name string `json:"name"` // Plugin name Name string `json:"name"` // Plugin name
DisplayName string `json:"displayName"` // Plugin display name DisplayName string `json:"displayName"` // Plugin display name
Enabled bool `json:"enabled"` // Whether enabled Enabled bool `json:"enabled"` // Whether enabled
Incompatible bool `json:"incompatible"` // Whether incompatible Incompatible bool `json:"incompatible"` // Whether incompatible
DisabledInPublish bool `json:"disabledInPublish"` // Whether disabled in publish mode
JS string `json:"js"` // JS code JS string `json:"js"` // JS code
CSS string `json:"css"` // CSS code CSS string `json:"css"` // CSS code
@ -44,7 +45,7 @@ type Petal struct {
func SetPetalEnabled(name string, enabled bool, frontend string) (ret *Petal, err error) { func SetPetalEnabled(name string, enabled bool, frontend string) (ret *Petal, err error) {
petals := getPetals() petals := getPetals()
found, displayName, incompatible := bazaar.ParseInstalledPlugin(name, frontend) found, displayName, incompatible, disabledInPublish := bazaar.ParseInstalledPlugin(name, frontend)
if !found { if !found {
logging.LogErrorf("plugin [%s] not found", name) logging.LogErrorf("plugin [%s] not found", name)
return return
@ -60,6 +61,7 @@ func SetPetalEnabled(name string, enabled bool, frontend string) (ret *Petal, er
ret.DisplayName = displayName ret.DisplayName = displayName
ret.Enabled = enabled ret.Enabled = enabled
ret.Incompatible = incompatible ret.Incompatible = incompatible
ret.DisabledInPublish = disabledInPublish
if incompatible { if incompatible {
err = fmt.Errorf(Conf.Language(205)) err = fmt.Errorf(Conf.Language(205))
@ -72,7 +74,7 @@ func SetPetalEnabled(name string, enabled bool, frontend string) (ret *Petal, er
return return
} }
func LoadPetals(frontend string) (ret []*Petal) { func LoadPetals(frontend string, isPublish bool) (ret []*Petal) {
ret = []*Petal{} ret = []*Petal{}
if Conf.Bazaar.PetalDisabled { if Conf.Bazaar.PetalDisabled {
@ -93,8 +95,8 @@ func LoadPetals(frontend string) (ret []*Petal) {
continue continue
} }
_, petal.DisplayName, petal.Incompatible = bazaar.ParseInstalledPlugin(petal.Name, frontend) _, petal.DisplayName, petal.Incompatible, petal.DisabledInPublish = bazaar.ParseInstalledPlugin(petal.Name, frontend)
if !petal.Enabled || petal.Incompatible { if !petal.Enabled || petal.Incompatible || (isPublish && petal.DisabledInPublish) {
continue continue
} }

View file

@ -587,20 +587,20 @@ func (tx *Transaction) doPrependInsert(operation *Operation) (ret *TxErr) {
if nil == insertedNode { if nil == insertedNode {
return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID} return &TxErr{code: TxErrCodeBlockNotFound, msg: "invalid data tree", id: block.ID}
} }
var remains []*ast.Node
for remain := insertedNode.Next; nil != remain; remain = remain.Next {
if ast.NodeKramdownBlockIAL != remain.Type {
if "" == remain.ID {
remain.ID = ast.NewNodeID()
remain.SetIALAttr("id", remain.ID)
}
remains = append(remains, remain)
}
}
if "" == insertedNode.ID { if "" == insertedNode.ID {
insertedNode.ID = ast.NewNodeID() insertedNode.ID = ast.NewNodeID()
insertedNode.SetIALAttr("id", insertedNode.ID) insertedNode.SetIALAttr("id", insertedNode.ID)
} }
var toInserts []*ast.Node
for toInsert := insertedNode; nil != toInsert; toInsert = toInsert.Next {
if ast.NodeKramdownBlockIAL != toInsert.Type {
if "" == toInsert.ID {
toInsert.ID = ast.NewNodeID()
toInsert.SetIALAttr("id", toInsert.ID)
}
toInserts = append(toInserts, toInsert)
}
}
node := treenode.GetNodeInTree(tree, operation.ParentID) node := treenode.GetNodeInTree(tree, operation.ParentID)
if nil == node { if nil == node {
@ -608,31 +608,45 @@ func (tx *Transaction) doPrependInsert(operation *Operation) (ret *TxErr) {
return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID} return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
} }
isContainer := node.IsContainerBlock() isContainer := node.IsContainerBlock()
for i := len(remains) - 1; 0 <= i; i-- { slices.Reverse(toInserts)
remain := remains[i]
for _, toInsert := range toInserts {
if isContainer { if isContainer {
if ast.NodeListItem == node.Type && 3 == node.ListData.Typ { if ast.NodeList == node.Type {
node.FirstChild.InsertAfter(remain) // 列表下只能挂列表项,所以这里需要分情况处理
if ast.NodeList == toInsert.Type {
var childLis []*ast.Node
for childLi := toInsert.FirstChild; nil != childLi; childLi = childLi.Next {
childLis = append(childLis, childLi)
}
for i := len(childLis) - 1; -1 < i; i-- {
node.PrependChild(childLis[i])
}
} else {
newLiID := ast.NewNodeID()
newLi := &ast.Node{ID: newLiID, Type: ast.NodeListItem, ListData: &ast.ListData{Typ: node.ListData.Typ}}
newLi.SetIALAttr("id", newLiID)
node.PrependChild(newLi)
newLi.AppendChild(toInsert)
}
} else if ast.NodeSuperBlock == node.Type { } else if ast.NodeSuperBlock == node.Type {
node.FirstChild.Next.InsertAfter(remain) layout := node.ChildByType(ast.NodeSuperBlockLayoutMarker)
if nil != layout {
layout.InsertAfter(toInsert)
} else {
node.FirstChild.InsertAfter(toInsert)
}
} else { } else {
node.PrependChild(remain) node.PrependChild(toInsert)
} }
} else { } else {
node.InsertAfter(remain) node.InsertAfter(toInsert)
} }
createdUpdated(toInsert)
tx.nodes[toInsert.ID] = toInsert
} }
if isContainer {
if ast.NodeListItem == node.Type && 3 == node.ListData.Typ {
node.FirstChild.InsertAfter(insertedNode)
} else if ast.NodeSuperBlock == node.Type {
node.FirstChild.Next.InsertAfter(insertedNode)
} else {
node.PrependChild(insertedNode)
}
} else {
node.InsertAfter(insertedNode)
}
createdUpdated(insertedNode) createdUpdated(insertedNode)
tx.nodes[insertedNode.ID] = insertedNode tx.nodes[insertedNode.ID] = insertedNode
if err = tx.writeTree(tree); err != nil { if err = tx.writeTree(tree); err != nil {
@ -692,8 +706,17 @@ func (tx *Transaction) doAppendInsert(operation *Operation) (ret *TxErr) {
return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID} return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
} }
isContainer := node.IsContainerBlock() isContainer := node.IsContainerBlock()
for i := 0; i < len(toInserts); i++ { if !isContainer {
toInsert := toInserts[i] slices.Reverse(toInserts)
}
var lastChildBelowHeading *ast.Node
if ast.NodeHeading == node.Type {
if children := treenode.HeadingChildren(node); 0 < len(children) {
lastChildBelowHeading = children[len(children)-1]
}
}
for _, toInsert := range toInserts {
if isContainer { if isContainer {
if ast.NodeList == node.Type { if ast.NodeList == node.Type {
// 列表下只能挂列表项,所以这里需要分情况处理 https://github.com/siyuan-note/siyuan/issues/9955 // 列表下只能挂列表项,所以这里需要分情况处理 https://github.com/siyuan-note/siyuan/issues/9955
@ -718,8 +741,19 @@ func (tx *Transaction) doAppendInsert(operation *Operation) (ret *TxErr) {
node.AppendChild(toInsert) node.AppendChild(toInsert)
} }
} else { } else {
node.InsertAfter(toInsert) if ast.NodeHeading == node.Type {
if nil != lastChildBelowHeading {
lastChildBelowHeading.InsertAfter(toInsert)
} else {
node.InsertAfter(toInsert)
}
} else {
node.InsertAfter(toInsert)
}
} }
createdUpdated(toInsert)
tx.nodes[toInsert.ID] = toInsert
} }
createdUpdated(insertedNode) createdUpdated(insertedNode)
@ -1248,11 +1282,19 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
node.FirstChild.InsertAfter(remain) node.FirstChild.InsertAfter(remain)
} }
} else { } else {
for i := len(remains) - 1; 0 <= i; i-- { if !node.IsContainerBlock() {
remain := remains[i] for i := len(remains) - 1; 0 <= i; i-- {
node.PrependChild(remain) remain := remains[i]
node.InsertAfter(remain)
}
node.InsertAfter(insertedNode)
} else {
for i := len(remains) - 1; 0 <= i; i-- {
remain := remains[i]
node.PrependChild(remain)
}
node.PrependChild(insertedNode)
} }
node.PrependChild(insertedNode)
} }
} }
} }

View file

@ -43,7 +43,7 @@ import (
func resetTree(tree *parse.Tree, titleSuffix string, removeAvBinding bool) { func resetTree(tree *parse.Tree, titleSuffix string, removeAvBinding bool) {
tree.ID = ast.NewNodeID() tree.ID = ast.NewNodeID()
tree.Root.ID = tree.ID tree.Root.ID = tree.ID
title := tree.Root.IALAttr("title")
if "" != titleSuffix { if "" != titleSuffix {
if t, parseErr := time.Parse("20060102150405", util.TimeFromID(tree.ID)); nil == parseErr { if t, parseErr := time.Parse("20060102150405", util.TimeFromID(tree.ID)); nil == parseErr {
titleSuffix += " " + t.Format("2006-01-02 15:04:05") titleSuffix += " " + t.Format("2006-01-02 15:04:05")
@ -52,9 +52,12 @@ func resetTree(tree *parse.Tree, titleSuffix string, removeAvBinding bool) {
} }
titleSuffix = "(" + titleSuffix + ")" titleSuffix = "(" + titleSuffix + ")"
titleSuffix = " " + titleSuffix titleSuffix = " " + titleSuffix
if Conf.language(16) == title {
titleSuffix = ""
}
} }
tree.Root.SetIALAttr("id", tree.ID) tree.Root.SetIALAttr("id", tree.ID)
tree.Root.SetIALAttr("title", tree.Root.IALAttr("title")+titleSuffix) tree.Root.SetIALAttr("title", title+titleSuffix)
tree.Root.RemoveIALAttr("scroll") tree.Root.RemoveIALAttr("scroll")
p := path.Join(path.Dir(tree.Path), tree.ID) + ".sy" p := path.Join(path.Dir(tree.Path), tree.ID) + ".sy"
tree.Path = p tree.Path = p

View file

@ -25,6 +25,7 @@ import (
"strings" "strings"
"github.com/88250/gulu" "github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/siyuan-note/filelock" "github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
@ -93,7 +94,7 @@ func InsertLocalAssets(id string, assetAbsPaths []string, isUpload bool) (succMa
// 已经存在同样数据的资源文件的话不重复保存 // 已经存在同样数据的资源文件的话不重复保存
succMap[baseName] = existAsset.Path succMap[baseName] = existAsset.Path
} else { } else {
fName = util.AssetName(fName) fName = util.AssetName(fName, ast.NewNodeID())
writePath := filepath.Join(assetsDirPath, fName) writePath := filepath.Join(assetsDirPath, fName)
if _, err = f.Seek(0, io.SeekStart); err != nil { if _, err = f.Seek(0, io.SeekStart); err != nil {
f.Close() f.Close()
@ -163,6 +164,10 @@ func Upload(c *gin.Context) {
for _, file := range files { for _, file := range files {
baseName := file.Filename baseName := file.Filename
_, lastID := util.LastID(baseName)
if !ast.IsNodeIDPattern(lastID) {
lastID = ""
}
needUnzip2Dir := false needUnzip2Dir := false
if gulu.OS.IsDarwin() { if gulu.OS.IsDarwin() {
@ -197,8 +202,17 @@ func Upload(c *gin.Context) {
succMap[baseName] = existAsset.Path succMap[baseName] = existAsset.Path
} else { } else {
if skipIfDuplicated { if skipIfDuplicated {
// https://github.com/siyuan-note/siyuan/issues/10666 // 复制 PDF 矩形注解时不再重复插入图片 No longer upload image repeatedly when copying PDF rectangle annotation https://github.com/siyuan-note/siyuan/issues/10666
matches, globErr := filepath.Glob(assetsDirPath + string(os.PathSeparator) + strings.TrimSuffix(fName, ext) + "*") pattern := assetsDirPath + string(os.PathSeparator) + strings.TrimSuffix(fName, ext)
_, patternLastID := util.LastID(fName)
if lastID != "" && lastID != patternLastID {
// 文件名太长被截断了,通过之前的 lastID 来匹配 PDF files with too long file names cannot generate annotated images https://github.com/siyuan-note/siyuan/issues/15739
pattern = assetsDirPath + string(os.PathSeparator) + "*" + lastID + ext
} else {
pattern += "*" + ext
}
matches, globErr := filepath.Glob(pattern)
if nil != globErr { if nil != globErr {
logging.LogErrorf("glob failed: %s", globErr) logging.LogErrorf("glob failed: %s", globErr)
} else { } else {
@ -211,7 +225,10 @@ func Upload(c *gin.Context) {
} }
} }
fName = util.AssetName(fName) if "" == lastID {
lastID = ast.NewNodeID()
}
fName = util.AssetName(fName, lastID)
writePath := filepath.Join(assetsDirPath, fName) writePath := filepath.Join(assetsDirPath, fName)
tmpDir := filepath.Join(util.TempDir, "convert", "zip", gulu.Rand.String(7)) tmpDir := filepath.Join(util.TempDir, "convert", "zip", gulu.Rand.String(7))
if needUnzip2Dir { if needUnzip2Dir {
@ -248,7 +265,7 @@ func Upload(c *gin.Context) {
fName = strings.TrimSuffix(fName, ext) fName = strings.TrimSuffix(fName, ext)
ext = strings.ToLower(ext) ext = strings.ToLower(ext)
fName += ext fName += ext
fName = util.AssetName(fName) fName = util.AssetName(fName, ast.NewNodeID())
tmpDir2 := filepath.Join(util.TempDir, "convert", "zip", gulu.Rand.String(7)) tmpDir2 := filepath.Join(util.TempDir, "convert", "zip", gulu.Rand.String(7))
if err = gulu.Zip.Unzip(writePath, tmpDir2); err != nil { if err = gulu.Zip.Unzip(writePath, tmpDir2); err != nil {
errFiles = append(errFiles, fName) errFiles = append(errFiles, fName)

View file

@ -74,11 +74,13 @@ func RenderView(attrView *av.AttributeView, view *av.View, query string) (ret av
renderedAttrViews := map[string]*av.AttributeView{} renderedAttrViews := map[string]*av.AttributeView{}
renderedAttrViews[attrView.ID] = attrView renderedAttrViews[attrView.ID] = attrView
ret = renderView(attrView, view, query, &depth, renderedAttrViews) ret = renderView(attrView, view, query, &depth, renderedAttrViews)
attrView.RenderedViewables[ret.GetID()] = ret
renderedAttrViews[attrView.ID] = attrView
return return
} }
func renderView(attrView *av.AttributeView, view *av.View, query string, func renderView(attrView *av.AttributeView, view *av.View, query string, depth *int, cachedAttrViews map[string]*av.AttributeView) (ret av.Viewable) {
depth *int, cachedAttrViews map[string]*av.AttributeView) (ret av.Viewable) {
if 7 < *depth { if 7 < *depth {
return return
} }
@ -280,10 +282,10 @@ func generateAttrViewItems(attrView *av.AttributeView, view *av.View) (ret map[s
return return
} }
func filterNotFoundAttrViewItems(keyValuesMap *map[string][]*av.KeyValues) { func filterNotFoundAttrViewItems(keyValuesMap map[string][]*av.KeyValues) {
var notFound []string var notFound []string
var toCheckBlockIDs []string var toCheckBlockIDs []string
for blockID, keyValues := range *keyValuesMap { for blockID, keyValues := range keyValuesMap {
blockValue := getBlockValue(keyValues) blockValue := getBlockValue(keyValues)
if nil == blockValue || nil == blockValue.Block { if nil == blockValue || nil == blockValue.Block {
notFound = append(notFound, blockID) notFound = append(notFound, blockID)
@ -308,7 +310,7 @@ func filterNotFoundAttrViewItems(keyValuesMap *map[string][]*av.KeyValues) {
} }
} }
for _, blockID := range notFound { for _, blockID := range notFound {
delete(*keyValuesMap, blockID) delete(keyValuesMap, blockID)
} }
} }
@ -334,9 +336,7 @@ func fillAttributeViewBaseValue(baseValue *av.BaseValue, fieldID, itemID string,
} }
} }
func fillAttributeViewAutoGeneratedValues(attrView *av.AttributeView, collection av.Collection, ials map[string]map[string]string, func fillAttributeViewAutoGeneratedValues(attrView *av.AttributeView, collection av.Collection, ials map[string]map[string]string, depth *int, cachedAttrViews map[string]*av.AttributeView) {
depth *int, cachedAttrViews map[string]*av.AttributeView) {
// 先渲染主键、创建时间、更新时间 // 先渲染主键、创建时间、更新时间
for _, item := range collection.GetItems() { for _, item := range collection.GetItems() {
@ -518,6 +518,45 @@ func fillAttributeViewAutoGeneratedValues(attrView *av.AttributeView, collection
} }
} }
func GetFurtherCollections(attrView *av.AttributeView, cachedAttrViews map[string]*av.AttributeView) (ret map[string]av.Collection) {
ret = map[string]av.Collection{}
for _, kv := range attrView.KeyValues {
if av.KeyTypeRollup != kv.Key.Type {
continue
}
relKey, _ := attrView.GetKey(kv.Key.Rollup.RelationKeyID)
if nil == relKey {
continue
}
destAv := cachedAttrViews[relKey.Relation.AvID]
if nil == destAv {
destAv, _ = av.ParseAttributeView(relKey.Relation.AvID)
if nil == destAv {
continue
}
cachedAttrViews[relKey.Relation.AvID] = destAv
}
destKey, _ := destAv.GetKey(kv.Key.Rollup.KeyID)
if nil == destKey {
continue
}
isSameAv := destAv.ID == attrView.ID
var furtherCollection av.Collection
if av.KeyTypeTemplate == destKey.Type || (!isSameAv && (av.KeyTypeUpdated == destKey.Type || av.KeyTypeCreated == destKey.Type)) {
viewable := RenderView(destAv, destAv.Views[0], "")
if nil != viewable {
furtherCollection = viewable.(av.Collection)
}
}
ret[kv.Key.ID] = furtherCollection
}
return
}
func fillAttributeViewTemplateValues(attrView *av.AttributeView, view *av.View, collection av.Collection, ials map[string]map[string]string) (err error) { func fillAttributeViewTemplateValues(attrView *av.AttributeView, view *av.View, collection av.Collection, ials map[string]map[string]string) (err error) {
items := generateAttrViewItems(attrView, view) items := generateAttrViewItems(attrView, view)
existTemplateField := false existTemplateField := false
@ -591,23 +630,6 @@ func fillAttributeViewKeyValues(attrView *av.AttributeView, collection av.Collec
} }
} }
func mergeKeyValues(kv1, kv2 []*av.KeyValues) (ret []*av.KeyValues) {
ret = kv2
for _, k1 := range kv1 {
found := false
for _, k2 := range kv2 {
if k1.Key.ID == k2.Key.ID {
found = true
break
}
}
if !found {
ret = append(ret, k1)
}
}
return
}
func FillAttributeViewNilValue(value *av.Value, typ av.KeyType) { func FillAttributeViewNilValue(value *av.Value, typ av.KeyType) {
value.Type = typ value.Type = typ
switch typ { switch typ {

View file

@ -18,8 +18,13 @@ import (
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
) )
func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query string, func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query string, depth *int, cachedAttrViews map[string]*av.AttributeView) (ret *av.Gallery) {
depth *int, cachedAttrViews map[string]*av.AttributeView) (ret *av.Gallery) { viewable := attrView.RenderedViewables[view.ID]
if nil != viewable {
ret = viewable.(*av.Gallery)
return
}
ret = &av.Gallery{ ret = &av.Gallery{
BaseInstance: av.NewViewBaseInstance(view), BaseInstance: av.NewViewBaseInstance(view),
CoverFrom: view.Gallery.CoverFrom, CoverFrom: view.Gallery.CoverFrom,
@ -62,7 +67,7 @@ func RenderAttributeViewGallery(attrView *av.AttributeView, view *av.View, query
} }
cardsValues := generateAttrViewItems(attrView, view) // 生成卡片 cardsValues := generateAttrViewItems(attrView, view) // 生成卡片
filterNotFoundAttrViewItems(&cardsValues) // 过滤掉不存在的卡片 filterNotFoundAttrViewItems(cardsValues) // 过滤掉不存在的卡片
// 批量加载绑定块对应的树 // 批量加载绑定块对应的树
var ialIDs []string var ialIDs []string

Some files were not shown because too many files have changed in this diff Show more