Merge branch 'siyuan-note:dev' into dev
This commit is contained in:
commit
5abebc0316
112 changed files with 3288 additions and 1007 deletions
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "Sekunde",
|
||||
"syncInterval": "Synchronisierungsintervall",
|
||||
"removeAV": "Aus der Datenbank entfernen",
|
||||
"empty": "Leer",
|
||||
"newRowInRelation": "Erstellen Sie einen neuen Eintrag in ${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "Beim Wechsel von deaktiviert auf aktiviert wird empfohlen, manuell auf die Synchronisationstaste zu klicken, um eine Synchronisation auszulösen.",
|
||||
"syncMode": "Cloud-Synchronisationsmodus",
|
||||
"syncModeTip": "Der Synchronisationsmodus kann nach der Aktivierung der Cloud-Synchronisation weiter ausgewählt werden.",
|
||||
"syncMode1": "Automatisch (Synchronisation alle 30 Sekunden, nachdem sich die Daten nicht mehr ändern)",
|
||||
"syncMode1": "Automatisch",
|
||||
"syncMode2": "Manuell (automatische Synchronisation nur einmal beim Starten und Schließen der Software, andere Zeitpunkte müssen manuell ausgelöst werden)",
|
||||
"syncMode3": "Vollständige manuelle Synchronisation (keine Synchronisation beim Start und beim Schließen, vollständige manuelle Kontrolle über den Synchronisationszeitpunkt und die Synchronisationsrichtung)",
|
||||
"cloudSync": "Cloud-Synchronisation",
|
||||
|
|
|
@ -768,7 +768,7 @@
|
|||
"openSyncTip2": "When changing from disabled to enabled, it is recommended to manually click the sync button to trigger a synchronization",
|
||||
"syncMode": "Cloud sync mode",
|
||||
"syncModeTip": "The sync mode can be further selected after cloud sync is enabled",
|
||||
"syncMode1": "Auto (sync every 30 seconds after the data no longer changes)",
|
||||
"syncMode1": "Auto",
|
||||
"syncMode2": "Manual (automatic auto only once when the software is started and closed, other times need to manually trigger)",
|
||||
"syncMode3": "Full manual sync (no sync on startup and shutdown, full manual control of sync timing and sync direction)",
|
||||
"cloudSync": "Cloud sync",
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
{
|
||||
"second": "second",
|
||||
"syncInterval": "Sync interval",
|
||||
"second": "segundo",
|
||||
"syncInterval": "intervalo de sincronización",
|
||||
"removeAV": "Eliminar de la base de datos",
|
||||
"empty": "Vacío",
|
||||
"newRowInRelation": "Crear una nueva entrada en ${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +772,7 @@
|
|||
"openSyncTip2": "Al cambiar de desactivado a activado, se recomienda hacer clic manualmente en el botón de sincronización para activar una sincronización",
|
||||
"syncMode": "Modo de sincronización en la nube",
|
||||
"syncModeTip": "El modo de sincronización se puede seguir seleccionando después de habilitar la sincronización en la nube",
|
||||
"syncMode1": "Auto (sincronización cada 30 segundos después de que los datos dejen de cambiar)",
|
||||
"syncMode1": "Auto",
|
||||
"syncMode2": "Manual (automático sólo una vez cuando se inicia y se cierra el software, otras veces hay que activarlo manualmente)",
|
||||
"syncMode3": "Manual Completa (sin sincronización al iniciar y apagar, control manual completo de sincronización y dirección de sincronización)",
|
||||
"cloudSync": "Sincronización en la nube",
|
||||
|
@ -1320,7 +1324,7 @@
|
|||
"quit": "Salir de la aplicación"
|
||||
},
|
||||
"_attrView": {
|
||||
"tabla": "Tabla",
|
||||
"table": "Tabla",
|
||||
"key": "Clave principal",
|
||||
"select": "Selección"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "seconde",
|
||||
"syncInterval": "intervalle de synchronisation",
|
||||
"removeAV": "Supprimer de la base de données",
|
||||
"empty": "Vide",
|
||||
"newRowInRelation": "Créer une nouvelle entrée dans ${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "Lorsque vous passez de la désactivation à l'activation, il est recommandé de cliquer manuellement sur le bouton de synchronisation pour déclencher une synchronisation",
|
||||
"syncMode": "Mode de synchronisation cloud",
|
||||
"syncModeTip": "Le mode de synchronisation peut être sélectionné davantage après l'activation de la synchronisation dans le cloud",
|
||||
"syncMode1": "Automatique (synchronisation toutes les 30 secondes après que les données ne changent plus)",
|
||||
"syncMode1": "Automatique",
|
||||
"syncMode2": "Manuelle (synchronisation automatique une seule fois lorsque le logiciel est démarré et fermé, les autres fois, il faut déclencher manuellement la synchronisation)",
|
||||
"syncMode3": "Manuelle Complète (pas de synchronisation au démarrage et à l'arrêt, contrôle manuel complet de la synchronisation et du sens de synchronisation)",
|
||||
"cloudSync": "Cloud Sync",
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "שנייה",
|
||||
"syncInterval": "מרווח סנכרון",
|
||||
"removeAV": "הסר ממסד הנתונים",
|
||||
"empty": "ריק",
|
||||
"newRowInRelation": "צור ערך חדש ב-${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "כאשר אתה משנה מ-מושבת ל-פעיל, מומלץ ללחוץ ידנית על כפתור הסנכרון כדי להפעיל סנכרון",
|
||||
"syncMode": "מצב סנכרון בענן",
|
||||
"syncModeTip": "מצב הסנכרון ניתן לבחירה נוספת לאחר שהסנכרון בענן הופעל",
|
||||
"syncMode1": "אוטומטי (סנכרון כל 30 שניות לאחר שהנתונים לא משתנים יותר)",
|
||||
"syncMode1": "אוטומטי",
|
||||
"syncMode2": "ידני (אוטומטית בהחלט פעם אחת בעת הפעלת התוכנה והכיבוי, פעמים אחרות יש להפעיל ידנית)",
|
||||
"syncMode3": "סנכרון ידני מלא (אין סנכרון בעת הפעלה וכיבוי, את שליטת הזמן והכיוונים של הסנכרון באופן ידני)",
|
||||
"cloudSync": "סנכרון בענן",
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "secondo",
|
||||
"syncInterval": "intervallo di sincronizzazione",
|
||||
"removeAV": "Rimuovi dal database",
|
||||
"empty": "Vuoto",
|
||||
"newRowInRelation": "Crea una nuova voce in ${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "Quando si cambia da disabilitato ad abilitato, si consiglia di fare clic manualmente sul pulsante di sincronizzazione per avviare la sincronizzazione",
|
||||
"syncMode": "Modalità di sincronizzazione cloud",
|
||||
"syncModeTip": "La modalità di sincronizzazione può essere ulteriormente selezionata dopo l'abilitazione della sincronizzazione cloud",
|
||||
"syncMode1": "Auto (sincronizza ogni 30 secondi dopo che i dati non cambiano più)",
|
||||
"syncMode1": "Auto",
|
||||
"syncMode2": "Manuale (auto automatico solo una volta quando il software viene avviato e chiuso, altre volte richiede l'attivazione manuale)",
|
||||
"syncMode3": "Sincronizzazione completamente manuale (nessuna sincronizzazione all'avvio e alla chiusura, controllo manuale completo del momento e della direzione della sincronizzazione)",
|
||||
"cloudSync": "Sincronizzazione cloud",
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "秒",
|
||||
"syncInterval": "同期間隔",
|
||||
"removeAV": "データベースから削除",
|
||||
"empty": "空白",
|
||||
"newRowInRelation": "${x} に新しい項目を作成 <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "無効から有効に変更した場合は手動で同期ボタンをクリックして同期をトリガーすることをお勧めします",
|
||||
"syncMode": "クラウド同期モード",
|
||||
"syncModeTip": "クラウド同期を有効にすると同期モードを選択できます",
|
||||
"syncMode1": "自動 (起動時と終了時に同期され、アプリケーションの使用中は同期アルゴリズムにしたがって自動的に同期されます)",
|
||||
"syncMode1": "自動",
|
||||
"syncMode2": "手動 (起動時と終了時に一度だけ同期され、それ以外の場合は手動で同期をトリガーする必要があります)",
|
||||
"syncMode3": "完全手動同期 (起動と終了時に同期されず、同期タイミングと同期方向をすべて手動で制御します)",
|
||||
"cloudSync": "クラウド同期",
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "sekunda",
|
||||
"syncInterval": "interwał synchronizacji",
|
||||
"removeAV": "Usuń z bazy danych",
|
||||
"empty": "Pusty",
|
||||
"newRowInRelation": "Utwórz nowy wpis w ${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "Podczas zmiany z wyłączonej na włączoną, zaleca się ręczne kliknięcie przycisku synchronizacji, aby wyzwolić synchronizację",
|
||||
"syncMode": "Tryb synchronizacji w chmurze",
|
||||
"syncModeTip": "Tryb synchronizacji można dalej wybrać po włączeniu synchronizacji w chmurze",
|
||||
"syncMode1": "Auto (synchronizacja co 30 sekund po tym, jak dane przestają się zmieniać)",
|
||||
"syncMode1": "Auto",
|
||||
"syncMode2": "Ręczny (automatyczna synchronizacja tylko raz przy uruchamianiu i zamykaniu oprogramowania, inne czasy wymagają ręcznego wyzwolenia)",
|
||||
"syncMode3": "W pełni ręczna synchronizacja (brak synchronizacji przy uruchamianiu i zamykaniu, pełna ręczna kontrola nad czasem synchronizacji i kierunkiem synchronizacji)",
|
||||
"cloudSync": "Synchronizacja w chmurze",
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "секунда",
|
||||
"syncInterval": "интервал синхронизации",
|
||||
"removeAV": "Удалить из базы данных",
|
||||
"empty": "Пусто",
|
||||
"newRowInRelation": "Создать новую запись в ${x} <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "При изменении с отключенного на включенное рекомендуется вручную нажать кнопку синхронизации для запуска синхронизации",
|
||||
"syncMode": "Режим облачной синхронизации",
|
||||
"syncModeTip": "Режим синхронизации можно дополнительно выбрать после включения облачной синхронизации",
|
||||
"syncMode1": "Авто (синхронизация каждые 30 секунд, когда данные больше не изменяются)",
|
||||
"syncMode1": "Авто",
|
||||
"syncMode2": "Ручной (автоматическая синхронизация только один раз при запуске и закрытии программы, в другие разы необходимо вручную запустить)",
|
||||
"syncMode3": "Полная ручная синхронизация (не синхронизируется при запуске и завершении, полный ручной контроль времени и направления синхронизации)",
|
||||
"cloudSync": "Облачная синхронизация",
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
{
|
||||
"second": "秒",
|
||||
"syncInterval": "同步間隔",
|
||||
"removeAV": "從資料庫中移除",
|
||||
"empty": "空白",
|
||||
"newRowInRelation": "在 ${x} 中新建條目 <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +770,7 @@
|
|||
"openSyncTip2": "從禁用改為啟用時建議手動點擊同步按鈕觸發一次同步",
|
||||
"syncMode": "雲端同步模式",
|
||||
"syncModeTip": "啟用雲端同步後可進一步選擇同步模式",
|
||||
"syncMode1": "自動同步(資料不再變動後 30 秒進行一次同步)",
|
||||
"syncMode1": "自動同步",
|
||||
"syncMode2": "手動同步(僅啟動和關閉軟體時自動同步一次,其他時候需要手動觸發同步)",
|
||||
"syncMode3": "完全手動同步(啟動和關閉時均不同步,完全手動控制同步時機和同步方向)",
|
||||
"cloudSync": "雲端同步",
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
{
|
||||
"second": "秒",
|
||||
"syncInterval": "同步间隔",
|
||||
"syncIntervalTip": "数据不再变动后自动进行数据同步",
|
||||
"removeAV": "从数据库中移除",
|
||||
"empty": "空白",
|
||||
"newRowInRelation": "在 ${x} 中新建条目 <b class='ft__on-surface'>${y}</b>",
|
||||
|
@ -768,7 +771,7 @@
|
|||
"openSyncTip2": "从禁用改为启用时建议手动点击同步按钮触发一次同步",
|
||||
"syncMode": "云端同步模式",
|
||||
"syncModeTip": "启用云端同步后可进一步选择同步模式",
|
||||
"syncMode1": "自动同步(数据不再变动后 30 秒进行一次同步)",
|
||||
"syncMode1": "自动同步",
|
||||
"syncMode2": "手动同步(仅启动和关闭软件时自动同步一次,其他时候需要手动触发同步)",
|
||||
"syncMode3": "完全手动同步(启动和关闭时均不同步,完全手动控制同步时机和同步方向)",
|
||||
"cloudSync": "云端同步",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
--b3-theme-primary-light: rgba(53, 117, 240, .54);
|
||||
--b3-theme-primary-lighter: rgba(53, 117, 240, .38);
|
||||
--b3-theme-primary-lightest: rgba(53, 117, 240, .12);
|
||||
--b3-theme-secondary: #f3a92f;
|
||||
--b3-theme-secondary: #ff9200;
|
||||
--b3-theme-background: #fff;
|
||||
--b3-theme-background-light: #dfe0e1;
|
||||
--b3-theme-surface: #f6f6f6;
|
||||
|
@ -23,11 +23,11 @@
|
|||
|
||||
/* 字体 */
|
||||
/* Windows 斜体遮挡添加 "Segoe UI" 字体 https://github.com/siyuan-note/siyuan/issues/11841 */
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans GB", "Segoe UI", "Microsoft Yahei", sans-serif, "Apple Color Emoji", "Noto Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Android Emoji", "EmojiSymbols";
|
||||
--b3-font-family-protyle: var(--b3-font-family);
|
||||
--b3-font-family-code: "JetBrainsMono-Regular", mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, var(--b3-font-family);
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Segoe UI", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
--b3-font-family-protyle: "Number Glyphs", "SiYuan Emojis", var(--b3-font-family);
|
||||
--b3-font-family-code: "Number Glyphs Of JetBrainsMono-Regular", "SiYuan Emojis", "JetBrainsMono-Regular", mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, var(--b3-font-family);
|
||||
--b3-font-family-graph: arial;
|
||||
--b3-font-family-emoji: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji";
|
||||
--b3-font-family-emoji: "SiYuan Emojis", "Emojis";
|
||||
--b3-font-family-math: KaTeX_Math;
|
||||
--b3-font-size: 14px;
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
|||
/* 线条 */
|
||||
--b3-border-color: var(--b3-theme-surface-lighter);
|
||||
--b3-border-radius: 6px;
|
||||
--b3-border-radius-s: 3px;
|
||||
--b3-border-radius-b: 12px;
|
||||
|
||||
/* 滚动条 */
|
||||
|
@ -66,13 +67,13 @@
|
|||
--b3-mask-background: rgba(220, 220, 220, .4);
|
||||
|
||||
/* 卡片背景 */
|
||||
--b3-card-error-color: rgb(97, 26, 21);
|
||||
--b3-card-error-color: #790600;
|
||||
--b3-card-error-background: #f5d1cf;
|
||||
--b3-card-warning-color: rgb(102, 60, 0);
|
||||
--b3-card-warning-color: #b16700;
|
||||
--b3-card-warning-background: #ffe8c8;
|
||||
--b3-card-info-color: rgb(13, 60, 97);
|
||||
--b3-card-info-color: #005599;
|
||||
--b3-card-info-background: #d6eaf9;
|
||||
--b3-card-success-color: rgb(30, 70, 32);
|
||||
--b3-card-success-color: #008606;
|
||||
--b3-card-success-background: #d7eed8;
|
||||
|
||||
/* 自定义文字 */
|
||||
|
@ -85,9 +86,9 @@
|
|||
--b3-font-color7: var(--b3-theme-secondary);
|
||||
--b3-font-color8: var(--b3-theme-error);
|
||||
--b3-font-color9: #f5539e;
|
||||
--b3-font-color10: #944194;
|
||||
--b3-font-color11: #65b84d;
|
||||
--b3-font-color12: #f5822e;
|
||||
--b3-font-color10: #00cdcd;
|
||||
--b3-font-color11: #00b853;
|
||||
--b3-font-color12: #9e9700;
|
||||
--b3-font-color13: var(--b3-theme-background);
|
||||
--b3-font-background1: var(--b3-card-error-background);
|
||||
--b3-font-background2: var(--b3-card-warning-background);
|
||||
|
@ -95,12 +96,12 @@
|
|||
--b3-font-background4: var(--b3-card-success-background);
|
||||
--b3-font-background5: #e2e3e4;
|
||||
--b3-font-background6: #acd0fc;
|
||||
--b3-font-background7: #fdeed6;
|
||||
--b3-font-background8: #fae1cf;
|
||||
--b3-font-background9: #fdd5e7;
|
||||
--b3-font-background10: #e6c7e6;
|
||||
--b3-font-background11: #def0d9;
|
||||
--b3-font-background12: #fae3e4;
|
||||
--b3-font-background7: #fddaab;
|
||||
--b3-font-background8: #ffb0a9;
|
||||
--b3-font-background9: #fdbfff;
|
||||
--b3-font-background10: #b1ffff;
|
||||
--b3-font-background11: #affad1;
|
||||
--b3-font-background12: #fff88f;
|
||||
--b3-font-background13: var(--b3-theme-on-background);
|
||||
|
||||
/* 动画效果 */
|
||||
|
@ -200,8 +201,16 @@
|
|||
--b3-parent-background: var(--b3-theme-background);
|
||||
}
|
||||
|
||||
:lang(ja_JP):root {
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Yu Gothic UI", "Segoe UI", sans-serif, "Apple Color Emoji", "Noto Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Android Emoji", "EmojiSymbols";
|
||||
:root:lang(zh_CN) {
|
||||
--b3-font-family: "Helvetica Neue", "PingFang SC", "Luxi Sans", "DejaVu Sans", "Hiragino Sans GB", "Segoe UI", "Source Han Sans SC", "Microsoft Yahei", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
}
|
||||
|
||||
:root:lang(zh_CHT) {
|
||||
--b3-font-family: "Helvetica Neue", "PingFang TC", "Luxi Sans", "DejaVu Sans", "Hiragino Sans TC", "Segoe UI", "Source Han Sans TC", "Microsoft JhengHei", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
}
|
||||
|
||||
:root:lang(ja_JP) {
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Yu Gothic UI", "Segoe UI", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
}
|
||||
|
||||
/* https://github.com/siyuan-note/siyuan/issues/6440 */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "daylight",
|
||||
"author": "Vanessa",
|
||||
"url": "https://github.com/Vanessa219",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"modes": [
|
||||
"light"
|
||||
]
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
--b3-theme-on-error: #fff;
|
||||
|
||||
/* 字体 */
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans GB", "Segoe UI", "Microsoft Yahei", sans-serif, "Apple Color Emoji", "Noto Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Android Emoji", "EmojiSymbols";
|
||||
--b3-font-family-protyle: var(--b3-font-family);
|
||||
--b3-font-family-code: "JetBrainsMono-Regular", mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, var(--b3-font-family);
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Segoe UI", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
--b3-font-family-protyle: "Number Glyphs", "SiYuan Emojis", var(--b3-font-family);
|
||||
--b3-font-family-code: "Number Glyphs Of JetBrainsMono-Regular", "SiYuan Emojis", "JetBrainsMono-Regular", mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, var(--b3-font-family);
|
||||
--b3-font-family-graph: arial;
|
||||
--b3-font-family-emoji: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji";
|
||||
--b3-font-family-emoji: "SiYuan Emojis", "Emojis";
|
||||
--b3-font-family-math: KaTeX_Math;
|
||||
--b3-font-size: 14px;
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
|||
/* 线条 */
|
||||
--b3-border-color: #363636;
|
||||
--b3-border-radius: 6px;
|
||||
--b3-border-radius-s: 3px;
|
||||
--b3-border-radius-b: 12px;
|
||||
|
||||
/* 滚动条 */
|
||||
|
@ -84,22 +85,22 @@
|
|||
--b3-font-color7: var(--b3-theme-secondary);
|
||||
--b3-font-color8: var(--b3-theme-error);
|
||||
--b3-font-color9: #f5539e;
|
||||
--b3-font-color10: #bc67bc;
|
||||
--b3-font-color11: #65b84d;
|
||||
--b3-font-color12: #f5822e;
|
||||
--b3-font-color10: #00eeff;
|
||||
--b3-font-color11: #74ff00;
|
||||
--b3-font-color12: #fff200;
|
||||
--b3-font-color13: var(--b3-theme-background);
|
||||
--b3-font-background1: var(--b3-card-error-background);
|
||||
--b3-font-background2: var(--b3-card-warning-background);
|
||||
--b3-font-background3: var(--b3-card-info-background);
|
||||
--b3-font-background4: var(--b3-card-success-background);
|
||||
--b3-font-background5: #4c5257;
|
||||
--b3-font-background6: #0c3d88;
|
||||
--b3-font-background6: #08296c;
|
||||
--b3-font-background7: #593905;
|
||||
--b3-font-background8: #541812;
|
||||
--b3-font-background9: #6a0634;
|
||||
--b3-font-background10: #6b2f6b;
|
||||
--b3-font-background11: #376629;
|
||||
--b3-font-background12: #803a06;
|
||||
--b3-font-background9: #843473;
|
||||
--b3-font-background10: #329096;
|
||||
--b3-font-background11: #568b2a;
|
||||
--b3-font-background12: #8d8829;
|
||||
--b3-font-background13: var(--b3-theme-on-background);
|
||||
|
||||
/* 动画效果 */
|
||||
|
@ -199,8 +200,16 @@
|
|||
--b3-parent-background: var(--b3-theme-background);
|
||||
}
|
||||
|
||||
:lang(ja_JP):root {
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Yu Gothic UI", "Segoe UI", sans-serif, "Apple Color Emoji", "Noto Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Android Emoji", "EmojiSymbols";
|
||||
:root:lang(zh_CN) {
|
||||
--b3-font-family: "Helvetica Neue", "PingFang SC", "Luxi Sans", "DejaVu Sans", "Hiragino Sans GB", "Segoe UI", "Source Han Sans SC", "Microsoft Yahei", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
}
|
||||
|
||||
:root:lang(zh_CHT) {
|
||||
--b3-font-family: "Helvetica Neue", "PingFang TC", "Luxi Sans", "DejaVu Sans", "Hiragino Sans TC", "Segoe UI", "Source Han Sans TC", "Microsoft JhengHei", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
}
|
||||
|
||||
:root:lang(ja_JP) {
|
||||
--b3-font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans", "Yu Gothic UI", "Segoe UI", sans-serif, "Arial", "Tahoma", "Emojis";
|
||||
}
|
||||
|
||||
/* https://github.com/siyuan-note/siyuan/issues/6440 */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"name": "midnight",
|
||||
"author": "Vanessa",
|
||||
"url": "https://github.com/Vanessa219",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"modes": [
|
||||
"dark"
|
||||
]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<Identity Name="89C2A984.SiYuan"
|
||||
ProcessorArchitecture="x64"
|
||||
Publisher="CN=087C656E-C1D9-42D8-8807-CED45A74FC0F"
|
||||
Version="3.1.14.0"/>
|
||||
Version="3.1.15.0"/>
|
||||
<Properties>
|
||||
<DisplayName>SiYuan</DisplayName>
|
||||
<PublisherDisplayName>云南链滴科技有限公司</PublisherDisplayName>
|
||||
|
|
53
app/changelogs/v3.1.15/v3.1.15.md
Normal file
53
app/changelogs/v3.1.15/v3.1.15.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
## Overview
|
||||
|
||||
This version supports use on the HarmonyOS NEXT system.
|
||||
|
||||
## Changelogs
|
||||
|
||||
Below are the detailed changes in this version.
|
||||
|
||||
### Enhancement
|
||||
|
||||
* [Improve Alt+M hiding/showing windows](https://github.com/siyuan-note/siyuan/issues/12656)
|
||||
* [Improve database cell positioning and editing input box size](https://github.com/siyuan-note/siyuan/issues/12708)
|
||||
* [Support HarmonyOS NEXT system](https://github.com/siyuan-note/siyuan/issues/13184)
|
||||
* [Remove the collapsed state of the collapsed heading on paste](https://github.com/siyuan-note/siyuan/issues/13232)
|
||||
* [Support the year in the database date field is less than 4 digits](https://github.com/siyuan-note/siyuan/issues/13252)
|
||||
* [Improve interaction with database descriptions](https://github.com/siyuan-note/siyuan/issues/13262)
|
||||
* [Improve document tag adding interaction](https://github.com/siyuan-note/siyuan/issues/13311)
|
||||
* [Improve tooltip](https://github.com/siyuan-note/siyuan/pull/13326)
|
||||
* [Improve exporting block ref](https://github.com/siyuan-note/siyuan/issues/13331)
|
||||
* [Improve search highlighting](https://github.com/siyuan-note/siyuan/issues/13343)
|
||||
* [Improve template search](https://github.com/siyuan-note/siyuan/issues/13348)
|
||||
* [Improve code block paging when exporting to PDF](https://github.com/siyuan-note/siyuan/issues/13349)
|
||||
* [Improve HTML clipping](https://github.com/siyuan-note/siyuan/issues/13355)
|
||||
* [Improve system font loading](https://github.com/siyuan-note/siyuan/issues/13356)
|
||||
* [Generating block reference with a block that has ' character is causing weird behaviour](https://github.com/siyuan-note/siyuan/issues/13358)
|
||||
* [Simplify document block paths in search results](https://github.com/siyuan-note/siyuan/issues/13364)
|
||||
* [The browser clipping extension adds some experimental features](https://github.com/siyuan-note/siyuan/issues/13366)
|
||||
* [Attribute panel - Database supports removing the current block](https://github.com/siyuan-note/siyuan/issues/13375)
|
||||
* [Support flac audio asset playback](https://github.com/siyuan-note/siyuan/issues/13386)
|
||||
* [Cannot double-click to preview them when image url include `%`](https://github.com/siyuan-note/siyuan/issues/13388)
|
||||
* [Using the middle button to close a tab triggers pasting on Linux](https://github.com/siyuan-note/siyuan/pull/13395)
|
||||
* [Improve setting appearance priority](https://github.com/siyuan-note/siyuan/issues/13404)
|
||||
|
||||
### Bugfix
|
||||
|
||||
* [The document in the mobile data history will be closed when you slide down](https://github.com/siyuan-note/siyuan/issues/13347)
|
||||
* [No results found after clicking on the inline tag](https://github.com/siyuan-note/siyuan/issues/13351)
|
||||
* [HTML tag search escaping issue](https://github.com/siyuan-note/siyuan/issues/13354)
|
||||
* [The sequence number of the ordered list exported to .docx is incorrect](https://github.com/siyuan-note/siyuan/issues/13365)
|
||||
* [File names ending with `.` will be considered as missing assets](https://github.com/siyuan-note/siyuan/issues/13368)
|
||||
* [Full manual sync mode causes data conflicts](https://github.com/siyuan-note/siyuan/issues/13387)
|
||||
|
||||
### Development
|
||||
|
||||
* [Improve the operation of `Backspace` `Delete` `Tab` `Shift+Tab` after selecting a block or table cell](https://github.com/siyuan-note/siyuan/issues/13027)
|
||||
* [Add a kernel API `/api/filetree/moveDocsByID`](https://github.com/siyuan-note/siyuan/issues/13247)
|
||||
* [Remove editor input console log](https://github.com/siyuan-note/siyuan/issues/13346)
|
||||
* [Add `disable`, `enable` method to Protyle](https://github.com/siyuan-note/siyuan/issues/13391)
|
||||
|
||||
## Download
|
||||
|
||||
* [B3log](https://b3log.org/siyuan/en/download.html)
|
||||
* [GitHub](https://github.com/siyuan-note/siyuan/releases)
|
53
app/changelogs/v3.1.15/v3.1.15_zh_CHT.md
Normal file
53
app/changelogs/v3.1.15/v3.1.15_zh_CHT.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
## 概述
|
||||
|
||||
這個版本支持了鴻蒙系統。
|
||||
|
||||
## 變更記錄
|
||||
|
||||
以下是此版本中的詳細變更。
|
||||
|
||||
### 改進功能
|
||||
|
||||
* [改進 Alt+M 隱藏/顯示視窗](https://github.com/siyuan-note/siyuan/issues/12656)
|
||||
* [改進資料庫單元格定位和編輯輸入框大小](https://github.com/siyuan-note/siyuan/issues/12708)
|
||||
* [支援鴻蒙系統](https://github.com/siyuan-note/siyuan/issues/13184)
|
||||
* [貼上時移除折疊標題的折疊狀態](https://github.com/siyuan-note/siyuan/issues/13232)
|
||||
* [支援資料庫日期欄位少於 4 位元的年份](https://github.com/siyuan-note/siyuan/issues/13252)
|
||||
* [改進資料庫描述的互動](https://github.com/siyuan-note/siyuan/issues/13262)
|
||||
* [改進文件標籤添加互動](https://github.com/siyuan-note/siyuan/issues/13311)
|
||||
* [改進工具提示](https://github.com/siyuan-note/siyuan/pull/13326)
|
||||
* [改進導出區塊引用](https://github.com/siyuan-note/siyuan/issues/13331)
|
||||
* [改進搜尋高亮](https://github.com/siyuan-note/siyuan/issues/13343)
|
||||
* [改進範本搜尋](https://github.com/siyuan-note/siyuan/issues/13348)
|
||||
* [改進匯出為 PDF 時的程式碼區塊分頁](https://github.com/siyuan-note/siyuan/issues/13349)
|
||||
* [改進 HTML 剪藏](https://github.com/siyuan-note/siyuan/issues/13355)
|
||||
* [改進系統字體載入](https://github.com/siyuan-note/siyuan/issues/13356)
|
||||
* [產生包含 ' 字元的區塊引用時導致奇怪的行為](https://github.com/siyuan-note/siyuan/issues/13358)
|
||||
* [簡化搜尋結果中的文件區塊路徑](https://github.com/siyuan-note/siyuan/issues/13364)
|
||||
* [瀏覽器剪藏擴充功能加入了一些實驗性功能](https://github.com/siyuan-note/siyuan/issues/13366)
|
||||
* [屬性面板 - 資料庫支援移除目前區塊](https://github.com/siyuan-note/siyuan/issues/13375)
|
||||
* [支援 flac 音訊資源播放](https://github.com/siyuan-note/siyuan/issues/13386)
|
||||
* [當圖像 URL 包含 `%` 時無法雙擊預覽](https://github.com/siyuan-note/siyuan/issues/13388)
|
||||
* [在 Linux 上使用滑鼠中鍵關閉標籤頁會觸發貼上](https://github.com/siyuan-note/siyuan/pull/13395)
|
||||
* [改進設定外觀優先權](https://github.com/siyuan-note/siyuan/issues/13404)
|
||||
|
||||
### 修復缺陷
|
||||
|
||||
* [行動端資料歷史中的文件在下滑時會關閉](https://github.com/siyuan-note/siyuan/issues/13347)
|
||||
* [點選行級標籤後找不到結果](https://github.com/siyuan-note/siyuan/issues/13351)
|
||||
* [HTML 標籤搜尋轉義問題](https://github.com/siyuan-note/siyuan/issues/13354)
|
||||
* [匯出至 .docx 的有序列表序號不正確](https://github.com/siyuan-note/siyuan/issues/13365)
|
||||
* [以 `.` 結尾的檔案名稱會被視為缺失資源](https://github.com/siyuan-note/siyuan/issues/13368)
|
||||
* [完全手動同步模式導致資料衝突](https://github.com/siyuan-note/siyuan/issues/13387)
|
||||
|
||||
### 開發者
|
||||
|
||||
* [改進選擇區塊或表格儲存格後 `Backspace` `Delete` `Tab` `Shift+Tab` 的操作](https://github.com/siyuan-note/siyuan/issues/13027)
|
||||
* [新增內核 API `/api/filetree/moveDocsByID`](https://github.com/siyuan-note/siyuan/issues/13247)
|
||||
* [移除編輯器輸入控制台日誌](https://github.com/siyuan-note/siyuan/issues/13346)
|
||||
* [為 Protyle 新增 `disable` 和 `enable` 方法](https://github.com/siyuan-note/siyuan/issues/13391)
|
||||
|
||||
## 下載
|
||||
|
||||
* [B3log](https://b3log.org/siyuan/download.html)
|
||||
* [GitHub](https://github.com/siyuan-note/siyuan/releases)
|
53
app/changelogs/v3.1.15/v3.1.15_zh_CN.md
Normal file
53
app/changelogs/v3.1.15/v3.1.15_zh_CN.md
Normal file
|
@ -0,0 +1,53 @@
|
|||
## 概述
|
||||
|
||||
该版本支持了鸿蒙系统。
|
||||
|
||||
## 变更记录
|
||||
|
||||
以下是此版本中的详细变更。
|
||||
|
||||
### 改进功能
|
||||
|
||||
* [改进 Alt+M 隐藏/显示窗口](https://github.com/siyuan-note/siyuan/issues/12656)
|
||||
* [改进数据库单元格定位和编辑输入框大小](https://github.com/siyuan-note/siyuan/issues/12708)
|
||||
* [支持鸿蒙系统](https://github.com/siyuan-note/siyuan/issues/13184)
|
||||
* [粘贴时移除折叠标题的折叠状态](https://github.com/siyuan-note/siyuan/issues/13232)
|
||||
* [支持数据库日期字段少于 4 位的年份](https://github.com/siyuan-note/siyuan/issues/13252)
|
||||
* [改进数据库描述的交互](https://github.com/siyuan-note/siyuan/issues/13262)
|
||||
* [改进文档标签添加交互](https://github.com/siyuan-note/siyuan/issues/13311)
|
||||
* [改进工具提示](https://github.com/siyuan-note/siyuan/pull/13326)
|
||||
* [改进导出块引用](https://github.com/siyuan-note/siyuan/issues/13331)
|
||||
* [改进搜索高亮](https://github.com/siyuan-note/siyuan/issues/13343)
|
||||
* [改进模板搜索](https://github.com/siyuan-note/siyuan/issues/13348)
|
||||
* [改进导出为 PDF 时的代码块分页](https://github.com/siyuan-note/siyuan/issues/13349)
|
||||
* [改进 HTML 剪藏](https://github.com/siyuan-note/siyuan/issues/13355)
|
||||
* [改进系统字体加载](https://github.com/siyuan-note/siyuan/issues/13356)
|
||||
* [生成包含 ' 字符的块引用时导致奇怪的行为](https://github.com/siyuan-note/siyuan/issues/13358)
|
||||
* [简化搜索结果中的文档块路径](https://github.com/siyuan-note/siyuan/issues/13364)
|
||||
* [浏览器剪藏扩展添加了一些实验性功能](https://github.com/siyuan-note/siyuan/issues/13366)
|
||||
* [属性面板 - 数据库支持移除当前块](https://github.com/siyuan-note/siyuan/issues/13375)
|
||||
* [支持 flac 音频资源播放](https://github.com/siyuan-note/siyuan/issues/13386)
|
||||
* [当图像 URL 包含 `%` 时无法双击预览](https://github.com/siyuan-note/siyuan/issues/13388)
|
||||
* [在 Linux 上使用鼠标中键关闭标签页会触发粘贴](https://github.com/siyuan-note/siyuan/pull/13395)
|
||||
* [改进设置外观优先级](https://github.com/siyuan-note/siyuan/issues/13404)
|
||||
|
||||
### 修复缺陷
|
||||
|
||||
* [移动端数据历史中的文档在下滑时会被关闭](https://github.com/siyuan-note/siyuan/issues/13347)
|
||||
* [点击行级标签后未找到结果](https://github.com/siyuan-note/siyuan/issues/13351)
|
||||
* [HTML 标签搜索转义问题](https://github.com/siyuan-note/siyuan/issues/13354)
|
||||
* [导出到 .docx 的有序列表序号不正确](https://github.com/siyuan-note/siyuan/issues/13365)
|
||||
* [以 `.` 结尾的文件名会被视为缺失资源](https://github.com/siyuan-note/siyuan/issues/13368)
|
||||
* [完全手动同步模式导致数据冲突](https://github.com/siyuan-note/siyuan/issues/13387)
|
||||
|
||||
### 开发者
|
||||
|
||||
* [改进选择块或表格单元格后 `Backspace` `Delete` `Tab` `Shift+Tab` 的操作](https://github.com/siyuan-note/siyuan/issues/13027)
|
||||
* [添加内核 API `/api/filetree/moveDocsByID`](https://github.com/siyuan-note/siyuan/issues/13247)
|
||||
* [移除编辑器输入控制台日志](https://github.com/siyuan-note/siyuan/issues/13346)
|
||||
* [为 Protyle 添加 `disable` 和 `enable` 方法](https://github.com/siyuan-note/siyuan/issues/13391)
|
||||
|
||||
## 下载
|
||||
|
||||
* [B3log](https://b3log.org/siyuan/download.html)
|
||||
* [GitHub](https://github.com/siyuan-note/siyuan/releases)
|
|
@ -43,7 +43,7 @@ const windowStatePath = path.join(confDir, "windowState.json");
|
|||
let bootWindow;
|
||||
let latestActiveWindow;
|
||||
let firstOpen = false;
|
||||
let workspaces = []; // workspaceDir, id, browserWindow, tray
|
||||
let workspaces = []; // workspaceDir, id, browserWindow, tray, hideShortcut
|
||||
let kernelPort = 6806;
|
||||
let resetWindowStateOnRestart = false;
|
||||
|
||||
|
@ -1098,6 +1098,12 @@ app.whenReady().then(() => {
|
|||
if (!data.hotkeys || data.hotkeys.length === 0) {
|
||||
return;
|
||||
}
|
||||
workspaces.find(workspaceItem => {
|
||||
if (event.sender.id === workspaceItem.browserWindow.webContents.id) {
|
||||
workspaceItem.hotkeys = data.hotkeys;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
data.hotkeys.forEach((item, index) => {
|
||||
const shortcut = hotKey2Electron(item);
|
||||
if (!shortcut) {
|
||||
|
@ -1111,11 +1117,19 @@ app.whenReady().then(() => {
|
|||
let currentWorkspace;
|
||||
const currentWebContentsId = (latestActiveWindow && !latestActiveWindow.isDestroyed()) ? latestActiveWindow.webContents.id : undefined;
|
||||
workspaces.find(workspaceItem => {
|
||||
if ((currentWebContentsId || event.sender.id) === workspaceItem.browserWindow.webContents.id) {
|
||||
if (currentWebContentsId === workspaceItem.browserWindow.webContents.id && workspaceItem.hotkeys[0] === item) {
|
||||
currentWorkspace = workspaceItem;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!currentWorkspace) {
|
||||
workspaces.find(workspaceItem => {
|
||||
if (workspaceItem.hotkeys[0] === item && event.sender.id === workspaceItem.browserWindow.webContents.id) {
|
||||
currentWorkspace = workspaceItem;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!currentWorkspace) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"id": "20201210233038-3xr19g5",
|
||||
"title": "Conversion of Document and Heading",
|
||||
"type": "doc",
|
||||
"updated": "20241018105907"
|
||||
"updated": "20241214173509"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -135,7 +135,8 @@
|
|||
"Type": "NodeHeading",
|
||||
"HeadingLevel": 2,
|
||||
"Properties": {
|
||||
"id": "20210104091550-5sh49go"
|
||||
"id": "20210104091550-5sh49go",
|
||||
"updated": "20241214173509"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -152,12 +153,13 @@
|
|||
"ID": "20210104091550-rbetlgr",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210104091550-rbetlgr"
|
||||
"id": "20210104091550-rbetlgr",
|
||||
"updated": "20241214173509"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "In the doc tree, select the document that needs to be converted into a heading block, and then drag it to the position to be inserted in the editor tab. There are two situations here:"
|
||||
"Data": "In the document tree, select the document you want to convert to a heading block, then hold down the Alt key and drag it to the position in the editor tab where you want to insert it. There are two situations here:"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"id": "20201204184532-3qm9l8n",
|
||||
"title": "Template snippet",
|
||||
"type": "doc",
|
||||
"updated": "20241008202623"
|
||||
"updated": "20241213215714"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -57,7 +57,7 @@
|
|||
"HeadingLevel": 2,
|
||||
"Properties": {
|
||||
"id": "20210104091444-jy56z0p",
|
||||
"updated": "20241008202623"
|
||||
"updated": "20241213215714"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -215,7 +215,7 @@
|
|||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20210104091444-mwbvc9m",
|
||||
"updated": "20240921122726"
|
||||
"updated": "20241213215714"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -429,7 +429,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210131162138-7ufhbho",
|
||||
"updated": "20240403150956"
|
||||
"updated": "20241213215545"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -443,7 +443,33 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": This function is used to query the database, and the return value is a list of blocks, please refer to the example below"
|
||||
"Data": ": This function is used to query the database, and the return value is a list of blocks"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215602-dk7iion",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215602-dk7iion",
|
||||
"updated": "20241213215602"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -466,7 +492,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210504093232-6wxl589",
|
||||
"updated": "20240403151002"
|
||||
"updated": "20241213215547"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -480,7 +506,375 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": This function is used to query the database, and the return value is a list of spans, please refer to the example below"
|
||||
"Data": ": This function is used to query the database, and the return value is a list of spans"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215606-a1mq6zf",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215606-a1mq6zf",
|
||||
"updated": "20241213215606"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM spans LIMIT ?\" \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213214939-he4wmcd",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241213214939-he4wmcd",
|
||||
"updated": "20241213214939"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241213214939-hrshqgv",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241213214939-hrshqgv",
|
||||
"updated": "20241213215550"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySQL"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": This function is used to query the database and the return value is a result set"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215554-rox3jk7",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215554-rox3jk7",
|
||||
"updated": "20241213215554"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM refs LIMIT 3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102027-j293sei",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102027-j293sei",
|
||||
"updated": "20241213215714"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-6c8tlnu",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-6c8tlnu",
|
||||
"updated": "20241212163902"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "statBlock"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": This function is used to count the block content"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215714-u0j3i4k",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215714-u0j3i4k",
|
||||
"updated": "20241213215714"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{ (statBlock .id).RuneCount} .action{ (statBlock .id).WordCount}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102028-4ew89te",
|
||||
"Type": "NodeList",
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20241212102028-4ew89te",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-wai3afs",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102028-wai3afs",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-wmtwngj",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-wmtwngj",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RuneCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102028-r9k7ody",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102028-r9k7ody",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-le5lpgo",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-le5lpgo",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "WordCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102028-3egh1dg",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102028-3egh1dg",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-pijmoea",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-pijmoea",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "LinkCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102028-qu6f5tc",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102028-qu6f5tc",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-8yj65um",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-8yj65um",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "ImageCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102028-8ivthzb",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102028-8ivthzb",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-p8nmm3a",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-p8nmm3a",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RefCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102028-frusted",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102028-frusted",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102028-h58utua",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102028-h58utua",
|
||||
"updated": "20241212102028"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "BlockCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212163841-3yjhffn",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212163841-3yjhffn",
|
||||
"updated": "20241212163918"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212163841-d8t3qxb",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212163841-d8t3qxb",
|
||||
"updated": "20241212163918"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "runeLen"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": This function is used to return the string length"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -857,64 +1251,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210604111714-yc1e5gj",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210604111714-yc1e5gj",
|
||||
"updated": "20210604111715"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "queryBlocks"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " and "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySpans"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " support variable parameter lists similar to SQL prepared statements to facilitate the input of parameters:"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210604111750-c3sm3jr",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20210604111750-c3sm3jr",
|
||||
"updated": "20210604111632"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"ID": "20220307092214-3yza25q",
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n",
|
||||
"Properties": {
|
||||
"id": "20220307092214-3yza25q"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210104091444-4re70bp",
|
||||
"Type": "NodeHeading",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"id": "20201210103036-1x3vm8t",
|
||||
"title": "文档块和标题块的转换",
|
||||
"type": "doc",
|
||||
"updated": "20241018104534"
|
||||
"updated": "20241214173542"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -135,7 +135,8 @@
|
|||
"Type": "NodeHeading",
|
||||
"HeadingLevel": 2,
|
||||
"Properties": {
|
||||
"id": "20210104090801-tojy8es"
|
||||
"id": "20210104090801-tojy8es",
|
||||
"updated": "20241214173542"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -152,12 +153,13 @@
|
|||
"ID": "20210104090801-q0rn7el",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210104090801-q0rn7el"
|
||||
"id": "20210104090801-q0rn7el",
|
||||
"updated": "20241214173542"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "在文档树上,选择需要转换为标题块的文档,然后将其拖拽到编辑器页签中需要插入的位置。这里有两种情况:"
|
||||
"Data": "在文档树上选择需要转换为标题块的文档,然后按住 Alt 键将其拖拽到编辑器页签中需要插入的位置。这里有两种情况:"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"id": "20201204181006-7bkppue",
|
||||
"title": "模板片段",
|
||||
"type": "doc",
|
||||
"updated": "20241008201610"
|
||||
"updated": "20241213215655"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -69,7 +69,7 @@
|
|||
"HeadingLevel": 2,
|
||||
"Properties": {
|
||||
"id": "20210104091309-fhb549c",
|
||||
"updated": "20241008201610"
|
||||
"updated": "20241213215655"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -237,7 +237,7 @@
|
|||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20210104091309-gjkg3u5",
|
||||
"updated": "20240921122737"
|
||||
"updated": "20241213215655"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -451,7 +451,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210131155558-ghlchbx",
|
||||
"updated": "20240403150712"
|
||||
"updated": "20241213215236"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -465,7 +465,33 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":该函数用于查询数据库,返回值为 blocks 列表,请参考下面的例子"
|
||||
"Data": ":该函数用于查询数据库,返回值为 blocks 列表"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210604111446-p6vadfc",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20210604111446-p6vadfc",
|
||||
"updated": "20241213215118"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -480,7 +506,7 @@
|
|||
},
|
||||
"Properties": {
|
||||
"id": "20210504093313-4aoyxd0",
|
||||
"updated": "20240403150838"
|
||||
"updated": "20241213215416"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -488,7 +514,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210504093313-ya53o58",
|
||||
"updated": "20240403150838"
|
||||
"updated": "20241213215302"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -502,7 +528,375 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":该函数用于查询数据库,返回值为 spans 列表,请参考下面的例子"
|
||||
"Data": ":该函数用于查询数据库,返回值为 spans 列表"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215337-rhkoc8k",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215337-rhkoc8k",
|
||||
"updated": "20241213215416"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM spans LIMIT ?\" \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213214733-ro4xcjm",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241213214733-ro4xcjm",
|
||||
"updated": "20241213215421"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241213214733-73dpip9",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241213214733-73dpip9",
|
||||
"updated": "20241213215139"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySQL"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":该函数用于查询数据库,返回值为结果集"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215240-f33bsqs",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215240-f33bsqs",
|
||||
"updated": "20241213215421"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM refs LIMIT 3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101708-0euo6is",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101708-0euo6is",
|
||||
"updated": "20241213215655"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101708-llv0ngj",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101708-llv0ngj",
|
||||
"updated": "20241212163723"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "statBlock"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":该函数用于统计块内容"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101810-6ffociu",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241212101810-6ffociu",
|
||||
"updated": "20241213215655"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{ (statBlock .id).RuneCount} .action{ (statBlock .id).WordCount}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101821-kf6un09",
|
||||
"Type": "NodeList",
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20241212101821-kf6un09",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-1qt2j1i",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101821-1qt2j1i",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-mkxql2a",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101821-mkxql2a",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RuneCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101821-kok8u5t",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101821-kok8u5t",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-7gsgfqo",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101821-7gsgfqo",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "WordCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101821-jxbirdz",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101821-jxbirdz",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-mep8mwc",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101821-mep8mwc",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "LinkCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101821-8dho5yg",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101821-8dho5yg",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-hriiyll",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101821-hriiyll",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "ImageCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101821-mrg92au",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101821-mrg92au",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-ovwsmzs",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101821-ovwsmzs",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RefCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212101821-kq0fb53",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212101821-kq0fb53",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212101821-6k4evcn",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212101821-6k4evcn",
|
||||
"updated": "20241212101821"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "BlockCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212163704-qmyz1ss",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212163704-qmyz1ss",
|
||||
"updated": "20241212163739"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212163704-i9p11h6",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212163704-i9p11h6",
|
||||
"updated": "20241212163739"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "runeLen"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":该函数用于返回字符串长度"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -879,64 +1273,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210604111213-774ll6c",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20210604111213-774ll6c",
|
||||
"updated": "20210604111557"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "queryBlocks"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 和 "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySpans"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 支持类似 SQL 预编译语句的变参列表,方便传入参数:"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210604111446-p6vadfc",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20210604111446-p6vadfc",
|
||||
"updated": "20210604111632"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"ID": "20220307091943-diuexe8",
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n",
|
||||
"Properties": {
|
||||
"id": "20220307091943-diuexe8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20210104091309-h71ogwf",
|
||||
"Type": "NodeHeading",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"id": "20211226120422-bkzsd2e",
|
||||
"title": "文檔塊和標題塊的轉換",
|
||||
"type": "doc",
|
||||
"updated": "20241018105510"
|
||||
"updated": "20241214173531"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -121,7 +121,7 @@
|
|||
"HeadingLevel": 2,
|
||||
"Properties": {
|
||||
"id": "20211226120500-5g12nsc",
|
||||
"updated": "20211225234143"
|
||||
"updated": "20241214173531"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -135,12 +135,12 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20211226120500-me21dop",
|
||||
"updated": "20211226160825"
|
||||
"updated": "20241214173531"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "在文檔樹上,選擇需要轉換為標題塊的文檔,然後將其拖拽到編輯器分頁中需要插入的位置。這裡有兩種情況:"
|
||||
"Data": "在文檔樹上選擇需要轉換為標題塊的文檔,然後按住 Alt 鍵將其拖拽到編輯器頁簽中需要插入的位置。這裡有兩種情況:"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"id": "20211226123004-dplpw0o",
|
||||
"title": "範本片段",
|
||||
"type": "doc",
|
||||
"updated": "20241008201617"
|
||||
"updated": "20241213215707"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -53,7 +53,7 @@
|
|||
"HeadingLevel": 2,
|
||||
"Properties": {
|
||||
"id": "20211226123024-eyagqur",
|
||||
"updated": "20241008201617"
|
||||
"updated": "20241213215707"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -208,7 +208,7 @@
|
|||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20211226123024-pjvw31z",
|
||||
"updated": "20240921122732"
|
||||
"updated": "20241213215707"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -422,7 +422,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20211226123024-vxjdsno",
|
||||
"updated": "20240403150942"
|
||||
"updated": "20241213215430"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -436,7 +436,33 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":該函數用於查詢資料庫,返回值為 blocks 列表,請參考下面的例子"
|
||||
"Data": ":該函數用於查詢資料庫,返回值為 blocks 列表"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215519-mfgruqs",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215519-mfgruqs",
|
||||
"updated": "20241213215519"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -459,7 +485,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20211226123024-4qwyf3w",
|
||||
"updated": "20240403150944"
|
||||
"updated": "20241213215431"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -473,7 +499,375 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":該函數用於查詢資料庫,返回值為 spans 列表,請參考下面的例子"
|
||||
"Data": ":該函數用於查詢資料庫,返回值為 spans 列表"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215524-9an3khb",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215524-9an3khb",
|
||||
"updated": "20241213215524"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM spans LIMIT ?\" \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213214930-4votv1n",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241213214930-4votv1n",
|
||||
"updated": "20241213214930"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241213214930-dogaks1",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241213214930-dogaks1",
|
||||
"updated": "20241213215433"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySQL"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":函數用於查詢資料庫,傳回值為結果集"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215530-f2iwrjz",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215530-f2iwrjz",
|
||||
"updated": "20241213215530"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM refs LIMIT 3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102019-gassjqt",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102019-gassjqt",
|
||||
"updated": "20241213215707"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-54wv84h",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-54wv84h",
|
||||
"updated": "20241212164010"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "statBlock"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":此函數用於統計區塊內容"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215707-lxpmd6b",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215707-lxpmd6b",
|
||||
"updated": "20241213215707"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{ (statBlock .id).RuneCount} .action{ (statBlock .id).WordCount}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102021-vj2zyyl",
|
||||
"Type": "NodeList",
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20241212102021-vj2zyyl",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-92gy6t3",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102021-92gy6t3",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-d3lo8xu",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-d3lo8xu",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RuneCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102021-n8ufevw",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102021-n8ufevw",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-omvwh9v",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-omvwh9v",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "WordCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102021-s12eoe7",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102021-s12eoe7",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-518qvnd",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-518qvnd",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "LinkCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102021-dolb6ct",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102021-dolb6ct",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-dx5rhed",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-dx5rhed",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "ImageCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102021-yt0q53w",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102021-yt0q53w",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-z97tnzw",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-z97tnzw",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RefCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102021-npgihna",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102021-npgihna",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102021-80qheu7",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102021-80qheu7",
|
||||
"updated": "20241212102021"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "BlockCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212164016-nxteno5",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212164016-nxteno5",
|
||||
"updated": "20241212164017"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212164016-ot8vo9l",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212164016-ot8vo9l",
|
||||
"updated": "20241212164017"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "runeLen"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":此函數用於傳回字串長度"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -850,64 +1244,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20211226123024-5rk6w30",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20211226123024-5rk6w30",
|
||||
"updated": "20211228134953"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "queryBlocks"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 和 "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySpans"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " 支援類似 SQL 預編譯語句的變參列表,方便傳入參數:"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20211226123024-sw1k190",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20211226123024-sw1k190",
|
||||
"updated": "20211225221841"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"ID": "20220307092237-mawslux",
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n",
|
||||
"Properties": {
|
||||
"id": "20220307092237-mawslux"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20211226123024-3wiifft",
|
||||
"Type": "NodeHeading",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"id": "20240530101000-6x9ivi7",
|
||||
"title": "テンプレートスニペット",
|
||||
"type": "doc",
|
||||
"updated": "20240921123108"
|
||||
"updated": "20241213215720"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -66,7 +66,7 @@
|
|||
"Properties": {
|
||||
"ID": "20240530101000-5nvn9ad",
|
||||
"id": "20240530101000-pi05yzt",
|
||||
"updated": "20240921123108"
|
||||
"updated": "20241213215720"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -226,7 +226,7 @@
|
|||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20240530101000-by5hqnb",
|
||||
"updated": "20240921123108"
|
||||
"updated": "20241213215720"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -440,7 +440,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20240530101000-obb5zo9",
|
||||
"updated": "20240530101000"
|
||||
"updated": "20241213215612"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -454,7 +454,33 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": この関数はデータベースをクエリしてブロックのリストを返します (下記の使用例を参照してください)"
|
||||
"Data": ": この関数はデータベースをクエリしてブロックのリストを返します"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215628-5gixpmp",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215628-5gixpmp",
|
||||
"updated": "20241213215628"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -477,7 +503,7 @@
|
|||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20240530101000-4wi25sk",
|
||||
"updated": "20240530101000"
|
||||
"updated": "20241213215614"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -491,7 +517,375 @@
|
|||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": この関数はデータベースをクエリしてスパンのリストを返します (下記の使用例を参照してください)"
|
||||
"Data": ": この関数はデータベースをクエリしてスパンのリストを返します"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215619-gkqs282",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215619-gkqs282",
|
||||
"updated": "20241213215619"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM spans LIMIT ?\" \"3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215009-qrtc56j",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241213215009-qrtc56j",
|
||||
"updated": "20241213215009"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241213215009-fev1gao",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241213215009-fev1gao",
|
||||
"updated": "20241213215617"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySQL"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": この関数はデータベースへのクエリに使用され、戻り値は結果セットです"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215633-69ltmv1",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215633-69ltmv1",
|
||||
"updated": "20241213215633"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": " .action{querySQL \"SELECT * FROM refs LIMIT 3\"}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-rn9u6t8",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-rn9u6t8",
|
||||
"updated": "20241213215720"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-d4azb7k",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-d4azb7k",
|
||||
"updated": "20241212163936"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "statBlock"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ":この関数はブロックの内容を数えるために使用されます"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241213215720-ueqpsna",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"id": "20241213215720-ueqpsna",
|
||||
"updated": "20241213215720"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{ (statBlock .id).RuneCount} .action{ (statBlock .id).WordCount}\n"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-ib8fdwx",
|
||||
"Type": "NodeList",
|
||||
"ListData": {},
|
||||
"Properties": {
|
||||
"id": "20241212102033-ib8fdwx",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-lijk8pe",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-lijk8pe",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-ch66lvd",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-ch66lvd",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RuneCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-527kxt0",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-527kxt0",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-7iop2es",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-7iop2es",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "WordCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-zicftlk",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-zicftlk",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-871ju7g",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-871ju7g",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "LinkCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-2k2gz3h",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-2k2gz3h",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-1ss2d9y",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-1ss2d9y",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "ImageCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-905g5ga",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-905g5ga",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-k7jgqz4",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-k7jgqz4",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "RefCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212102033-xbpy9ew",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212102033-xbpy9ew",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212102033-kvquhrn",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212102033-kvquhrn",
|
||||
"updated": "20241212102033"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "BlockCount"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20241212163938-ewajrsj",
|
||||
"Type": "NodeListItem",
|
||||
"ListData": {
|
||||
"BulletChar": 42,
|
||||
"Marker": "Kg=="
|
||||
},
|
||||
"Properties": {
|
||||
"id": "20241212163938-ewajrsj",
|
||||
"updated": "20241212163955"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"ID": "20241212163938-y1al3b9",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"id": "20241212163938-y1al3b9",
|
||||
"updated": "20241212163955"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "runeLen"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ": この関数は文字列の長さを返すために使用されます"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -868,71 +1262,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20240530101000-5twj99z",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"ID": "20240530101000-p45pa4c",
|
||||
"id": "20240530101000-5twj99z",
|
||||
"updated": "20240530101000"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": ""
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "queryBlocks"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " と "
|
||||
},
|
||||
{
|
||||
"Type": "NodeTextMark",
|
||||
"TextMarkType": "code",
|
||||
"TextMarkTextContent": "querySpans"
|
||||
},
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": " はパラメータの入力を容易にするために、SQL のプリペアドステートメントに似た可変長引数リストをサポートしています:"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20240530101000-ao36z4x",
|
||||
"Type": "NodeCodeBlock",
|
||||
"IsFencedCodeBlock": true,
|
||||
"Properties": {
|
||||
"ID": "20240530101000-2pwl178",
|
||||
"id": "20240530101000-ao36z4x",
|
||||
"updated": "20240530101000"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceOpenMarker",
|
||||
"Data": "```"
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceInfoMarker"
|
||||
},
|
||||
{
|
||||
"ID": "20240530101000-ry5jzum",
|
||||
"Type": "NodeCodeBlockCode",
|
||||
"Data": ".action{$today := now | date \"20060102150405\"}\n.action{$blocks :=queryBlocks \"SELECT * FROM blocks WHERE content LIKE '?' AND updated \u003e '?' LIMIT ?\" \"%foo%\" $today \"3\"}\n",
|
||||
"Properties": {
|
||||
"ID": "20240530101000-i3tqwi3",
|
||||
"id": "20240530101000-ry5jzum"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "NodeCodeBlockFenceCloseMarker",
|
||||
"Data": "```"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ID": "20240530101000-ud82uol",
|
||||
"Type": "NodeHeading",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"id": "20240530101000-dro2zi9",
|
||||
"title": "ドキュメントと見出しの変換",
|
||||
"type": "doc",
|
||||
"updated": "20241018110150"
|
||||
"updated": "20241214173436"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -149,7 +149,7 @@
|
|||
"Properties": {
|
||||
"ID": "20240530101000-g3g26mu",
|
||||
"id": "20240530101000-7z8z1w9",
|
||||
"updated": "20240530101000"
|
||||
"updated": "20241214173436"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
|
@ -162,14 +162,13 @@
|
|||
"ID": "20240530101000-281oxo0",
|
||||
"Type": "NodeParagraph",
|
||||
"Properties": {
|
||||
"ID": "20240530101000-wtkhsae",
|
||||
"id": "20240530101000-281oxo0",
|
||||
"updated": "20240530101000"
|
||||
"updated": "20241214173436"
|
||||
},
|
||||
"Children": [
|
||||
{
|
||||
"Type": "NodeText",
|
||||
"Data": "ドキュメントツリーで見出しブロックに変換するドキュメントブロックを選択し、開かれているエディタの挿入したい位置にドラッグします。ここでは、以下の 2 つのパターンがあります:"
|
||||
"Data": "ドキュメントツリーでタイトルブロックに変換するドキュメントを選択し、Altキーを押しながらエディタタブの挿入したい位置にドラッグします。ここでは、以下の 2 つのパターンがあります:"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "SiYuan",
|
||||
"version": "3.1.14",
|
||||
"version": "3.1.15",
|
||||
"description": "Refactor your thinking",
|
||||
"homepage": "https://b3log.org/siyuan",
|
||||
"main": "./electron/main.js",
|
||||
|
|
8
app/pnpm-lock.yaml
generated
8
app/pnpm-lock.yaml
generated
|
@ -1942,8 +1942,8 @@ packages:
|
|||
ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
nanoid@3.3.6:
|
||||
resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==}
|
||||
nanoid@3.3.8:
|
||||
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
|
@ -4891,7 +4891,7 @@ snapshots:
|
|||
|
||||
ms@2.1.2: {}
|
||||
|
||||
nanoid@3.3.6: {}
|
||||
nanoid@3.3.8: {}
|
||||
|
||||
natural-compare@1.4.0: {}
|
||||
|
||||
|
@ -5110,7 +5110,7 @@ snapshots:
|
|||
|
||||
postcss@8.4.31:
|
||||
dependencies:
|
||||
nanoid: 3.3.6
|
||||
nanoid: 3.3.8
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
|
||||
|
|
|
@ -197,8 +197,11 @@ export const initAnno = (element: HTMLElement, pdf: any) => {
|
|||
} else if (type === "remove") {
|
||||
const urlPath = pdf.appConfig.file.replace(location.origin, "").substr(1);
|
||||
const config = getConfig(pdf);
|
||||
delete config[rectElement.getAttribute("data-node-id")];
|
||||
rectElement.remove();
|
||||
const id = rectElement.getAttribute("data-node-id");
|
||||
delete config[id];
|
||||
element.querySelectorAll(`[data-node-id="${id}"]`).forEach(item => {
|
||||
item.remove();
|
||||
});
|
||||
fetchPost("/api/asset/setFileAnnotation", {
|
||||
path: urlPath + ".sya",
|
||||
data: JSON.stringify(config),
|
||||
|
@ -393,7 +396,7 @@ const showToolbar = (element: HTMLElement, range: Range, target?: HTMLElement) =
|
|||
};
|
||||
|
||||
const getTextNode = (element: HTMLElement, isFirst: boolean) => {
|
||||
const spans = element.querySelectorAll(".markedContent span");
|
||||
const spans = element.querySelectorAll('span[role="presentation"]');
|
||||
let index = isFirst ? 0 : spans.length - 1;
|
||||
while (spans[index]) {
|
||||
if (spans[index].textContent) {
|
||||
|
|
92
app/src/assets/fonts/Noto-COLRv1-2.047/LICENSE
Normal file
92
app/src/assets/fonts/Noto-COLRv1-2.047/LICENSE
Normal file
|
@ -0,0 +1,92 @@
|
|||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to
|
||||
provide a free and open framework in which fonts may be shared and
|
||||
improved in partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software
|
||||
components as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to,
|
||||
deleting, or substituting -- in part or in whole -- any of the
|
||||
components of the Original Version, by changing formats or by porting
|
||||
the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed,
|
||||
modify, redistribute, and sell modified and unmodified copies of the
|
||||
Font Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components, in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created using
|
||||
the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
BIN
app/src/assets/fonts/Noto-COLRv1-2.047/Noto-COLRv1.woff2
Normal file
BIN
app/src/assets/fonts/Noto-COLRv1-2.047/Noto-COLRv1.woff2
Normal file
Binary file not shown.
|
@ -35,6 +35,7 @@
|
|||
@import "business/resize";
|
||||
@import "business/av";
|
||||
@import "business/emojis";
|
||||
@import "component/svg";
|
||||
|
||||
/*
|
||||
.status: 2
|
||||
|
@ -93,25 +94,6 @@ html {
|
|||
}
|
||||
}
|
||||
|
||||
.svg {
|
||||
fill: currentColor;
|
||||
display: inline-block;
|
||||
stroke-width: 0;
|
||||
stroke: currentColor;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--mid {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&--small {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
background-color: var(--b3-toolbar-background);
|
||||
|
|
|
@ -314,8 +314,18 @@
|
|||
|
||||
&--select {
|
||||
background-color: var(--b3-theme-primary-lightest);
|
||||
box-shadow: 2px 2px 0 var(--b3-theme-primary-lighter) inset, -2px -2px 0 var(--b3-theme-primary-lighter) inset;
|
||||
border-radius: var(--b3-border-radius);
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
border-radius: var(--b3-border-radius-s);
|
||||
box-shadow: 0 0 0 2px var(--b3-theme-primary-lighter);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
&--active {
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
margin: 0 8px 0 0;
|
||||
}
|
||||
|
||||
&:hover:not(.color__square--list),
|
||||
&:hover:not(.color__square--list):not(.color__square--current) {
|
||||
box-shadow: 0 0 0 1px var(--b3-border-color) inset, 0 0 0 3px var(--b3-list-hover);
|
||||
}
|
||||
|
||||
&--current {
|
||||
box-shadow: 0 0 0 1px var(--b3-list-hover) inset, 0 0 0 4px var(--b3-theme-background);
|
||||
box-shadow: 0 0 0 2px var(--b3-menu-background) inset, 0 0 0 3px var(--b3-list-hover);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
color: var(--b3-protyle-inline-blockref-color);
|
||||
opacity: .86;
|
||||
transition: var(--b3-transition);
|
||||
flex: 1;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
.emoji__dynamic {
|
||||
&-item {
|
||||
width: 74px;
|
||||
width: 73px;
|
||||
margin: 8px;
|
||||
cursor: pointer;
|
||||
transition: var(--b3-transition);
|
||||
|
@ -46,12 +46,11 @@
|
|||
}
|
||||
|
||||
&__item {
|
||||
font-size: 24px;
|
||||
line-height: .9em; // windows 需要这样设置
|
||||
font-size: 19px;
|
||||
font-family: var(--b3-font-family-emoji);
|
||||
text-align: center;
|
||||
height: 28px;
|
||||
padding: 2px 4px;
|
||||
height: 32px;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
transition: var(--b3-transition);
|
||||
|
@ -60,7 +59,7 @@
|
|||
margin: 1px;
|
||||
overflow: hidden;
|
||||
border-radius: var(--b3-border-radius);
|
||||
min-width: 32px;
|
||||
width: 32px;
|
||||
|
||||
img, svg {
|
||||
height: 24px;
|
||||
|
@ -103,6 +102,7 @@
|
|||
background-color: transparent;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
font-family: var(--b3-font-family-emoji);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--b3-theme-surface-lighter);
|
||||
|
|
|
@ -243,6 +243,7 @@
|
|||
}
|
||||
|
||||
&--readonly {
|
||||
cursor: default;
|
||||
padding-left: 13px;
|
||||
padding-right: 8px;
|
||||
max-width: none;
|
||||
|
|
|
@ -19,6 +19,15 @@
|
|||
width: 16px;
|
||||
}
|
||||
|
||||
&-list {
|
||||
height: 28px;
|
||||
width: 42px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&-input {
|
||||
padding-left: 35px !important;
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
}
|
||||
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
font-family: var(--b3-font-family-emoji);
|
||||
margin-right: 4px;
|
||||
line-height: 22px;
|
||||
|
|
24
app/src/assets/scss/component/_svg.scss
Normal file
24
app/src/assets/scss/component/_svg.scss
Normal file
|
@ -0,0 +1,24 @@
|
|||
.svg {
|
||||
fill: currentColor;
|
||||
display: inline-block;
|
||||
stroke-width: 0;
|
||||
stroke: currentColor;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--mid {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&--small {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
&--smaller {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
|
@ -3,6 +3,32 @@
|
|||
src: url(../fonts/JetBrainsMono-2.304/JetBrainsMono-Regular.woff2) format('woff2');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Number Glyphs Of JetBrainsMono-Regular";
|
||||
src: url(../fonts/JetBrainsMono-2.304/JetBrainsMono-Regular.woff2) format('woff2');
|
||||
/* 数字 0-9 */
|
||||
unicode-range: U+30-39;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "SiYuan Emojis";
|
||||
src: url(../fonts/Noto-COLRv1-2.047/Noto-COLRv1.woff2) format("woff2");
|
||||
// 表情中包含的 emoji 对应的 Unicode
|
||||
unicode-range: U+23, U+2A, U+30-39, U+A9, U+AE, U+200D, U+203C, U+2049, U+2122, U+2139, U+2194-2199, U+21A9-21AA, U+231A-231B, U+2328, U+23CF, U+23E9-23F3, U+23F8-23FA, U+24C2, U+25AA-25AB, U+25B6, U+25C0, U+25FB-25FE, U+2600-2604, U+260E, U+2611, U+2614-2615, U+2618, U+261D, U+2620, U+2622-2623, U+2626, U+262A, U+262E-262F, U+2638-263A, U+2640, U+2642, U+2648-2653, U+265F-2660, U+2663, U+2665-2666, U+2668, U+267B, U+267E-267F, U+2692-2697, U+2699, U+269B-269C, U+26A0-26A1, U+26A7, U+26AA-26AB, U+26B0-26B1, U+26BD-26BE, U+26C4-26C5, U+26C8, U+26CE-26CF, U+26D1, U+26D3-26D4, U+26E9-26EA, U+26F0-26F5, U+26F7-26FA, U+26FD, U+2702, U+2705, U+2708-270D, U+270F, U+2712, U+2714, U+2716, U+271D, U+2721, U+2728, U+2733-2734, U+2744, U+2747, U+274C, U+274E, U+2753-2755, U+2757, U+2763-2764, U+2795-2797, U+27A1, U+27B0, U+27BF, U+2934-2935, U+2B05-2B07, U+2B1B-2B1C, U+2B50, U+2B55, U+3030, U+303D, U+3297, U+3299, U+E50A, U+1F004, U+1F0CF, U+1F170-1F171, U+1F17E-1F17F, U+1F18E, U+1F191-1F19A, U+1F1E6-1F1FF, U+1F201-1F202, U+1F21A, U+1F22F, U+1F232-1F23A, U+1F250-1F251, U+1F300-1F321, U+1F324-1F393, U+1F396-1F397, U+1F399-1F39B, U+1F39E-1F3F0, U+1F3F3-1F3F5, U+1F3F7-1F4FD, U+1F4FF-1F53D, U+1F549-1F54E, U+1F550-1F567, U+1F56F-1F570, U+1F573-1F57A, U+1F587, U+1F58A-1F58D, U+1F590, U+1F595-1F596, U+1F5A4-1F5A5, U+1F5A8, U+1F5B1-1F5B2, U+1F5BC, U+1F5C2-1F5C4, U+1F5D1-1F5D3, U+1F5DC-1F5DE, U+1F5E1, U+1F5E3, U+1F5E8, U+1F5EF, U+1F5F3, U+1F5FA-1F64F, U+1F680-1F6C5, U+1F6CB-1F6D2, U+1F6D5-1F6D7, U+1F6DC-1F6E5, U+1F6E9, U+1F6EB-1F6EC, U+1F6F0, U+1F6F3-1F6FC, U+1F7E0-1F7EB, U+1F7F0, U+1F90C-1F93A, U+1F93C-1F945, U+1F947-1F9FF, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Emojis";
|
||||
src: local("Segoe UI Emoji"),
|
||||
local("Segoe UI Symbol"),
|
||||
local("Apple Color Emoji"),
|
||||
local("Twemoji Mozilla"),
|
||||
local("Noto Color Emoji"),
|
||||
local("Android Emoji"),
|
||||
local("EmojiSymbols"),
|
||||
local("SiYuan Emojis");
|
||||
}
|
||||
|
||||
.b3-typography,
|
||||
.protyle-wysiwyg {
|
||||
font-variant-ligatures: no-common-ligatures;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
@import "business/av";
|
||||
@import "business/search";
|
||||
@import "business/emojis";
|
||||
@import "component/svg";
|
||||
|
||||
.block__popover {
|
||||
width: 80vw;
|
||||
|
@ -138,6 +139,15 @@
|
|||
&:not(.toolbar__icon-deactivate):hover {
|
||||
background-color: var(--b3-list-hover);
|
||||
}
|
||||
|
||||
&--history {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
|
@ -152,10 +162,6 @@
|
|||
color: var(--b3-theme-on-background);
|
||||
}
|
||||
|
||||
&__search {
|
||||
margin: 8px;
|
||||
}
|
||||
|
||||
&__text {
|
||||
@include text-clamp(1);
|
||||
flex: 1;
|
||||
|
@ -395,6 +401,7 @@
|
|||
stroke: currentColor;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--mid {
|
||||
width: 16px;
|
||||
|
@ -405,6 +412,11 @@
|
|||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
&--smaller {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#empty {
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
min-height: 0 !important;
|
||||
min-width: 0 !important;
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,13 +121,11 @@ export class BlockPanel {
|
|||
openNewWindowById(this.nodeIds[0]);
|
||||
/// #endif
|
||||
} else if (type === "stickTab") {
|
||||
/// #if !BROWSER
|
||||
openFileById({
|
||||
app: options.app,
|
||||
id: this.nodeIds[0],
|
||||
action: this.editors[0].protyle.block.rootID !== this.nodeIds[0] ? [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS] : [Constants.CB_GET_CONTEXT],
|
||||
});
|
||||
/// #endif
|
||||
}
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
@ -233,14 +231,14 @@ export class BlockPanel {
|
|||
return;
|
||||
}
|
||||
let openHTML = "";
|
||||
/// #if !BROWSER
|
||||
if (this.nodeIds.length === 1) {
|
||||
openHTML = `<span data-type="stickTab" class="block__icon block__icon--show b3-tooltips b3-tooltips__sw" aria-label="${window.siyuan.languages.openBy}"><svg><use xlink:href="#iconOpen"></use></svg></span>
|
||||
<span class="fn__space"></span>
|
||||
<span data-type="open" class="block__icon block__icon--show b3-tooltips b3-tooltips__sw" aria-label="${window.siyuan.languages.openByNewWindow}"><svg><use xlink:href="#iconOpenWindow"></use></svg></span>
|
||||
<span class="fn__space"></span>`;
|
||||
/// #if !BROWSER
|
||||
openHTML += `<span data-type="open" class="block__icon block__icon--show b3-tooltips b3-tooltips__sw" aria-label="${window.siyuan.languages.openByNewWindow}"><svg><use xlink:href="#iconOpenWindow"></use></svg></span>
|
||||
<span class="fn__space"></span>`;
|
||||
/// #endif
|
||||
}
|
||||
/// #endif
|
||||
let html = `<div class="block__icons block__icons--menu">
|
||||
<span class="fn__space fn__flex-1 resize__move"></span>${openHTML}
|
||||
<span data-type="pin" class="block__icon block__icon--show b3-tooltips b3-tooltips__sw" aria-label="${window.siyuan.languages.pin}"><svg><use xlink:href="#iconPin"></use></svg></span>
|
||||
|
|
|
@ -54,7 +54,7 @@ export const initBlockPopover = (app: App) => {
|
|||
aElement.style.overflow = "";
|
||||
}
|
||||
}
|
||||
} else if (aElement.parentElement.parentElement.classList.contains("av__views")) {
|
||||
} else if (aElement.parentElement.parentElement.classList.contains("av__views") && aElement.parentElement.classList.contains("layout-tab-bar")) {
|
||||
const textElement = aElement.querySelector(".item__text");
|
||||
const desc = aElement.getAttribute("data-desc");
|
||||
if (textElement.scrollWidth > textElement.clientWidth + 2 || desc) {
|
||||
|
|
|
@ -10,13 +10,14 @@ import {App} from "../../index";
|
|||
import {Dialog} from "../../dialog";
|
||||
import {getAllModels} from "../../layout/getAll";
|
||||
import {hasClosestByClassName} from "../../protyle/util/hasClosest";
|
||||
import {getArticle, inputEvent, replace, toggleReplaceHistory, toggleSearchHistory} from "../../search/util";
|
||||
import {getArticle, inputEvent, replace} from "../../search/util";
|
||||
import {showFileInFolder} from "../../util/pathName";
|
||||
import {assetInputEvent, renderPreview, toggleAssetHistory} from "../../search/assets";
|
||||
import {assetInputEvent, renderPreview} from "../../search/assets";
|
||||
import {initSearchMenu} from "../../menus/search";
|
||||
import {writeText} from "../../protyle/util/compatibility";
|
||||
import {checkFold} from "../../util/noRelyPCFunction";
|
||||
import {getUnRefList} from "../../search/unRef";
|
||||
import {toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "../../search/toggleHistory";
|
||||
|
||||
export const searchKeydown = (app: App, event: KeyboardEvent) => {
|
||||
if (getSelection().rangeCount === 0) {
|
||||
|
@ -72,7 +73,7 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
|
|||
toggleAssetHistory(assetsElement);
|
||||
} else if (searchType === "doc") {
|
||||
if (targetId === "replaceInput") {
|
||||
toggleReplaceHistory(element);
|
||||
toggleReplaceHistory(element.querySelector("#replaceInput"));
|
||||
} else {
|
||||
toggleSearchHistory(element, config, edit);
|
||||
}
|
||||
|
|
|
@ -28,13 +28,13 @@ export const image = {
|
|||
<div class="fn__flex-1">
|
||||
<div class="config-assets" data-type="remove" data-init="true">
|
||||
<div class="fn__hr--b"></div>
|
||||
<label class="fn__flex">
|
||||
<div class="fn__flex">
|
||||
<div class="fn__space"></div>
|
||||
<button id="removeAll" class="b3-button b3-button--outline fn__flex-center fn__size200">
|
||||
<svg class="svg"><use xlink:href="#iconTrashcan"></use></svg>
|
||||
${window.siyuan.languages.delete}
|
||||
</button>
|
||||
</label>
|
||||
</div>
|
||||
<div class="fn__hr"></div>
|
||||
<ul class="b3-list b3-list--background config-assets__list">
|
||||
<li class="fn__loading"><img src="/stage/loading-pure.svg"></li>
|
||||
|
|
|
@ -392,6 +392,16 @@ export const repos = {
|
|||
<option value="3" ${window.siyuan.config.sync.mode === 3 ? "selected" : ""}>${window.siyuan.languages.syncMode3}</option>
|
||||
</select>
|
||||
</div>
|
||||
<label class="fn__flex b3-label${(window.siyuan.config.sync.mode !== 1 || window.siyuan.config.system.container === "docker" || window.siyuan.config.sync.provider !== 0) ? " fn__none" : ""}">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.syncInterval}
|
||||
<div class="b3-label__text">${window.siyuan.languages.syncIntervalTip}</div>
|
||||
</div>
|
||||
<span class="fn__space"></span>
|
||||
<input type="number" min="30" max="43200" id="syncInterval" class="b3-text-field fn__flex-center" value="${window.siyuan.config.sync.interval}" >
|
||||
<span class="fn__space"></span>
|
||||
<span class="fn__flex-center ft__on-surface">${window.siyuan.languages.second}</span>
|
||||
</label>
|
||||
<label class="fn__flex b3-label${(window.siyuan.config.sync.mode !== 1 || window.siyuan.config.system.container === "docker" || window.siyuan.config.sync.provider !== 0) ? " fn__none" : ""}">
|
||||
<div class="fn__flex-1">
|
||||
${window.siyuan.languages.syncPerception}
|
||||
|
@ -434,6 +444,21 @@ export const repos = {
|
|||
processSync();
|
||||
});
|
||||
});
|
||||
const syncIntervalElement = repos.element.querySelector("#syncInterval") as HTMLInputElement;
|
||||
syncIntervalElement.addEventListener("change", () => {
|
||||
let interval = parseInt(syncIntervalElement.value);
|
||||
if (30 > interval) {
|
||||
interval = 30;
|
||||
}
|
||||
if (43200 < interval) {
|
||||
interval = 43200;
|
||||
}
|
||||
syncIntervalElement.value = interval.toString();
|
||||
fetchPost("/api/sync/setSyncInterval", {interval: interval}, () => {
|
||||
window.siyuan.config.sync.interval = interval;
|
||||
processSync();
|
||||
});
|
||||
});
|
||||
const syncPerceptionElement = repos.element.querySelector("#syncPerception") as HTMLInputElement;
|
||||
syncPerceptionElement.addEventListener("change", () => {
|
||||
fetchPost("/api/sync/setSyncPerception", {enabled: syncPerceptionElement.checked}, () => {
|
||||
|
@ -452,8 +477,10 @@ export const repos = {
|
|||
fetchPost("/api/sync/setSyncMode", {mode: parseInt(syncModeElement.value, 10)}, () => {
|
||||
if (syncModeElement.value === "1" && window.siyuan.config.sync.provider === 0 && window.siyuan.config.system.container !== "docker") {
|
||||
syncPerceptionElement.parentElement.classList.remove("fn__none");
|
||||
syncIntervalElement.parentElement.classList.remove("fn__none");
|
||||
} else {
|
||||
syncPerceptionElement.parentElement.classList.add("fn__none");
|
||||
syncIntervalElement.parentElement.classList.add("fn__none");
|
||||
}
|
||||
window.siyuan.config.sync.mode = parseInt(syncModeElement.value, 10);
|
||||
});
|
||||
|
@ -475,8 +502,10 @@ export const repos = {
|
|||
syncConfigElement.classList.add("fn__none");
|
||||
if (window.siyuan.config.sync.mode !== 1 || window.siyuan.config.system.container === "docker" || window.siyuan.config.sync.provider !== 0) {
|
||||
syncPerceptionElement.parentElement.classList.add("fn__none");
|
||||
syncIntervalElement.parentElement.classList.add("fn__none");
|
||||
} else {
|
||||
syncPerceptionElement.parentElement.classList.remove("fn__none");
|
||||
syncIntervalElement.parentElement.classList.remove("fn__none");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -124,6 +124,7 @@ export abstract class Constants {
|
|||
public static readonly LOCAL_PLUGIN_DOCKS = "local-plugin-docks";
|
||||
public static readonly LOCAL_IMAGES = "local-images";
|
||||
public static readonly LOCAL_EMOJIS = "local-emojis";
|
||||
public static readonly LOCAL_MOVE_PATH = "local-move-path";
|
||||
|
||||
// dialog
|
||||
public static readonly DIALOG_CONFIRM = "dialog-confirm";
|
||||
|
|
|
@ -249,7 +249,7 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
|
|||
disableAnimation: true,
|
||||
transparent: true,
|
||||
hideCloseIcon: true,
|
||||
width: isMobile() ? "80vw" : "372px",
|
||||
width: isMobile() ? "80vw" : "368px",
|
||||
height: "50vh",
|
||||
content: `<div class="emojis">
|
||||
<div class="emojis__tabheader">
|
||||
|
|
|
@ -37,7 +37,7 @@ import {Asset} from "../asset";
|
|||
import {newFile} from "../util/newFile";
|
||||
import {MenuItem} from "../menus/Menu";
|
||||
import {escapeHtml} from "../util/escape";
|
||||
import {isWindow} from "../util/functions";
|
||||
import {getFrontend, isWindow} from "../util/functions";
|
||||
import {hideAllElements} from "../protyle/ui/hideElements";
|
||||
import {focusByOffset, getSelectionOffset} from "../protyle/util/selection";
|
||||
import {Custom} from "./dock/Custom";
|
||||
|
@ -101,11 +101,29 @@ export class Wnd {
|
|||
window.siyuan.menus.menu.remove();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
const frontend = getFrontend();
|
||||
if ((["desktop", "desktop-window"].includes(frontend) && window.siyuan.config.system.os === "linux") ||
|
||||
(frontend === "browser-desktop" && navigator.userAgent.indexOf("Linux") !== -1)) {
|
||||
const activeElement = document.activeElement;
|
||||
window.addEventListener("paste", this.#preventPast, {
|
||||
capture: true,
|
||||
once: true
|
||||
});
|
||||
// TODO 保持原有焦点?https://github.com/siyuan-note/siyuan/pull/13395/files#r1877004077
|
||||
if (activeElement instanceof HTMLElement) {
|
||||
activeElement.focus();
|
||||
}
|
||||
// 如果在短时间内没有 paste 事件发生,移除监听
|
||||
setTimeout(() => {
|
||||
window.removeEventListener("paste", this.#preventPast, {
|
||||
capture: true
|
||||
});
|
||||
}, Constants.TIMEOUT_INPUT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
target = target.parentElement;
|
||||
}
|
||||
|
||||
});
|
||||
this.headersElement.addEventListener("mousewheel", (event: WheelEvent) => {
|
||||
this.headersElement.scrollLeft = this.headersElement.scrollLeft + event.deltaY;
|
||||
|
@ -590,6 +608,11 @@ export class Wnd {
|
|||
}
|
||||
}
|
||||
|
||||
#preventPast(event: ClipboardEvent) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
private renderTabList(target: HTMLElement) {
|
||||
if (!window.siyuan.menus.menu.element.classList.contains("fn__none") &&
|
||||
window.siyuan.menus.menu.element.getAttribute("data-name") === "tabList") {
|
||||
|
|
|
@ -467,7 +467,7 @@ export class Backlink extends Model {
|
|||
}
|
||||
});
|
||||
editor.protyle.notebookId = liElement.getAttribute("data-notebook-id");
|
||||
searchMarkRender(editor.protyle, keyword.split(" "));
|
||||
searchMarkRender(editor.protyle, response.data.keywords);
|
||||
this.editors.push(editor);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -390,6 +390,10 @@ export class Outline extends Model {
|
|||
id: this.blockId,
|
||||
preview: this.isPreview
|
||||
}, response => {
|
||||
// 文档切换后不再更新原有推送 https://github.com/siyuan-note/siyuan/issues/13409
|
||||
if (data.data.rootID !== this.blockId) {
|
||||
return;
|
||||
}
|
||||
this.update(response);
|
||||
// https://github.com/siyuan-note/siyuan/issues/8372
|
||||
if (getSelection().rangeCount > 0) {
|
||||
|
|
|
@ -1,13 +1,19 @@
|
|||
export const openModel = (obj: {
|
||||
html: string,
|
||||
icon: string,
|
||||
icon?: string,
|
||||
title: string,
|
||||
bindEvent: (element: HTMLElement) => void
|
||||
}) => {
|
||||
const modelElement = document.getElementById("model");
|
||||
modelElement.style.transform = "translateY(0px)";
|
||||
modelElement.style.zIndex = (++window.siyuan.zIndex).toString();
|
||||
modelElement.querySelector(".toolbar__icon use").setAttribute("xlink:href", "#" + obj.icon);
|
||||
const iconElement = modelElement.querySelector(".toolbar__icon");
|
||||
if(obj.icon) {
|
||||
iconElement.classList.remove("fn__none");
|
||||
iconElement.querySelector("use").setAttribute("xlink:href", "#" + obj.icon);
|
||||
} else {
|
||||
iconElement.classList.add("fn__none");
|
||||
}
|
||||
modelElement.querySelector(".toolbar__text").innerHTML = obj.title;
|
||||
const modelMainElement = modelElement.querySelector("#modelMain") as HTMLElement;
|
||||
modelMainElement.innerHTML = obj.html;
|
||||
|
|
|
@ -26,6 +26,13 @@ import {
|
|||
import {addClearButton} from "../../util/addClearButton";
|
||||
import {checkFold} from "../../util/noRelyPCFunction";
|
||||
import {getDefaultType} from "../../search/getDefault";
|
||||
import {
|
||||
saveAssetKeyList,
|
||||
saveKeyList,
|
||||
toggleAssetHistory,
|
||||
toggleReplaceHistory,
|
||||
toggleSearchHistory
|
||||
} from "../../search/toggleHistory";
|
||||
|
||||
const replace = (element: Element, config: Config.IUILayoutTabSearchConfig, isAll: boolean) => {
|
||||
if (config.method === 1 || config.method === 2) {
|
||||
|
@ -39,6 +46,7 @@ const replace = (element: Element, config: Config.IUILayoutTabSearchConfig, isAl
|
|||
if (!loadElement.classList.contains("fn__none")) {
|
||||
return;
|
||||
}
|
||||
saveKeyList("replaceKeys", replaceInputElement.value);
|
||||
let currentLiElement: HTMLElement = searchListElement.querySelector(".b3-list-item--focus");
|
||||
if (!currentLiElement) {
|
||||
return;
|
||||
|
@ -287,6 +295,7 @@ const initSearchEvent = (app: App, element: Element, config: Config.IUILayoutTab
|
|||
window.siyuan.storage[Constants.LOCAL_SEARCHDATA] = Object.assign({}, config);
|
||||
setStorageVal(Constants.LOCAL_SEARCHDATA, window.siyuan.storage[Constants.LOCAL_SEARCHDATA]);
|
||||
}
|
||||
saveKeyList("keys", searchInputElement.value);
|
||||
});
|
||||
addClearButton({
|
||||
inputElement: searchInputElement,
|
||||
|
@ -313,7 +322,17 @@ const initSearchEvent = (app: App, element: Element, config: Config.IUILayoutTab
|
|||
let target = event.target as HTMLElement;
|
||||
while (target && !target.isSameNode(element)) {
|
||||
const type = target.getAttribute("data-type");
|
||||
if (type === "previous") {
|
||||
if (type === "replaceHistory") {
|
||||
toggleReplaceHistory(target.nextElementSibling as HTMLInputElement);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (type === "assetHistory") {
|
||||
toggleAssetHistory(assetsElement);
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
break;
|
||||
} else if (type === "previous") {
|
||||
if (!target.getAttribute("disabled")) {
|
||||
config.page--;
|
||||
updateSearchResult(config, element);
|
||||
|
@ -663,13 +682,19 @@ export const popSearch = (app: App, searchConfig?: any) => {
|
|||
|
||||
openModel({
|
||||
title: `<div class="fn__flex">
|
||||
<span data-menu="true" class="toolbar__icon toolbar__icon--history" data-type="history">
|
||||
<svg class="svg--mid"><use xlink:href="#iconSearch"></use></svg>
|
||||
<svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
|
||||
</span>
|
||||
<input id="toolbarSearch" placeholder="${window.siyuan.languages.showRecentUpdatedBlocks}" class="toolbar__title fn__block">
|
||||
<svg id="toolbarSearchNew" class="toolbar__icon"><use xlink:href="#iconFile"></use></svg>
|
||||
</div>`,
|
||||
icon: "iconSearch",
|
||||
html: `<div class="fn__flex-column" style="height: 100%">
|
||||
<div class="toolbar toolbar--border${config.hasReplace ? "" : " fn__none"}">
|
||||
<svg class="toolbar__icon"><use xlink:href="#iconReplace"></use></svg>
|
||||
<span data-menu="true" class="toolbar__icon toolbar__icon--history" data-type="replaceHistory">
|
||||
<svg class="svg--mid"><use xlink:href="#iconReplace"></use></svg>
|
||||
<svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
|
||||
</span>
|
||||
<input id="toolbarReplace" class="toolbar__title">
|
||||
<svg class="fn__rotate fn__none toolbar__icon"><use xlink:href="#iconRefresh"></use></svg>
|
||||
<div class="fn__space"></div>
|
||||
|
@ -707,7 +732,10 @@ export const popSearch = (app: App, searchConfig?: any) => {
|
|||
</div>
|
||||
<div class="fn__none fn__flex-column" style="position: fixed;top: 0;width: 100%;background: var(--b3-theme-surface);height: 100%;" id="searchAssetsPanel">
|
||||
<div class="toolbar toolbar--border">
|
||||
<svg class="toolbar__icon"><use xlink:href="#iconSearch"></use></svg>
|
||||
<span data-menu="true" class="toolbar__icon toolbar__icon--history" data-type="assetHistory">
|
||||
<svg class="svg--mid"><use xlink:href="#iconSearch"></use></svg>
|
||||
<svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
|
||||
</span>
|
||||
<input id="searchAssetInput" placeholder="${window.siyuan.languages.keyword}" class="toolbar__title fn__block">
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
|
@ -750,6 +778,10 @@ export const popSearch = (app: App, searchConfig?: any) => {
|
|||
document.querySelector("#toolbarSearchNew").addEventListener("click", () => {
|
||||
newFileByName(app, (document.querySelector("#toolbarSearch") as HTMLInputElement).value);
|
||||
});
|
||||
const historyElement = document.querySelector('.toolbar [data-type="history"]');
|
||||
historyElement.addEventListener("click", () => {
|
||||
toggleSearchHistory(document.querySelector("#model"), config, undefined);
|
||||
});
|
||||
initSearchEvent(app, element.firstElementChild, config);
|
||||
updateSearchResult(config, element);
|
||||
}
|
||||
|
@ -778,6 +810,9 @@ const goAsset = () => {
|
|||
}
|
||||
assetInputEvent(assetsElement, localSearch);
|
||||
});
|
||||
inputElement.addEventListener("blur", () => {
|
||||
saveAssetKeyList(inputElement);
|
||||
});
|
||||
assetInputEvent(assetsElement, localSearch);
|
||||
addClearButton({
|
||||
inputElement,
|
||||
|
|
|
@ -18,6 +18,9 @@ const forwardStack: IBackStack[] = [];
|
|||
|
||||
const focusStack = (backStack: IBackStack) => {
|
||||
const protyle = getCurrentEditor().protyle;
|
||||
// 前进后快速后退会导致滚动错位 https://ld246.com/article/1734018624070
|
||||
protyle.observerLoad.disconnect();
|
||||
|
||||
window.siyuan.storage[Constants.LOCAL_DOCINFO] = {
|
||||
id: backStack.id,
|
||||
};
|
||||
|
@ -95,6 +98,10 @@ const focusStack = (backStack: IBackStack) => {
|
|||
setReadonlyByConfig(protyle, true);
|
||||
}
|
||||
protyle.contentElement.scrollTop = backStack.scrollTop;
|
||||
// 等待 av 等加载 https://ld246.com/article/1734018624070
|
||||
setTimeout(() => {
|
||||
protyle.contentElement.scrollTop = backStack.scrollTop;
|
||||
}, Constants.TIMEOUT_LOAD);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -318,6 +318,9 @@ const renderPDF = async (id: string) => {
|
|||
item.style.width = Math.min(item.clientWidth, width) + "px";
|
||||
item.removeAttribute('data-render');
|
||||
})
|
||||
previewElement.querySelectorAll('[data-type="NodeCodeBlock"][data-subtype="mermaid"] svg').forEach((item) => {
|
||||
item.style.maxHeight = width * 1.414 + "px";
|
||||
})
|
||||
Protyle.mathRender(previewElement, "${servePath}/stage/protyle", true);
|
||||
previewElement.querySelectorAll("table").forEach(item => {
|
||||
if (item.clientWidth > item.parentElement.clientWidth) {
|
||||
|
|
|
@ -443,8 +443,8 @@ export class Background {
|
|||
if (tags) {
|
||||
let html = "";
|
||||
const colors = ["secondary", "primary", "info", "success", "warning", "error", "pink"];
|
||||
tags.split(",").forEach((item, index) => {
|
||||
if (!item) {
|
||||
new Set(tags.split(",")).forEach((item, index) => {
|
||||
if (!item.replace(/ /g, "")) {
|
||||
return;
|
||||
}
|
||||
html += `<div class="b3-chip b3-chip--middle b3-chip--pointer b3-chip--${colors[index % 7]}" data-type="open-search">${escapeHtml(item)}<svg class="b3-chip__close" data-type="remove-tag"><use xlink:href="#iconCloseRound"></use></svg></div>`;
|
||||
|
@ -522,8 +522,12 @@ export class Background {
|
|||
k: "",
|
||||
}, (response) => {
|
||||
let html = "";
|
||||
const currentTags = this.getTags();
|
||||
response.data.tags.forEach((item: string, index: number) => {
|
||||
html += `<div class="b3-list-item b3-list-item--narrow${index === 0 ? " b3-list-item--focus" : ""}">${item}</div>`;
|
||||
html += `<div class="b3-list-item b3-list-item--narrow${index === 0 ? " b3-list-item--focus" : ""}">
|
||||
<div class="fn__flex-1">${item}</div>
|
||||
${currentTags.includes(Lute.UnEscapeHTMLStr(item))?'<svg class="b3-menu__checked"><use xlink:href="#iconSelect"></use></svg>':""}
|
||||
</div>`;
|
||||
});
|
||||
listElement.innerHTML = html;
|
||||
});
|
||||
|
@ -537,12 +541,12 @@ export class Background {
|
|||
if (event.key === "Enter") {
|
||||
const currentElement = listElement.querySelector(".b3-list-item--focus");
|
||||
if (currentElement) {
|
||||
this.addTags(currentElement.textContent, protyle);
|
||||
this.addTags(currentElement.textContent.trim(), protyle);
|
||||
} else {
|
||||
this.addTags(inputElement.value, protyle);
|
||||
this.addTags(inputElement.value.trim(), protyle);
|
||||
}
|
||||
inputElement.value = "";
|
||||
inputElement.dispatchEvent(new CustomEvent("input"));
|
||||
inputElement.dispatchEvent(new CustomEvent("input"));
|
||||
} else if (event.key === "Escape") {
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
|
@ -554,8 +558,12 @@ export class Background {
|
|||
}, (response) => {
|
||||
let searchHTML = "";
|
||||
let hasKey = false;
|
||||
const currentTags = this.getTags();
|
||||
response.data.tags.forEach((item: string) => {
|
||||
searchHTML += `<div class="b3-list-item b3-list-item--narrow">${item}</div>`;
|
||||
searchHTML += `<div class="b3-list-item b3-list-item--narrow">
|
||||
<div class="fn__flex-1">${item}</div>
|
||||
${currentTags.includes(Lute.UnEscapeHTMLStr(item.replace(/<mark>/g,"").replace(/<\/mark>/g,"")))?'<svg class="b3-menu__checked"><use xlink:href="#iconSelect"></use></svg>':""}
|
||||
</div>`;
|
||||
if (item === `<mark>${response.data.k}</mark>`) {
|
||||
hasKey = true;
|
||||
}
|
||||
|
@ -573,7 +581,8 @@ export class Background {
|
|||
if (!listItemElement) {
|
||||
return;
|
||||
}
|
||||
this.addTags(listItemElement.textContent, protyle);
|
||||
this.addTags(listItemElement.textContent.trim(), protyle);
|
||||
inputElement.dispatchEvent(new CustomEvent("input"));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -34,7 +34,7 @@ export const addFilesToDatabase = (fileLiElements: Element[]) => {
|
|||
};
|
||||
|
||||
export const addEditorToDatabase = (protyle: IProtyle, range: Range, type?: string) => {
|
||||
if (protyle.title?.editElement?.contains(range.startContainer) || type === "title") {
|
||||
if ((range && protyle.title?.editElement?.contains(range.startContainer)) || type === "title") {
|
||||
openSearchAV("", protyle.breadcrumb.element, (listItemElement) => {
|
||||
const avID = listItemElement.dataset.avId;
|
||||
transaction(protyle, [{
|
||||
|
|
|
@ -184,6 +184,7 @@ export const renderAVAttribute = (element: HTMLElement, id: string, protyle: IPr
|
|||
<div class="block__logo popover__block" data-id='${JSON.stringify(table.blockIDs)}'>
|
||||
<svg class="block__logoicon"><use xlink:href="#iconDatabase"></use></svg><span>${table.avName || window.siyuan.languages.database}</span>
|
||||
</div>
|
||||
<div class="fn__flex-1"></div>
|
||||
<span class="fn__space"></span>
|
||||
<span data-type="remove" class="block__icon block__icon--show b3-tooltips__w b3-tooltips" aria-label="${window.siyuan.languages.removeAV}"><svg><use xlink:href="#iconTrashcan"></use></svg></span>
|
||||
</div>`;
|
||||
|
|
|
@ -307,7 +307,6 @@ export const cellScrollIntoView = (blockElement: HTMLElement, cellElement: Eleme
|
|||
if (contentElement && cellElement.getAttribute("data-dtype") !== "checkbox") {
|
||||
const keyboardToolbarElement = document.getElementById("keyboardToolbar");
|
||||
const keyboardH = parseInt(keyboardToolbarElement.getAttribute("data-keyboardheight")) || (window.outerHeight / 2 - 42);
|
||||
console.log(keyboardH, window.innerHeight, cellRect.bottom);
|
||||
if (cellRect.bottom > window.innerHeight - keyboardH - 42) {
|
||||
contentElement.scrollTop += cellRect.bottom - window.innerHeight + 42 + keyboardH;
|
||||
} else if (cellRect.top < 110) {
|
||||
|
|
|
@ -393,7 +393,7 @@ export const bindEditEvent = (options: {
|
|||
return;
|
||||
}
|
||||
colData.options.push({
|
||||
color: (colData.options.length + 1).toString(),
|
||||
color: ((colData.options.length || 0) % 14 + 1).toString(),
|
||||
name: addOptionElement.value
|
||||
});
|
||||
transaction(options.protyle, [{
|
||||
|
|
|
@ -349,7 +349,11 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex)}
|
|||
if (isSearching) {
|
||||
searchInputElement.focus();
|
||||
}
|
||||
searchInputElement.addEventListener("compositionstart", (event: KeyboardEvent) => {
|
||||
event.stopPropagation();
|
||||
});
|
||||
searchInputElement.addEventListener("input", (event: KeyboardEvent) => {
|
||||
event.stopPropagation();
|
||||
if (event.isComposing) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ const filterSelectHTML = (key: string, options: {
|
|||
});
|
||||
}
|
||||
if (!hasMatch && key) {
|
||||
const colorIndex = (options?.length || 0) % 13 + 1;
|
||||
const colorIndex = (options?.length || 0) % 14 + 1;
|
||||
html = `<button data-type="addColOptionOrCell" class="b3-menu__item b3-menu__item--current" data-name="${key}" data-color="${colorIndex}">
|
||||
<svg class="b3-menu__icon"><use xlink:href="#iconAdd"></use></svg>
|
||||
<div class="fn__flex-1">
|
||||
|
@ -318,87 +318,91 @@ export const setColOption = (protyle: IProtyle, data: IAV, target: HTMLElement,
|
|||
}
|
||||
});
|
||||
menu.addSeparator();
|
||||
Array.from(Array(13).keys()).forEach(index => {
|
||||
menu.addItem({
|
||||
checked: parseInt(color) === index + 1,
|
||||
iconHTML: "",
|
||||
label: `<span class="color__square color__square--list" style="margin: 2px 0;color: var(--b3-font-color${index + 1});background-color: var(--b3-font-background${index + 1});">A</span>`,
|
||||
click(element) {
|
||||
if (element.lastElementChild.classList.contains("b3-menu__checked")) {
|
||||
return;
|
||||
}
|
||||
element.parentElement.querySelector(".b3-menu__checked")?.remove();
|
||||
element.insertAdjacentHTML("beforeend", '<svg class="b3-menu__checked"><use xlink:href="#iconSelect"></use></svg></span>');
|
||||
transaction(protyle, [{
|
||||
action: "updateAttrViewColOption",
|
||||
id: colId,
|
||||
avID: data.id,
|
||||
data: {
|
||||
oldName: name,
|
||||
newName: inputElement.value,
|
||||
oldColor: color,
|
||||
newColor: (index + 1).toString(),
|
||||
newDesc: descElement.value
|
||||
},
|
||||
}], [{
|
||||
action: "updateAttrViewColOption",
|
||||
id: colId,
|
||||
avID: data.id,
|
||||
data: {
|
||||
oldName: inputElement.value,
|
||||
newName: name,
|
||||
oldColor: (index + 1).toString(),
|
||||
newColor: color,
|
||||
newDesc: descElement.value
|
||||
},
|
||||
}]);
|
||||
let html = "<div class=\"fn__flex fn__flex-wrap\" style=\"width: 238px\">";
|
||||
Array.from(Array(14).keys()).forEach(index => {
|
||||
html += `<button data-color="${index + 1}" class="color__square${parseInt(color) === index + 1 ? " color__square--current" : ""}" style="color: var(--b3-font-color${index + 1});background-color: var(--b3-font-background${index + 1});">A</button>`;
|
||||
});
|
||||
menu.addItem({
|
||||
type: "empty",
|
||||
iconHTML: "",
|
||||
label: html + "</div>",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.classList.contains("color__square") && !target.classList.contains("color__square--current")) {
|
||||
element.querySelector(".color__square--current")?.classList.remove("color__square--current");
|
||||
target.classList.add("color__square--current");
|
||||
const newColor = target.getAttribute("data-color");
|
||||
transaction(protyle, [{
|
||||
action: "updateAttrViewColOption",
|
||||
id: colId,
|
||||
avID: data.id,
|
||||
data: {
|
||||
oldName: name,
|
||||
newName: inputElement.value,
|
||||
oldColor: color,
|
||||
newColor,
|
||||
newDesc: descElement.value
|
||||
},
|
||||
}], [{
|
||||
action: "updateAttrViewColOption",
|
||||
id: colId,
|
||||
avID: data.id,
|
||||
data: {
|
||||
oldName: inputElement.value,
|
||||
newName: name,
|
||||
oldColor: newColor,
|
||||
newColor: color,
|
||||
newDesc: descElement.value
|
||||
},
|
||||
}]);
|
||||
|
||||
data.view.columns.find(column => {
|
||||
if (column.id === colId) {
|
||||
column.options.find((item) => {
|
||||
if (item.name === name) {
|
||||
item.name = inputElement.value;
|
||||
item.color = (index + 1).toString();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
const oldScroll = menuElement.querySelector(".b3-menu__items").scrollTop;
|
||||
if (!cellElements) {
|
||||
menuElement.innerHTML = getEditHTML({protyle, data, colId, isCustomAttr});
|
||||
bindEditEvent({protyle, data, menuElement, isCustomAttr, blockID});
|
||||
} else {
|
||||
cellElements.forEach((cellElement: HTMLElement, cellIndex) => {
|
||||
const rowElement = hasClosestByClassName(cellElement, "av__row");
|
||||
if (rowElement) {
|
||||
cellElement = cellElements[cellIndex] = (blockElement.querySelector(`.av__row[data-id="${rowElement.dataset.id}"] .av__cell[data-col-id="${cellElement.dataset.colId}"]`) ||
|
||||
blockElement.querySelector(`.fn__flex-1[data-col-id="${cellElement.dataset.colId}"]`)) as HTMLElement;
|
||||
}
|
||||
cellValues[cellIndex].mSelect.find((item) => {
|
||||
if (item.content === name) {
|
||||
item.content = inputElement.value;
|
||||
item.color = (index + 1).toString();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (cellElement.classList.contains("custom-attr__avvalue")) {
|
||||
cellElement.innerHTML = genAVValueHTML(cellValues[cellIndex]);
|
||||
} else {
|
||||
updateAttrViewCellAnimation(cellElement, cellValues[cellIndex]);
|
||||
data.view.columns.find(column => {
|
||||
if (column.id === colId) {
|
||||
column.options.find((item) => {
|
||||
if (item.name === name) {
|
||||
item.name = inputElement.value;
|
||||
item.color = newColor;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
});
|
||||
menuElement.innerHTML = getSelectHTML(data.view, cellElements);
|
||||
bindSelectEvent(protyle, data, menuElement, cellElements, blockElement);
|
||||
const oldScroll = menuElement.querySelector(".b3-menu__items").scrollTop;
|
||||
if (!cellElements) {
|
||||
menuElement.innerHTML = getEditHTML({protyle, data, colId, isCustomAttr});
|
||||
bindEditEvent({protyle, data, menuElement, isCustomAttr, blockID});
|
||||
} else {
|
||||
cellElements.forEach((cellElement: HTMLElement, cellIndex) => {
|
||||
const rowElement = hasClosestByClassName(cellElement, "av__row");
|
||||
if (rowElement) {
|
||||
cellElement = cellElements[cellIndex] = (blockElement.querySelector(`.av__row[data-id="${rowElement.dataset.id}"] .av__cell[data-col-id="${cellElement.dataset.colId}"]`) ||
|
||||
blockElement.querySelector(`.fn__flex-1[data-col-id="${cellElement.dataset.colId}"]`)) as HTMLElement;
|
||||
}
|
||||
cellValues[cellIndex].mSelect.find((item) => {
|
||||
if (item.content === name) {
|
||||
item.content = inputElement.value;
|
||||
item.color = newColor;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (cellElement.classList.contains("custom-attr__avvalue")) {
|
||||
cellElement.innerHTML = genAVValueHTML(cellValues[cellIndex]);
|
||||
} else {
|
||||
updateAttrViewCellAnimation(cellElement, cellValues[cellIndex]);
|
||||
}
|
||||
});
|
||||
menuElement.innerHTML = getSelectHTML(data.view, cellElements);
|
||||
bindSelectEvent(protyle, data, menuElement, cellElements, blockElement);
|
||||
}
|
||||
menuElement.querySelector(".b3-menu__items").scrollTop = oldScroll;
|
||||
name = inputElement.value;
|
||||
desc = descElement.value;
|
||||
color = newColor;
|
||||
}
|
||||
menuElement.querySelector(".b3-menu__items").scrollTop = oldScroll;
|
||||
name = inputElement.value;
|
||||
desc = descElement.value;
|
||||
color = (index + 1).toString();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
const rect = target.getBoundingClientRect();
|
||||
menu.open({
|
||||
|
@ -630,7 +634,7 @@ export const mergeAddOption = (column: IAVColumn, cellValue: IAVCellValue, avID:
|
|||
}
|
||||
});
|
||||
if (!needAdd) {
|
||||
const newColor = ((column.options?.length || 0) % 13 + 1).toString();
|
||||
const newColor = ((column.options?.length || 0) % 14 + 1).toString();
|
||||
column.options.push({
|
||||
name: item.content,
|
||||
color: newColor
|
||||
|
|
|
@ -61,7 +61,9 @@ export const scrollEvent = (protyle: IProtyle, element: HTMLElement) => {
|
|||
}
|
||||
if (protyle.wysiwyg.element.getAttribute("data-top") || protyle.block.showAll ||
|
||||
(protyle.scroll && protyle.scroll.element.classList.contains("fn__none")) || !protyle.scroll ||
|
||||
protyle.scroll.lastScrollTop === element.scrollTop || protyle.scroll.lastScrollTop === -1) {
|
||||
protyle.scroll.lastScrollTop === element.scrollTop || protyle.scroll.lastScrollTop === -1 ||
|
||||
// 移动端跳转的时候会设置 wysiwyg.element.innerHTML = "";
|
||||
!protyle.wysiwyg.element.firstElementChild) {
|
||||
return;
|
||||
}
|
||||
if (protyle.scroll.lastScrollTop - element.scrollTop > 0) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import {genAssetHTML} from "../../asset/renderAssets";
|
|||
import {hasClosestBlock} from "../util/hasClosest";
|
||||
import {getContenteditableElement} from "../wysiwyg/getBlock";
|
||||
import {getTypeByCellElement, updateCellsValue} from "../render/av/cell";
|
||||
import {scrollCenter} from "../../util/highlightById";
|
||||
|
||||
export class Upload {
|
||||
public element: HTMLElement;
|
||||
|
@ -118,28 +119,30 @@ const genUploadedLabel = (responseText: string, protyle: IProtyle) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
let succFileText = "";
|
||||
let successFileText = "";
|
||||
const keys = Object.keys(response.data.succMap);
|
||||
const avAssets: IAVCellAssetValue[] = [];
|
||||
let hasImage = false;
|
||||
keys.forEach((key, index) => {
|
||||
const path = response.data.succMap[key];
|
||||
const type = pathPosix().extname(key).toLowerCase();
|
||||
const filename = protyle.options.upload.filename(key);
|
||||
const name = filename.substring(0, filename.length - type.length);
|
||||
hasImage = Constants.SIYUAN_ASSETS_IMAGE.includes(type);
|
||||
avAssets.push({
|
||||
type: Constants.SIYUAN_ASSETS_IMAGE.includes(type) ? "image" : "file",
|
||||
content: path,
|
||||
name: name
|
||||
});
|
||||
succFileText += genAssetHTML(type, path, name, filename);
|
||||
successFileText += genAssetHTML(type, path, name, filename);
|
||||
if (!Constants.SIYUAN_ASSETS_AUDIO.includes(type) && !Constants.SIYUAN_ASSETS_VIDEO.includes(type) &&
|
||||
keys.length - 1 !== index) {
|
||||
if (nodeElement && nodeElement.classList.contains("table")) {
|
||||
succFileText += "<br>";
|
||||
successFileText += "<br>";
|
||||
} else if (insertBlock) {
|
||||
succFileText += "\n\n";
|
||||
successFileText += "\n\n";
|
||||
} else {
|
||||
succFileText += "\n";
|
||||
successFileText += "\n";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -191,7 +194,11 @@ const genUploadedLabel = (responseText: string, protyle: IProtyle) => {
|
|||
}
|
||||
}
|
||||
// 避免插入代码块中,其次因为都要独立成块 https://github.com/siyuan-note/siyuan/issues/7607
|
||||
insertHTML(succFileText, protyle, insertBlock);
|
||||
insertHTML(successFileText, protyle, insertBlock);
|
||||
// 粘贴图片后定位不准确 https://github.com/siyuan-note/siyuan/issues/13336
|
||||
setTimeout(() => {
|
||||
scrollCenter(protyle, undefined, false, "smooth");
|
||||
}, hasImage ? 0 : Constants.TIMEOUT_LOAD);
|
||||
};
|
||||
|
||||
export const uploadLocalFiles = (files: string[], protyle: IProtyle, isUpload: boolean) => {
|
||||
|
|
|
@ -300,6 +300,7 @@ export const getLocalStorage = (cb: () => void) => {
|
|||
replaceTypes: Object.assign({}, Constants.SIYUAN_DEFAULT_REPLACETYPES),
|
||||
};
|
||||
defaultStorage[Constants.LOCAL_ZOOM] = 1;
|
||||
defaultStorage[Constants.LOCAL_MOVE_PATH] = {keys: [], k: ""};
|
||||
|
||||
[Constants.LOCAL_EXPORTIMG, Constants.LOCAL_SEARCHKEYS, Constants.LOCAL_PDFTHEME, Constants.LOCAL_BAZAAR,
|
||||
Constants.LOCAL_EXPORTWORD, Constants.LOCAL_EXPORTPDF, Constants.LOCAL_DOCINFO, Constants.LOCAL_FONTSTYLES,
|
||||
|
@ -307,7 +308,7 @@ export const getLocalStorage = (cb: () => void) => {
|
|||
Constants.LOCAL_PLUGINTOPUNPIN, Constants.LOCAL_SEARCHASSET, Constants.LOCAL_FLASHCARD,
|
||||
Constants.LOCAL_DIALOGPOSITION, Constants.LOCAL_SEARCHUNREF, Constants.LOCAL_HISTORY,
|
||||
Constants.LOCAL_OUTLINE, Constants.LOCAL_FILEPOSITION, Constants.LOCAL_FILESPATHS, Constants.LOCAL_IMAGES,
|
||||
Constants.LOCAL_PLUGIN_DOCKS, Constants.LOCAL_EMOJIS].forEach((key) => {
|
||||
Constants.LOCAL_PLUGIN_DOCKS, Constants.LOCAL_EMOJIS, Constants.LOCAL_MOVE_PATH].forEach((key) => {
|
||||
if (typeof response.data[key] === "string") {
|
||||
try {
|
||||
const parseData = JSON.parse(response.data[key]);
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
import {hideElements} from "../ui/hideElements";
|
||||
import {isSupportCSSHL} from "../render/searchMarkRender";
|
||||
|
||||
export const destroy = (protyle: IProtyle) => {
|
||||
if (!protyle) {
|
||||
return;
|
||||
}
|
||||
hideElements(["util"], protyle);
|
||||
protyle.highlight.markHL.clear();
|
||||
protyle.highlight.mark.clear();
|
||||
protyle.highlight.ranges = [];
|
||||
protyle.highlight.rangeIndex = 0;
|
||||
if (isSupportCSSHL()) {
|
||||
protyle.highlight.markHL.clear();
|
||||
protyle.highlight.mark.clear();
|
||||
protyle.highlight.ranges = [];
|
||||
protyle.highlight.rangeIndex = 0;
|
||||
}
|
||||
protyle.observer?.disconnect();
|
||||
protyle.observerLoad?.disconnect();
|
||||
protyle.element.classList.remove("protyle");
|
||||
|
|
|
@ -1132,15 +1132,28 @@ export const dropEvent = (protyle: IProtyle, editorElement: HTMLElement) => {
|
|||
blockElement.setAttribute("updated", newUpdated);
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
if (ids[i]) {
|
||||
await fetchSyncPost("/api/filetree/doc2Heading", {
|
||||
srcID: ids[i],
|
||||
after: targetElement.classList.contains("dragover__bottom"),
|
||||
targetID: targetElement.getAttribute("data-node-id"),
|
||||
});
|
||||
if (targetElement.classList.contains("dragover__bottom")) {
|
||||
for (let i = ids.length - 1; i > -1; i--) {
|
||||
if (ids[i]) {
|
||||
await fetchSyncPost("/api/filetree/doc2Heading", {
|
||||
srcID: ids[i],
|
||||
after: true,
|
||||
targetID: targetElement.getAttribute("data-node-id"),
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
if (ids[i]) {
|
||||
await fetchSyncPost("/api/filetree/doc2Heading", {
|
||||
srcID: ids[i],
|
||||
after: false,
|
||||
targetID: targetElement.getAttribute("data-node-id"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fetchPost("/api/filetree/getDoc", {
|
||||
id: protyle.block.id,
|
||||
size: window.siyuan.config.editor.dynamicLoadBlocks,
|
||||
|
|
|
@ -502,6 +502,7 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
|
|||
return;
|
||||
} else if (files && files.length > 0) {
|
||||
uploadFiles(protyle, files);
|
||||
return;
|
||||
} else if (textPlain.trim() !== "" && files && files.length === 0) {
|
||||
if (range.toString() !== "") {
|
||||
const firstLine = textPlain.split("\n")[0];
|
||||
|
|
|
@ -46,7 +46,7 @@ export const reloadProtyle = (protyle: IProtyle, focus: boolean, updateReadonly?
|
|||
}, response => {
|
||||
protyle.options.backlinkData = isMention ? response.data.backmentions : response.data.backlinks;
|
||||
renderBacklink(protyle, protyle.options.backlinkData);
|
||||
searchMarkRender(protyle, keyword.split(" "));
|
||||
searchMarkRender(protyle, response.data.keywords);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -737,7 +737,14 @@ export const clearTableCell = (protyle: IProtyle, tableBlockElement: HTMLElement
|
|||
}
|
||||
});
|
||||
tableSelectElement.removeAttribute("style");
|
||||
if (getSelection().rangeCount>0) {
|
||||
const range = getSelection().getRangeAt(0);
|
||||
if (tableBlockElement.contains(range.startContainer)) {
|
||||
range.insertNode(document.createElement("wbr"));
|
||||
}
|
||||
}
|
||||
const oldHTML = tableBlockElement.outerHTML;
|
||||
tableBlockElement.querySelector("wbr")?.remove();
|
||||
tableBlockElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||
selectCellElements.forEach(item => {
|
||||
item.innerHTML = "";
|
||||
|
|
|
@ -1482,7 +1482,14 @@ export class WYSIWYG {
|
|||
}
|
||||
});
|
||||
tableSelectElement.removeAttribute("style");
|
||||
if (getSelection().rangeCount>0) {
|
||||
const range = getSelection().getRangeAt(0);
|
||||
if (nodeElement.contains(range.startContainer)) {
|
||||
range.insertNode(document.createElement("wbr"));
|
||||
}
|
||||
}
|
||||
const oldHTML = nodeElement.outerHTML;
|
||||
nodeElement.querySelector("wbr")?.remove();
|
||||
nodeElement.setAttribute("updated", dayjs().format("YYYYMMDDHHmmss"));
|
||||
selectCellElements.forEach((item, index) => {
|
||||
if (index === 0 || !item.previousElementSibling ||
|
||||
|
|
|
@ -12,6 +12,7 @@ import {hasClosestByClassName} from "../protyle/util/hasClosest";
|
|||
import {addClearButton} from "../util/addClearButton";
|
||||
import {isPaidUser} from "../util/needSubscribe";
|
||||
import {showMessage} from "../dialog/message";
|
||||
import {saveAssetKeyList} from "./toggleHistory";
|
||||
|
||||
export const openSearchAsset = (element: Element, isStick: boolean) => {
|
||||
/// #if !MOBILE
|
||||
|
@ -108,18 +109,7 @@ export const openSearchAsset = (element: Element, isStick: boolean) => {
|
|||
assetInputEvent(element, localSearch);
|
||||
});
|
||||
searchInputElement.addEventListener("blur", () => {
|
||||
if (!searchInputElement.value) {
|
||||
return;
|
||||
}
|
||||
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys;
|
||||
list.splice(0, 0, searchInputElement.value);
|
||||
list = Array.from(new Set(list));
|
||||
if (list.length > window.siyuan.config.search.limit) {
|
||||
list.splice(window.siyuan.config.search.limit, list.length - window.siyuan.config.search.limit);
|
||||
}
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].k = searchInputElement.value;
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = list;
|
||||
setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
|
||||
saveAssetKeyList(searchInputElement);
|
||||
});
|
||||
assetInputEvent(element, localSearch);
|
||||
addClearButton({
|
||||
|
@ -242,75 +232,6 @@ export const assetInputEvent = (element: Element, localSearch?: ISearchAssetOpti
|
|||
}, Constants.TIMEOUT_INPUT);
|
||||
};
|
||||
|
||||
export const toggleAssetHistory = (assetElement: Element) => {
|
||||
const keys = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys;
|
||||
if (!keys || keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("search-asset-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = [];
|
||||
setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
const assetInputElement = assetElement.querySelector("#searchAssetInput") as HTMLInputElement;
|
||||
keys.forEach((s: string) => {
|
||||
if (s !== assetInputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
keys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
keys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = keys;
|
||||
setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
assetInputElement.value = element.textContent;
|
||||
assetInputEvent(assetElement);
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = assetInputElement.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
|
||||
export const renderPreview = (element: Element, id: string, query: string, queryMethod: number) => {
|
||||
fetchPost("/api/search/getAssetContent", {id, query, queryMethod}, (response) => {
|
||||
element.innerHTML = `<p style="white-space: pre-wrap;">${response.data.assetContent.content}</p>`;
|
||||
|
|
249
app/src/search/toggleHistory.ts
Normal file
249
app/src/search/toggleHistory.ts
Normal file
|
@ -0,0 +1,249 @@
|
|||
import {Constants} from "../constants";
|
||||
import {Menu} from "../plugin/Menu";
|
||||
import {setStorageVal} from "../protyle/util/compatibility";
|
||||
import {escapeHtml} from "../util/escape";
|
||||
import {hasClosestByClassName} from "../protyle/util/hasClosest";
|
||||
import {Protyle} from "../protyle";
|
||||
import {assetInputEvent} from "./assets";
|
||||
/// #if MOBILE
|
||||
import {updateSearchResult} from "../mobile/menu/search";
|
||||
/// #else
|
||||
import {inputEvent} from "./util";
|
||||
/// #endif
|
||||
|
||||
export const toggleReplaceHistory = (replaceInputElement: HTMLInputElement) => {
|
||||
const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
|
||||
if (!list.replaceKeys || list.replaceKeys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("search-replace-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = [];
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
list.replaceKeys.forEach((s: string) => {
|
||||
if (s !== replaceInputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
list.replaceKeys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
list.replaceKeys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = list.replaceKeys;
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
replaceInputElement.value = element.textContent;
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = replaceInputElement.previousElementSibling.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
|
||||
export const toggleSearchHistory = (searchElement: Element, config: Config.IUILayoutTabSearchConfig, edit: Protyle) => {
|
||||
const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
|
||||
if (!list.keys || list.keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("search-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = [];
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
const searchInputElement = searchElement.querySelector("#searchInput, #toolbarSearch") as HTMLInputElement;
|
||||
list.keys.forEach((s: string) => {
|
||||
if (s !== searchInputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
list.keys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
list.keys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = list.keys;
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
searchInputElement.value = element.textContent;
|
||||
config.page = 1;
|
||||
/// #if MOBILE
|
||||
updateSearchResult(config, searchElement, true);
|
||||
/// #else
|
||||
inputEvent(searchElement, config, edit, true);
|
||||
/// #endif
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = searchInputElement.previousElementSibling.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
|
||||
export const toggleAssetHistory = (assetElement: Element) => {
|
||||
const keys = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys;
|
||||
if (!keys || keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("search-asset-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = [];
|
||||
setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
const assetInputElement = assetElement.querySelector("#searchAssetInput") as HTMLInputElement;
|
||||
keys.forEach((s: string) => {
|
||||
if (s !== assetInputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
keys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
keys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = keys;
|
||||
setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
assetInputElement.value = element.textContent;
|
||||
assetInputEvent(assetElement);
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = assetInputElement.previousElementSibling.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
|
||||
export const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
|
||||
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type];
|
||||
list.splice(0, 0, value);
|
||||
list = Array.from(new Set(list));
|
||||
if (list.length > window.siyuan.config.search.limit) {
|
||||
list.splice(window.siyuan.config.search.limit, list.length - window.siyuan.config.search.limit);
|
||||
}
|
||||
// new Set 后需重新赋值
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type] = list;
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
};
|
||||
|
||||
export const saveAssetKeyList = (inputElement:HTMLInputElement) => {
|
||||
if (!inputElement.value) {
|
||||
return;
|
||||
}
|
||||
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys;
|
||||
list.splice(0, 0, inputElement.value);
|
||||
list = Array.from(new Set(list));
|
||||
if (list.length > window.siyuan.config.search.limit) {
|
||||
list.splice(window.siyuan.config.search.limit, list.length - window.siyuan.config.search.limit);
|
||||
}
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].k = inputElement.value;
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHASSET].keys = list;
|
||||
setStorageVal(Constants.LOCAL_SEARCHASSET, window.siyuan.storage[Constants.LOCAL_SEARCHASSET]);
|
||||
};
|
|
@ -43,165 +43,14 @@ import {
|
|||
openSearchAsset,
|
||||
renderNextAssetMark,
|
||||
renderPreview,
|
||||
toggleAssetHistory
|
||||
} from "./assets";
|
||||
import {resize} from "../protyle/util/resize";
|
||||
import {Menu} from "../plugin/Menu";
|
||||
import {addClearButton} from "../util/addClearButton";
|
||||
import {checkFold} from "../util/noRelyPCFunction";
|
||||
import {getUnRefList, openSearchUnRef, unRefMoreMenu} from "./unRef";
|
||||
import {getDefaultType} from "./getDefault";
|
||||
import {isSupportCSSHL, searchMarkRender} from "../protyle/render/searchMarkRender";
|
||||
|
||||
export const toggleReplaceHistory = (searchElement: Element) => {
|
||||
const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
|
||||
if (!list.replaceKeys || list.replaceKeys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("search-replace-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = [];
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
const replaceInputElement = searchElement.querySelector("#replaceInput") as HTMLInputElement;
|
||||
list.replaceKeys.forEach((s: string) => {
|
||||
if (s !== replaceInputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
list.replaceKeys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
list.replaceKeys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].replaceKeys = list.replaceKeys;
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
replaceInputElement.value = element.textContent;
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = replaceInputElement.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
|
||||
export const toggleSearchHistory = (searchElement: Element, config: Config.IUILayoutTabSearchConfig, edit: Protyle) => {
|
||||
const list = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS];
|
||||
if (!list.keys || list.keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("search-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = [];
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
const searchInputElement = searchElement.querySelector("#searchInput") as HTMLInputElement;
|
||||
list.keys.forEach((s: string) => {
|
||||
if (s !== searchInputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
list.keys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
list.keys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS].keys = list.keys;
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
searchInputElement.value = element.textContent;
|
||||
config.page = 1;
|
||||
inputEvent(searchElement, config, edit, true);
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = searchInputElement.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
|
||||
const saveKeyList = (type: "keys" | "replaceKeys", value: string) => {
|
||||
let list: string[] = window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type];
|
||||
list.splice(0, 0, value);
|
||||
list = Array.from(new Set(list));
|
||||
if (list.length > window.siyuan.config.search.limit) {
|
||||
list.splice(window.siyuan.config.search.limit, list.length - window.siyuan.config.search.limit);
|
||||
}
|
||||
// new Set 后需重新赋值
|
||||
window.siyuan.storage[Constants.LOCAL_SEARCHKEYS][type] = list;
|
||||
setStorageVal(Constants.LOCAL_SEARCHKEYS, window.siyuan.storage[Constants.LOCAL_SEARCHKEYS]);
|
||||
};
|
||||
import {saveKeyList, toggleAssetHistory, toggleReplaceHistory, toggleSearchHistory} from "./toggleHistory";
|
||||
|
||||
export const openGlobalSearch = (app: App, text: string, replace: boolean, searchData?: Config.IUILayoutTabSearchConfig) => {
|
||||
text = text.trim();
|
||||
|
@ -296,7 +145,7 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
|
|||
</div>
|
||||
<div class="b3-form__icon search__header">
|
||||
<div style="position: relative" class="fn__flex-1">
|
||||
<span class="search__history-icon ariaLabel" id="searchHistoryBtn" aria-label="${updateHotkeyTip("⌥↓")}">
|
||||
<span class="search__history-icon ariaLabel" id="searchHistoryBtn" aria-label="${updateHotkeyTip("⌥↓")}">
|
||||
<svg data-menu="true" class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg>
|
||||
<svg class="search__arrowdown"><use xlink:href="#iconDown"></use></svg>
|
||||
</span>
|
||||
|
@ -908,7 +757,7 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
|
|||
event.preventDefault();
|
||||
return;
|
||||
} else if (target.id === "replaceHistoryBtn") {
|
||||
toggleReplaceHistory(element);
|
||||
toggleReplaceHistory(element.querySelector("#replaceInput"));
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return;
|
||||
|
|
4
app/src/types/config.d.ts
vendored
4
app/src/types/config.d.ts
vendored
|
@ -1349,6 +1349,10 @@ declare namespace Config {
|
|||
* - `3`: Completely manual synchronization
|
||||
*/
|
||||
mode: number;
|
||||
/**
|
||||
* Synchronization interval (unit: seconds)
|
||||
*/
|
||||
interval: number;
|
||||
/**
|
||||
* Whether to enable synchronization perception
|
||||
*/
|
||||
|
|
|
@ -201,7 +201,28 @@ export const addGA = () => {
|
|||
|
||||
export const setInlineStyle = (set = true) => {
|
||||
const height = Math.floor(window.siyuan.config.editor.fontSize * 1.625);
|
||||
let style = `.b3-typography, .protyle-wysiwyg, .protyle-title {font-size:${window.siyuan.config.editor.fontSize}px !important}
|
||||
let style;
|
||||
if (window.siyuan.config.editor.fontFamily) {
|
||||
style = `@font-face {
|
||||
font-family: "Number Glyphs";
|
||||
src: local("${window.siyuan.config.editor.fontFamily}");
|
||||
unicode-range: U+30-39;
|
||||
}
|
||||
.b3-typography:not(.b3-typography--default), .protyle-wysiwyg, .protyle-title {font-family: "Number Glyphs", "SiYuan Emojis", "${window.siyuan.config.editor.fontFamily}", var(--b3-font-family-protyle)}`;
|
||||
} else {
|
||||
style = `@font-face {
|
||||
font-family: "Number Glyphs";
|
||||
src: local("Helvetica Neue"),
|
||||
local("Luxi Sans"),
|
||||
local("DejaVu Sans"),
|
||||
local("Hiragino Sans GB"),
|
||||
local("Segoe UI"),
|
||||
local("Microsoft Yahei"),
|
||||
local("sans-serif");
|
||||
unicode-range: U+30-39;
|
||||
}`;
|
||||
}
|
||||
style += `.b3-typography, .protyle-wysiwyg, .protyle-title {font-size:${window.siyuan.config.editor.fontSize}px !important}
|
||||
.b3-typography code:not(.hljs), .protyle-wysiwyg span[data-type~=code] { font-variant-ligatures: ${window.siyuan.config.editor.codeLigatures ? "normal" : "none"} }
|
||||
.li > .protyle-action {height:${height + 8}px;line-height: ${height + 8}px}
|
||||
.protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h1, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h2, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h3, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h4, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h5, .protyle-wysiwyg [data-node-id].li > .protyle-action ~ .h6 {line-height:${height + 8}px;}
|
||||
|
@ -218,9 +239,6 @@ export const setInlineStyle = (set = true) => {
|
|||
.protyle-wysiwyg [data-node-id] {${window.siyuan.config.editor.justify ? " text-align: justify;" : ""}}
|
||||
.protyle-wysiwyg .li {min-height:${height + 8}px}
|
||||
.protyle-gutters button svg {height:${height}px}`;
|
||||
if (window.siyuan.config.editor.fontFamily) {
|
||||
style += `\n.b3-typography:not(.b3-typography--default), .protyle-wysiwyg, .protyle-title {font-family: "${window.siyuan.config.editor.fontFamily}", var(--b3-font-family-protyle)}`;
|
||||
}
|
||||
// pad 端菜单移除显示,如工作空间
|
||||
if ("ontouchend" in document) {
|
||||
style += "\n.b3-menu .b3-menu__action {opacity: 0.68;}";
|
||||
|
|
|
@ -59,7 +59,7 @@ const focusStack = async (app: App, stack: IBackStack) => {
|
|||
tab,
|
||||
blockId: stack.zoomId || stack.protyle.block.rootID,
|
||||
rootId: stack.protyle.block.rootID,
|
||||
action: stack.zoomId ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL] : [Constants.CB_GET_FOCUS]
|
||||
action: stack.zoomId ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_UNUNDO] : [Constants.CB_GET_FOCUS, Constants.CB_GET_UNUNDO]
|
||||
});
|
||||
tab.addModel(editor);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@ import {Constants} from "../constants";
|
|||
import {ipcRenderer} from "electron";
|
||||
/// #endif
|
||||
import {showMessage} from "../dialog/message";
|
||||
import {isOnlyMeta} from "../protyle/util/compatibility";
|
||||
import {isOnlyMeta, setStorageVal, updateHotkeyTip} from "../protyle/util/compatibility";
|
||||
import {matchHotKey} from "../protyle/util/hotKey";
|
||||
import {Menu} from "../plugin/Menu";
|
||||
import {hasClosestByClassName} from "../protyle/util/hasClosest";
|
||||
|
||||
export const showFileInFolder = (filePath: string) => {
|
||||
/// #if !BROWSER
|
||||
|
@ -154,8 +157,11 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void,
|
|||
title: `${title || window.siyuan.languages.move}
|
||||
<div style="max-height: 16px;overflow: auto;line-height: 14px;-webkit-mask-image: linear-gradient(to top, rgba(0, 0, 0, 0) 0, #000 6px);padding-bottom: 4px;margin-bottom: -4px" class="ft__smaller ft__on-surface fn__hidescrollbar"></div>`,
|
||||
content: `<div class="b3-form__icon" style="margin: 8px">
|
||||
<svg class="b3-form__icon-icon"><use xlink:href="#iconSearch"></use></svg>
|
||||
<input class="b3-text-field fn__block b3-form__icon-input" value="" placeholder="${window.siyuan.languages.search}">
|
||||
<span data-menu="true" class="b3-form__icon-list fn__a b3-tooltips b3-tooltips__s" aria-label="${updateHotkeyTip("⌥↓")}">
|
||||
<svg class="svg--mid"><use xlink:href="#iconSearch"></use></svg>
|
||||
<svg class="svg--smaller"><use xlink:href="#iconDown"></use></svg>
|
||||
</span>
|
||||
<input class="b3-text-field fn__block" style="padding-left: 42px;" value="" placeholder="${window.siyuan.languages.search}">
|
||||
</div>
|
||||
<ul id="foldList" class="fn__flex-1 fn__none b3-list b3-list--background${isMobile() ? " b3-list--mobile" : ""}" style="overflow: auto;position: relative"></ul>
|
||||
<div id="foldTree" class="fn__flex-1${isMobile() ? " b3-list--mobile" : ""}" style="overflow: auto;position: relative"></div>
|
||||
|
@ -205,8 +211,9 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void,
|
|||
}, flashcard);
|
||||
|
||||
const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement;
|
||||
inputElement.value = window.siyuan.storage[Constants.LOCAL_MOVE_PATH].k;
|
||||
/// #if !MOBILE
|
||||
inputElement.focus();
|
||||
inputElement.select();
|
||||
/// #endif
|
||||
const inputEvent = (event?: InputEvent) => {
|
||||
if (event && event.isComposing) {
|
||||
|
@ -250,6 +257,74 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void,
|
|||
searchListElement.innerHTML = fileHTML;
|
||||
});
|
||||
};
|
||||
|
||||
const toggleMovePathHistory = () => {
|
||||
const keys = window.siyuan.storage[Constants.LOCAL_MOVE_PATH].keys;
|
||||
if (!keys || keys.length === 0) {
|
||||
return;
|
||||
}
|
||||
const menu = new Menu("move-path-history");
|
||||
if (menu.isOpen) {
|
||||
return;
|
||||
}
|
||||
menu.element.classList.add("b3-menu--list");
|
||||
menu.addItem({
|
||||
iconHTML: "",
|
||||
label: window.siyuan.languages.clearHistory,
|
||||
click() {
|
||||
window.siyuan.storage[Constants.LOCAL_MOVE_PATH].keys = [];
|
||||
setStorageVal(Constants.LOCAL_MOVE_PATH, window.siyuan.storage[Constants.LOCAL_MOVE_PATH]);
|
||||
}
|
||||
});
|
||||
const separatorElement = menu.addSeparator(1);
|
||||
let current = true;
|
||||
keys.forEach((s: string) => {
|
||||
if (s !== inputElement.value && s) {
|
||||
const menuItem = menu.addItem({
|
||||
iconHTML: "",
|
||||
label: escapeHtml(s),
|
||||
action: "iconCloseRound",
|
||||
bind(element) {
|
||||
element.addEventListener("click", (itemEvent) => {
|
||||
if (hasClosestByClassName(itemEvent.target as Element, "b3-menu__action")) {
|
||||
keys.find((item: string, index: number) => {
|
||||
if (item === s) {
|
||||
keys.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
window.siyuan.storage[Constants.LOCAL_MOVE_PATH].keys = keys;
|
||||
setStorageVal(Constants.LOCAL_MOVE_PATH, window.siyuan.storage[Constants.LOCAL_MOVE_PATH]);
|
||||
if (element.previousElementSibling?.classList.contains("b3-menu__separator") && !element.nextElementSibling) {
|
||||
window.siyuan.menus.menu.remove();
|
||||
} else {
|
||||
element.remove();
|
||||
}
|
||||
} else {
|
||||
inputElement.value = element.textContent;
|
||||
inputEvent();
|
||||
window.siyuan.menus.menu.remove();
|
||||
}
|
||||
itemEvent.preventDefault();
|
||||
itemEvent.stopPropagation();
|
||||
});
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
menuItem.classList.add("b3-menu__item--current");
|
||||
}
|
||||
current = false;
|
||||
}
|
||||
});
|
||||
if (current) {
|
||||
separatorElement.remove();
|
||||
}
|
||||
const rect = inputElement.getBoundingClientRect();
|
||||
menu.open({
|
||||
x: rect.left,
|
||||
y: rect.bottom
|
||||
});
|
||||
};
|
||||
inputEvent();
|
||||
inputElement.addEventListener("compositionend", (event: InputEvent) => {
|
||||
inputEvent(event);
|
||||
|
@ -257,11 +332,33 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void,
|
|||
inputElement.addEventListener("input", (event: InputEvent) => {
|
||||
inputEvent(event);
|
||||
});
|
||||
inputElement.addEventListener("blur", () => {
|
||||
if (!inputElement.value) {
|
||||
return;
|
||||
}
|
||||
let list: string[] = window.siyuan.storage[Constants.LOCAL_MOVE_PATH].keys;
|
||||
list.splice(0, 0, inputElement.value);
|
||||
list = Array.from(new Set(list));
|
||||
if (list.length > window.siyuan.config.search.limit) {
|
||||
list.splice(window.siyuan.config.search.limit, list.length - window.siyuan.config.search.limit);
|
||||
}
|
||||
window.siyuan.storage[Constants.LOCAL_MOVE_PATH].k = inputElement.value;
|
||||
window.siyuan.storage[Constants.LOCAL_MOVE_PATH].keys = list;
|
||||
setStorageVal(Constants.LOCAL_MOVE_PATH, window.siyuan.storage[Constants.LOCAL_MOVE_PATH]);
|
||||
});
|
||||
const lineHeight = 28;
|
||||
inputElement.addEventListener("keydown", (event: KeyboardEvent) => {
|
||||
if (event.isComposing) {
|
||||
return;
|
||||
}
|
||||
if (matchHotKey("⌥↓", event)) {
|
||||
event.stopPropagation();
|
||||
toggleMovePathHistory();
|
||||
return;
|
||||
}
|
||||
if (window.siyuan.menus.menu.element.getAttribute("data-name") === "move-path-history") {
|
||||
return;
|
||||
}
|
||||
const currentPanelElement = searchListElement.classList.contains("fn__none") ? searchTreeElement : searchListElement;
|
||||
const currentItemElements = currentPanelElement.querySelectorAll(".b3-list-item--focus");
|
||||
if (currentItemElements.length === 0) {
|
||||
|
@ -424,6 +521,11 @@ export const movePathTo = (cb: (toPath: string[], toNotebook: string[]) => void,
|
|||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (target.classList.contains("b3-form__icon-list")) {
|
||||
toggleMovePathHistory();
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
break;
|
||||
} else if (target.classList.contains("b3-button--text")) {
|
||||
const currentPanelElement = searchListElement.classList.contains("fn__none") ? searchTreeElement : searchListElement;
|
||||
const currentItemElements = currentPanelElement.querySelectorAll(".b3-list-item--focus");
|
||||
|
|
4
app/stage/protyle/js/lute/lute.min.js
vendored
4
app/stage/protyle/js/lute/lute.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -26,6 +26,7 @@ import (
|
|||
"github.com/88250/lute/html"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/siyuan-note/logging"
|
||||
"github.com/siyuan-note/siyuan/kernel/filesys"
|
||||
"github.com/siyuan-note/siyuan/kernel/model"
|
||||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
@ -320,7 +321,7 @@ func getContentWordCount(c *gin.Context) {
|
|||
}
|
||||
|
||||
content := arg["content"].(string)
|
||||
ret.Data = model.ContentStat(content)
|
||||
ret.Data = filesys.ContentStat(content)
|
||||
}
|
||||
|
||||
func getBlocksWordCount(c *gin.Context) {
|
||||
|
@ -337,7 +338,7 @@ func getBlocksWordCount(c *gin.Context) {
|
|||
for _, id := range idsArg {
|
||||
ids = append(ids, id.(string))
|
||||
}
|
||||
ret.Data = model.BlocksWordCount(ids)
|
||||
ret.Data = filesys.BlocksWordCount(ids)
|
||||
}
|
||||
|
||||
func getTreeStat(c *gin.Context) {
|
||||
|
@ -350,7 +351,7 @@ func getTreeStat(c *gin.Context) {
|
|||
}
|
||||
|
||||
id := arg["id"].(string)
|
||||
ret.Data = model.StatTree(id)
|
||||
ret.Data = filesys.StatTree(id)
|
||||
}
|
||||
|
||||
func getDOMText(c *gin.Context) {
|
||||
|
|
|
@ -60,9 +60,10 @@ func getBackmentionDoc(c *gin.Context) {
|
|||
if val, ok := arg["highlight"]; ok {
|
||||
highlight = val.(bool)
|
||||
}
|
||||
backlinks := model.GetBackmentionDoc(defID, refTreeID, keyword, containChildren, highlight)
|
||||
backlinks, keywords := model.GetBackmentionDoc(defID, refTreeID, keyword, containChildren, highlight)
|
||||
ret.Data = map[string]interface{}{
|
||||
"backmentions": backlinks,
|
||||
"keywords": keywords,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,9 +87,10 @@ func getBacklinkDoc(c *gin.Context) {
|
|||
if val, ok := arg["highlight"]; ok {
|
||||
highlight = val.(bool)
|
||||
}
|
||||
backlinks := model.GetBacklinkDoc(defID, refTreeID, keyword, containChildren, highlight)
|
||||
backlinks, keywords := model.GetBacklinkDoc(defID, refTreeID, keyword, containChildren, highlight)
|
||||
ret.Data = map[string]interface{}{
|
||||
"backlinks": backlinks,
|
||||
"keywords": keywords,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -237,6 +237,7 @@ func ServeAPI(ginServer *gin.Engine) {
|
|||
ginServer.Handle("POST", "/api/cloud/getCloudSpace", model.CheckAuth, model.CheckAdminRole, getCloudSpace)
|
||||
|
||||
ginServer.Handle("POST", "/api/sync/setSyncEnable", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncEnable)
|
||||
ginServer.Handle("POST", "/api/sync/setSyncInterval", model.CheckAuth, setSyncInterval)
|
||||
ginServer.Handle("POST", "/api/sync/setSyncPerception", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncPerception)
|
||||
ginServer.Handle("POST", "/api/sync/setSyncGenerateConflictDoc", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncGenerateConflictDoc)
|
||||
ginServer.Handle("POST", "/api/sync/setSyncMode", model.CheckAuth, model.CheckAdminRole, model.CheckReadonly, setSyncMode)
|
||||
|
|
|
@ -541,6 +541,17 @@ func setSyncEnable(c *gin.Context) {
|
|||
model.SetSyncEnable(enabled)
|
||||
}
|
||||
|
||||
func setSyncInterval(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
arg, ok := util.JsonArg(c, ret)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
interval := int(arg["interval"].(float64))
|
||||
model.SetSyncInterval(interval)
|
||||
}
|
||||
|
||||
func setSyncPerception(c *gin.Context) {
|
||||
ret := gulu.Ret.NewResult()
|
||||
defer c.JSON(http.StatusOK, ret)
|
||||
|
|
|
@ -80,6 +80,12 @@ func renderTemplate(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if !util.IsAbsPathInWorkspace(p) {
|
||||
ret.Code = -1
|
||||
ret.Msg = "Path [" + p + "] is not in workspace"
|
||||
return
|
||||
}
|
||||
|
||||
preview := false
|
||||
if previewArg := arg["preview"]; nil != previewArg {
|
||||
preview = previewArg.(bool)
|
||||
|
|
|
@ -21,6 +21,7 @@ type Sync struct {
|
|||
Enabled bool `json:"enabled"` // 是否开启同步
|
||||
Perception bool `json:"perception"` // 是否开启感知
|
||||
Mode int `json:"mode"` // 同步模式,0:未设置(为兼容已有配置,initConf 函数中会转换为 1),1:自动,2:手动 https://github.com/siyuan-note/siyuan/issues/5089,3:完全手动 https://github.com/siyuan-note/siyuan/issues/7295
|
||||
Interval int `json:"interval"` // 自动同步间隔,单位:秒
|
||||
Synced int64 `json:"synced"` // 最近同步时间
|
||||
Stat string `json:"stat"` // 最近同步统计信息
|
||||
GenerateConflictDoc bool `json:"generateConflictDoc"` // 云端同步冲突时是否生成冲突文档
|
||||
|
@ -37,6 +38,7 @@ func NewSync() *Sync {
|
|||
Mode: 1,
|
||||
GenerateConflictDoc: false,
|
||||
Provider: ProviderSiYuan,
|
||||
Interval: 30,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
223
kernel/filesys/stat.go
Normal file
223
kernel/filesys/stat.go
Normal file
|
@ -0,0 +1,223 @@
|
|||
// SiYuan - Refactor your thinking
|
||||
// Copyright (c) 2020-present, b3log.org
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package filesys
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/88250/lute"
|
||||
"github.com/88250/lute/ast"
|
||||
"github.com/88250/lute/parse"
|
||||
"github.com/siyuan-note/siyuan/kernel/av"
|
||||
"github.com/siyuan-note/siyuan/kernel/treenode"
|
||||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
)
|
||||
|
||||
func ContentStat(content string) (ret *util.BlockStatResult) {
|
||||
luteEngine := util.NewLute()
|
||||
return contentStat(content, luteEngine)
|
||||
}
|
||||
|
||||
func contentStat(content string, luteEngine *lute.Lute) (ret *util.BlockStatResult) {
|
||||
tree := luteEngine.BlockDOM2Tree(content)
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat()
|
||||
return &util.BlockStatResult{
|
||||
RuneCount: runeCnt,
|
||||
WordCount: wordCnt,
|
||||
LinkCount: linkCnt,
|
||||
ImageCount: imgCnt,
|
||||
RefCount: refCnt,
|
||||
}
|
||||
}
|
||||
|
||||
func StatBlock(id string) (ret *util.BlockStatResult) {
|
||||
trees := LoadTrees([]string{id})
|
||||
if 1 > len(trees) {
|
||||
return
|
||||
}
|
||||
|
||||
tree := trees[id]
|
||||
if nil == tree {
|
||||
return
|
||||
}
|
||||
|
||||
node := treenode.GetNodeInTree(tree, id)
|
||||
if nil == node {
|
||||
return
|
||||
}
|
||||
|
||||
if ast.NodeDocument == node.Type {
|
||||
return statTree(tree)
|
||||
}
|
||||
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := node.Stat()
|
||||
ret = &util.BlockStatResult{
|
||||
runeCnt,
|
||||
wordCnt,
|
||||
linkCnt,
|
||||
imgCnt,
|
||||
refCnt,
|
||||
1,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func StatTree(id string) (ret *util.BlockStatResult) {
|
||||
trees := LoadTrees([]string{id})
|
||||
if 1 > len(trees) {
|
||||
return
|
||||
}
|
||||
|
||||
tree := trees[id]
|
||||
if nil == tree {
|
||||
return
|
||||
}
|
||||
|
||||
return statTree(tree)
|
||||
}
|
||||
|
||||
func statTree(tree *parse.Tree) (ret *util.BlockStatResult) {
|
||||
blockCount := 0
|
||||
var databaseBlockNodes []*ast.Node
|
||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
if n.IsBlock() {
|
||||
blockCount++
|
||||
}
|
||||
|
||||
if ast.NodeAttributeView != n.Type {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
databaseBlockNodes = append(databaseBlockNodes, n)
|
||||
return ast.WalkContinue
|
||||
})
|
||||
|
||||
luteEngine := util.NewLute()
|
||||
var dbRuneCnt, dbWordCnt, dbLinkCnt, dbImgCnt, dbRefCnt int
|
||||
for _, n := range databaseBlockNodes {
|
||||
if "" == n.AttributeViewID {
|
||||
continue
|
||||
}
|
||||
|
||||
attrView, _ := av.ParseAttributeView(n.AttributeViewID)
|
||||
if nil == attrView {
|
||||
continue
|
||||
}
|
||||
|
||||
content := bytes.Buffer{}
|
||||
for _, kValues := range attrView.KeyValues {
|
||||
for _, v := range kValues.Values {
|
||||
switch kValues.Key.Type {
|
||||
case av.KeyTypeURL:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
dbLinkCnt++
|
||||
content.WriteString(v.URL.Content)
|
||||
case av.KeyTypeMAsset:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, asset := range v.MAsset {
|
||||
if av.AssetTypeImage == asset.Type {
|
||||
dbImgCnt++
|
||||
}
|
||||
}
|
||||
case av.KeyTypeBlock:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !v.IsDetached {
|
||||
dbRefCnt++
|
||||
}
|
||||
content.WriteString(v.Block.Content)
|
||||
case av.KeyTypeText:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
content.WriteString(v.Text.Content)
|
||||
case av.KeyTypeNumber:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
v.Number.FormatNumber()
|
||||
content.WriteString(v.Number.FormattedContent)
|
||||
case av.KeyTypeEmail:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
content.WriteString(v.Email.Content)
|
||||
case av.KeyTypePhone:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
content.WriteString(v.Phone.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbStat := contentStat(content.String(), luteEngine)
|
||||
dbRuneCnt += dbStat.RuneCount
|
||||
dbWordCnt += dbStat.WordCount
|
||||
}
|
||||
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat()
|
||||
runeCnt += dbRuneCnt
|
||||
wordCnt += dbWordCnt
|
||||
linkCnt += dbLinkCnt
|
||||
imgCnt += dbImgCnt
|
||||
refCnt += dbRefCnt
|
||||
return &util.BlockStatResult{
|
||||
RuneCount: runeCnt,
|
||||
WordCount: wordCnt,
|
||||
LinkCount: linkCnt,
|
||||
ImageCount: imgCnt,
|
||||
RefCount: refCnt,
|
||||
BlockCount: blockCount,
|
||||
}
|
||||
}
|
||||
|
||||
func BlocksWordCount(ids []string) (ret *util.BlockStatResult) {
|
||||
ret = &util.BlockStatResult{}
|
||||
trees := LoadTrees(ids)
|
||||
for _, id := range ids {
|
||||
tree := trees[id]
|
||||
if nil == tree {
|
||||
continue
|
||||
}
|
||||
|
||||
node := treenode.GetNodeInTree(tree, id)
|
||||
if nil == node {
|
||||
continue
|
||||
}
|
||||
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := node.Stat()
|
||||
ret.RuneCount += runeCnt
|
||||
ret.WordCount += wordCnt
|
||||
ret.LinkCount += linkCnt
|
||||
ret.ImageCount += imgCnt
|
||||
ret.RefCount += refCnt
|
||||
}
|
||||
ret.BlockCount = len(ids)
|
||||
return
|
||||
}
|
|
@ -14,23 +14,31 @@
|
|||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package treenode
|
||||
package filesys
|
||||
|
||||
import (
|
||||
"math"
|
||||
"text/template"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/88250/go-humanize"
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/araddon/dateparse"
|
||||
"github.com/siyuan-note/logging"
|
||||
"github.com/siyuan-note/siyuan/kernel/treenode"
|
||||
"github.com/siyuan-note/siyuan/kernel/util"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
func BuiltInTemplateFuncs() (ret template.FuncMap) {
|
||||
ret = sprig.TxtFuncMap()
|
||||
|
||||
// 因为安全原因移除一些函数 https://github.com/siyuan-note/siyuan/issues/13426
|
||||
delete(ret, "env")
|
||||
delete(ret, "expandenv")
|
||||
delete(ret, "getHostByName")
|
||||
|
||||
ret["Weekday"] = util.Weekday
|
||||
ret["WeekdayCN"] = util.WeekdayCN
|
||||
ret["WeekdayCN2"] = util.WeekdayCN2
|
||||
|
@ -42,9 +50,15 @@ func BuiltInTemplateFuncs() (ret template.FuncMap) {
|
|||
ret["parseTime"] = parseTime
|
||||
ret["FormatFloat"] = FormatFloat
|
||||
ret["getHPathByID"] = getHPathByID
|
||||
ret["statBlock"] = StatBlock
|
||||
ret["runeLen"] = runeLen
|
||||
return
|
||||
}
|
||||
|
||||
func runeLen(s string) int {
|
||||
return utf8.RuneCountInString(s)
|
||||
}
|
||||
|
||||
func pow(a, b interface{}) int64 { return int64(math.Pow(cast.ToFloat64(a), cast.ToFloat64(b))) }
|
||||
func powf(a, b interface{}) float64 { return math.Pow(cast.ToFloat64(a), cast.ToFloat64(b)) }
|
||||
func log(a, b interface{}) int64 {
|
||||
|
@ -67,7 +81,7 @@ func FormatFloat(format string, n float64) string {
|
|||
}
|
||||
|
||||
func getHPathByID(id string) (ret string) {
|
||||
bt := GetBlockTree(id)
|
||||
bt := treenode.GetBlockTree(id)
|
||||
if nil == bt {
|
||||
return
|
||||
}
|
|
@ -9,8 +9,8 @@ require (
|
|||
github.com/88250/clipboard v0.1.5
|
||||
github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48
|
||||
github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7
|
||||
github.com/88250/gulu v1.2.3-0.20241127120230-1ae6a9868a2d
|
||||
github.com/88250/lute v1.7.7-0.20241208103455-3223b6b5f502
|
||||
github.com/88250/gulu v1.2.3-0.20241212012748-c4dc08fe45ec
|
||||
github.com/88250/lute v1.7.7-0.20241213121436-8647e479e280
|
||||
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
|
||||
github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4
|
||||
github.com/ConradIrwin/font v0.0.0-20240627033111-8567075b2bfe
|
||||
|
@ -30,7 +30,7 @@ require (
|
|||
github.com/flopp/go-findfont v0.1.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gabriel-vasile/mimetype v1.4.5
|
||||
github.com/getsentry/sentry-go v0.29.1
|
||||
github.com/getsentry/sentry-go v0.30.0
|
||||
github.com/gin-contrib/gzip v1.0.1
|
||||
github.com/gin-contrib/sessions v1.0.1
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
|
@ -57,12 +57,12 @@ require (
|
|||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
||||
github.com/sashabaranov/go-openai v1.29.1
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/siyuan-note/dejavu v0.0.0-20241206093814-2bd2e504b64f
|
||||
github.com/siyuan-note/dejavu v0.0.0-20241212013736-f1a4428c07cc
|
||||
github.com/siyuan-note/encryption v0.0.0-20231219001248-1e028a4d13b4
|
||||
github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97
|
||||
github.com/siyuan-note/filelock v0.0.0-20241202160444-1a99015900ff
|
||||
github.com/siyuan-note/httpclient v0.0.0-20241203001628-e7e7cab1f949
|
||||
github.com/siyuan-note/logging v0.0.0-20240505035402-6430d57006a2
|
||||
github.com/siyuan-note/filelock v0.0.0-20241212013445-c66518cdacfa
|
||||
github.com/siyuan-note/httpclient v0.0.0-20241212013326-2b23123573c3
|
||||
github.com/siyuan-note/logging v0.0.0-20241212013108-623e0bb0bcd9
|
||||
github.com/siyuan-note/riff v0.0.0-20241203002117-3b8d28360e46
|
||||
github.com/spf13/cast v1.7.0
|
||||
github.com/steambap/captcha v1.4.1
|
||||
|
@ -74,8 +74,8 @@ require (
|
|||
golang.org/x/image v0.21.0
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b
|
||||
golang.org/x/mod v0.22.0
|
||||
golang.org/x/net v0.31.0
|
||||
golang.org/x/text v0.20.0
|
||||
golang.org/x/net v0.32.0
|
||||
golang.org/x/text v0.21.0
|
||||
golang.org/x/time v0.6.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
@ -110,7 +110,7 @@ require (
|
|||
github.com/go-resty/resty/v2 v2.14.0 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/google/pprof v0.0.0-20241128161848-dc51965c6481 // indirect
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
|
@ -168,11 +168,11 @@ require (
|
|||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/arch v0.10.0 // indirect
|
||||
golang.org/x/crypto v0.29.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
|
||||
golang.org/x/sync v0.9.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/tools v0.27.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
|
|
@ -12,10 +12,10 @@ github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7 h1:MafIFwSS0x6A4
|
|||
github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7/go.mod h1:HrKCCTin3YNDSLBD02K0AOljjV6eNwc3/zyEI+xyV1I=
|
||||
github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950 h1:Pa5hMiBceTVVqrYaDlLio2QSKbXMUmAZPbzCwT5eNCw=
|
||||
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.20241127120230-1ae6a9868a2d h1:dexFyk3UkR4c2xpyrC4Zk4L28xFbfLYAeowIW/7QYEA=
|
||||
github.com/88250/gulu v1.2.3-0.20241127120230-1ae6a9868a2d/go.mod h1:MUfzyfmbPrRDZLqxc7aPrVYveatTHRfoUa5TynPS0i8=
|
||||
github.com/88250/lute v1.7.7-0.20241208103455-3223b6b5f502 h1:agB9kKKmVrmMa4iSpI7YAN4O3OyV3W+w09CTwgnY7Z8=
|
||||
github.com/88250/lute v1.7.7-0.20241208103455-3223b6b5f502/go.mod h1:VDAzL8b+oCh+e3NAlmwwLzC53ten0rZlS8NboB7ljtk=
|
||||
github.com/88250/gulu v1.2.3-0.20241212012748-c4dc08fe45ec h1:YsUSpByWJP+x8C+IT+C3QlFvU7ZQ6+E95SFd9+zy6QU=
|
||||
github.com/88250/gulu v1.2.3-0.20241212012748-c4dc08fe45ec/go.mod h1:c8uVw25vW2W4dhJ/j4iYsX5H1hc19spim266jO5x2hU=
|
||||
github.com/88250/lute v1.7.7-0.20241213121436-8647e479e280 h1:Ub4MpkyCTOvf3L1po5FUSJ1h52qlrThN8YQtbxbUu2s=
|
||||
github.com/88250/lute v1.7.7-0.20241213121436-8647e479e280/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o=
|
||||
github.com/88250/pdfcpu v0.3.14-0.20241201033812-5a93b7586a01 h1:AcFe63RXjIh1XtX/dc4Es3U8bYKjlEkvavHd1nFBOHM=
|
||||
github.com/88250/pdfcpu v0.3.14-0.20241201033812-5a93b7586a01/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI=
|
||||
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=
|
||||
|
@ -112,8 +112,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
|||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4=
|
||||
github.com/getsentry/sentry-go v0.29.1 h1:DyZuChN8Hz3ARxGVV8ePaNXh1dQ7d76AiB117xcREwA=
|
||||
github.com/getsentry/sentry-go v0.29.1/go.mod h1:x3AtIzN01d6SiWkderzaH28Tm0lgkafpJ5Bm3li39O0=
|
||||
github.com/getsentry/sentry-go v0.30.0 h1:lWUwDnY7sKHaVIoZ9wYqRHJ5iEmoc0pqcRqFkosKzBo=
|
||||
github.com/getsentry/sentry-go v0.30.0/go.mod h1:WU9B9/1/sHDqeV8T+3VwwbjeR5MSXs/6aqG3mqZrezA=
|
||||
github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573 h1:u8AQ9bPa9oC+8/A/jlWouakhIvkFfuxgIIRjiy8av7I=
|
||||
github.com/gigawattio/window v0.0.0-20180317192513-0f5467e35573/go.mod h1:eBvb3i++NHDH4Ugo9qCvMw8t0mTSctaEa5blJbWcNxs=
|
||||
github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE=
|
||||
|
@ -166,8 +166,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
|||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20241128161848-dc51965c6481 h1:yudKIrXagAOl99WQzrP1gbz5HLB9UjhcOFnPzdd6Qec=
|
||||
github.com/google/pprof v0.0.0-20241128161848-dc51965c6481/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||
|
@ -341,18 +341,18 @@ github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+D
|
|||
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d h1:lvCTyBbr36+tqMccdGMwuEU+hjux/zL6xSmf5S9ITaA=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20241206093814-2bd2e504b64f h1:4NOFYagREPvdf24wG8rMd8qMW0BVnbArIHq4Js6XeyA=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20241206093814-2bd2e504b64f/go.mod h1:Xu51gaOy8gup2N1q9xwdYdHDqKdCMLL7GiGEno3VnMQ=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20241212013736-f1a4428c07cc h1:QT2xfpSFChSdvw7uzY9S46pnKtsFkWKS0OOFfyjOtmA=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20241212013736-f1a4428c07cc/go.mod h1:ytDHT/FQKl1SuGEsnI2YQbhirlswQiiwc0rSW3nnnFo=
|
||||
github.com/siyuan-note/encryption v0.0.0-20231219001248-1e028a4d13b4 h1:kJaw5L/evyW6LcB9IQT8PR4ppx8JVqOFP9Ix3rfwSrc=
|
||||
github.com/siyuan-note/encryption v0.0.0-20231219001248-1e028a4d13b4/go.mod h1:UYcCCY+0wh+GmUoDOaO63j1sV5lgy7laLAk1XhEiUis=
|
||||
github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97 h1:lM5v8BfNtbOL5jYwhCdMYBcYtr06IYBKjjSLAPMKTM8=
|
||||
github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97/go.mod h1:1/nGgthl89FPA7GzAcEWKl6zRRnfgyTjzLZj9bW7kuw=
|
||||
github.com/siyuan-note/filelock v0.0.0-20241202160444-1a99015900ff h1:Ec6Q5dI/q2uSiFxSkbHajLQgqQQ3mFYXwZKiOSldmE4=
|
||||
github.com/siyuan-note/filelock v0.0.0-20241202160444-1a99015900ff/go.mod h1:QUxfb/zE/lMrpiGBV9MBT5c5NKQanGvpdBXtMwWjTD0=
|
||||
github.com/siyuan-note/httpclient v0.0.0-20241203001628-e7e7cab1f949 h1:6tiXciMclIbCkgpbShVEh3LhUnz3YgfxPykdoHWAdIs=
|
||||
github.com/siyuan-note/httpclient v0.0.0-20241203001628-e7e7cab1f949/go.mod h1:vQ9SXdb5eqqE0AxULHuW+pvHfWBILEUqV1Xx3zF4WM4=
|
||||
github.com/siyuan-note/logging v0.0.0-20240505035402-6430d57006a2 h1:/2+tlOThVB86RxSLeW0JFw2ISUrH2ZFRg15ULGAUGAE=
|
||||
github.com/siyuan-note/logging v0.0.0-20240505035402-6430d57006a2/go.mod h1:3Osd2/nwzXZFl6ZcDE4hA0HD83Wyv1fds47nVuapyOM=
|
||||
github.com/siyuan-note/filelock v0.0.0-20241212013445-c66518cdacfa h1:NM/0m8/hmFZGo0v+xNnjEeoqTtZShcVadWS0WYah+yI=
|
||||
github.com/siyuan-note/filelock v0.0.0-20241212013445-c66518cdacfa/go.mod h1:OmJuq0Dm+S8I713lmfmZNFwtQ/o4mdZHSfsEra39lfY=
|
||||
github.com/siyuan-note/httpclient v0.0.0-20241212013326-2b23123573c3 h1:9iSRzXsEmDgofy11kjtiWFC83wqHsGSHZ0meW0qiCJw=
|
||||
github.com/siyuan-note/httpclient v0.0.0-20241212013326-2b23123573c3/go.mod h1:PJNk4sdv+CQFjlAFJhv821asNZhJmBoa1Jbe4TAGQlg=
|
||||
github.com/siyuan-note/logging v0.0.0-20241212013108-623e0bb0bcd9 h1:DYF4JZFiVTy1hmFvrpyRxc+8qaymm/THwdyow/xWark=
|
||||
github.com/siyuan-note/logging v0.0.0-20241212013108-623e0bb0bcd9/go.mod h1:jZ4dO1KQBl3mqarQCwL8bnAyWz3SeZsySLT6HjSuZjY=
|
||||
github.com/siyuan-note/riff v0.0.0-20241203002117-3b8d28360e46 h1:HHplIFTgsRdPJo3uQuVgzqwiw2+Uyurkpee8NAO+k+Q=
|
||||
github.com/siyuan-note/riff v0.0.0-20241203002117-3b8d28360e46/go.mod h1:/mdhL34JKGnWtVuhenkIfeqqBeZTZg6ZOIklMXA7pvA=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
|
@ -425,10 +425,10 @@ golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq
|
|||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
|
||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
||||
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
|
||||
|
@ -456,16 +456,16 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
|||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -486,8 +486,8 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -515,8 +515,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
|||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
@ -525,8 +525,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
|||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o=
|
||||
golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q=
|
||||
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
|
|
|
@ -19,6 +19,7 @@ package model
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
@ -3112,7 +3113,11 @@ func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID string, valueDa
|
|||
for _, valOpt := range val.MSelect {
|
||||
if opt := key.GetOption(valOpt.Content); nil == opt {
|
||||
// 不存在的选项新建保存
|
||||
opt = &av.SelectOption{Name: valOpt.Content, Color: valOpt.Color}
|
||||
color := valOpt.Color
|
||||
if "" == color {
|
||||
color = fmt.Sprintf("%d", 1+rand.Intn(14))
|
||||
}
|
||||
opt = &av.SelectOption{Name: valOpt.Content, Color: color}
|
||||
key.Options = append(key.Options, opt)
|
||||
} else {
|
||||
// 已经存在的选项颜色需要保持不变
|
||||
|
|
|
@ -62,8 +62,7 @@ type Backlink struct {
|
|||
node *ast.Node // 仅用于按文档内容顺序排序
|
||||
}
|
||||
|
||||
func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren, highlight bool) (ret []*Backlink) {
|
||||
var keywords []string
|
||||
func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren, highlight bool) (ret []*Backlink, keywords []string) {
|
||||
keyword = strings.TrimSpace(keyword)
|
||||
if "" != keyword {
|
||||
keywords = strings.Split(keyword, " ")
|
||||
|
@ -98,6 +97,11 @@ func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren, highli
|
|||
mentionKeywords = append(mentionKeywords, strings.Split(keyword, " ")...)
|
||||
}
|
||||
mentionKeywords = gulu.Str.RemoveDuplicatedElem(mentionKeywords)
|
||||
keywords = append(keywords, mentionKeywords...)
|
||||
keywords = gulu.Str.RemoveDuplicatedElem(keywords)
|
||||
if 1 > len(keywords) {
|
||||
keywords = []string{}
|
||||
}
|
||||
|
||||
var refTree *parse.Tree
|
||||
trees := filesys.LoadTrees(mentionBlockIDs)
|
||||
|
@ -118,12 +122,15 @@ func GetBackmentionDoc(defID, refTreeID, keyword string, containChildren, highli
|
|||
return
|
||||
}
|
||||
|
||||
func GetBacklinkDoc(defID, refTreeID, keyword string, containChildren, highlight bool) (ret []*Backlink) {
|
||||
var keywords []string
|
||||
func GetBacklinkDoc(defID, refTreeID, keyword string, containChildren, highlight bool) (ret []*Backlink, keywords []string) {
|
||||
keyword = strings.TrimSpace(keyword)
|
||||
if "" != keyword {
|
||||
keywords = strings.Split(keyword, " ")
|
||||
}
|
||||
keywords = gulu.Str.RemoveDuplicatedElem(keywords)
|
||||
if 1 > len(keywords) {
|
||||
keywords = []string{}
|
||||
}
|
||||
|
||||
ret = []*Backlink{}
|
||||
sqlBlock := sql.GetBlock(defID)
|
||||
|
|
|
@ -547,6 +547,22 @@ func GetHeadingChildrenDOM(id string) (ret string) {
|
|||
nodes := append([]*ast.Node{}, heading)
|
||||
children := treenode.HeadingChildren(heading)
|
||||
nodes = append(nodes, children...)
|
||||
|
||||
// 取消折叠 https://github.com/siyuan-note/siyuan/issues/13232#issuecomment-2535955152
|
||||
for _, child := range children {
|
||||
ast.Walk(child, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
n.RemoveIALAttr("heading-fold")
|
||||
n.RemoveIALAttr("fold")
|
||||
return ast.WalkContinue
|
||||
})
|
||||
}
|
||||
heading.RemoveIALAttr("fold")
|
||||
heading.RemoveIALAttr("heading-fold")
|
||||
|
||||
luteEngine := util.NewLute()
|
||||
ret = renderBlockDOMByNodes(nodes, luteEngine)
|
||||
return
|
||||
|
|
|
@ -215,6 +215,22 @@ func setNodeAttrs0(node *ast.Node, nameValues map[string]string) (oldAttrs map[s
|
|||
}
|
||||
}
|
||||
|
||||
if tag, ok := nameValues["tags"]; ok {
|
||||
var tags []string
|
||||
tmp := strings.Split(tag, ",")
|
||||
for _, t := range tmp {
|
||||
t = util.RemoveInvalid(t)
|
||||
t = strings.TrimSpace(t)
|
||||
if "" != t {
|
||||
tags = append(tags, t)
|
||||
}
|
||||
}
|
||||
tags = gulu.Str.RemoveDuplicatedElem(tags)
|
||||
if 0 < len(tags) {
|
||||
nameValues["tags"] = strings.Join(tags, ",")
|
||||
}
|
||||
}
|
||||
|
||||
for name, value := range nameValues {
|
||||
value = util.RemoveInvalid(value)
|
||||
value = strings.TrimSpace(value)
|
||||
|
|
|
@ -344,6 +344,12 @@ func InitConf() {
|
|||
if 0 == Conf.Sync.Mode {
|
||||
Conf.Sync.Mode = 1
|
||||
}
|
||||
if 30 > Conf.Sync.Interval {
|
||||
Conf.Sync.Interval = 30
|
||||
}
|
||||
if 60*60*12 < Conf.Sync.Interval {
|
||||
Conf.Sync.Interval = 60 * 60 * 12
|
||||
}
|
||||
if nil == Conf.Sync.S3 {
|
||||
Conf.Sync.S3 = &conf.S3{PathStyle: true, SkipTlsVerify: true}
|
||||
}
|
||||
|
|
|
@ -532,7 +532,13 @@ func ExportResources(resourcePaths []string, mainName string) (exportFilePath st
|
|||
|
||||
// 将需要导出的文件/文件夹复制到临时文件夹
|
||||
for _, resourcePath := range resourcePaths {
|
||||
resourceFullPath := filepath.Join(util.WorkspaceDir, resourcePath) // 资源完整路径
|
||||
resourceFullPath := filepath.Join(util.WorkspaceDir, resourcePath) // 资源完整路径
|
||||
if !util.IsAbsPathInWorkspace(resourceFullPath) {
|
||||
logging.LogErrorf("resource path [%s] is not in workspace", resourceFullPath)
|
||||
err = errors.New("resource path [" + resourcePath + "] is not in workspace")
|
||||
return
|
||||
}
|
||||
|
||||
resourceBaseName := filepath.Base(resourceFullPath) // 资源名称
|
||||
resourceCopyPath := filepath.Join(exportFolderPath, resourceBaseName) // 资源副本完整路径
|
||||
if err = filelock.Copy(resourceFullPath, resourceCopyPath); err != nil {
|
||||
|
@ -571,7 +577,7 @@ func Preview(id string) (retStdHTML string) {
|
|||
blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
|
||||
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
|
||||
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
|
||||
Conf.Export.AddTitle)
|
||||
Conf.Export.AddTitle, true)
|
||||
luteEngine := NewLute()
|
||||
luteEngine.SetFootnotes(true)
|
||||
addBlockIALNodes(tree, false)
|
||||
|
@ -674,7 +680,7 @@ func ExportMarkdownHTML(id, savePath string, docx, merge bool) (name, dom string
|
|||
blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
|
||||
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
|
||||
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
|
||||
Conf.Export.AddTitle)
|
||||
Conf.Export.AddTitle, true)
|
||||
name = path.Base(tree.HPath)
|
||||
name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614
|
||||
savePath = strings.TrimSpace(savePath)
|
||||
|
@ -833,7 +839,7 @@ func ExportHTML(id, savePath string, pdf, image, keepFold, merge bool) (name, do
|
|||
blockRefMode, Conf.Export.BlockEmbedMode, Conf.Export.FileAnnotationRefMode,
|
||||
Conf.Export.TagOpenMarker, Conf.Export.TagCloseMarker,
|
||||
Conf.Export.BlockRefTextLeft, Conf.Export.BlockRefTextRight,
|
||||
Conf.Export.AddTitle)
|
||||
Conf.Export.AddTitle, true)
|
||||
name = path.Base(tree.HPath)
|
||||
name = util.FilterFileName(name) // 导出 PDF、HTML 和 Word 时未移除不支持的文件名符号 https://github.com/siyuan-note/siyuan/issues/5614
|
||||
|
||||
|
@ -1967,7 +1973,7 @@ func exportMarkdownContent0(tree *parse.Tree, cloudAssetsBase string, assetsDest
|
|||
blockRefMode, blockEmbedMode, fileAnnotationRefMode,
|
||||
tagOpenMarker, tagCloseMarker,
|
||||
blockRefTextLeft, blockRefTextRight,
|
||||
addTitle)
|
||||
addTitle, 0 < len(defBlockIDs))
|
||||
luteEngine := NewLute()
|
||||
luteEngine.SetFootnotes(true)
|
||||
luteEngine.SetKramdownIAL(false)
|
||||
|
@ -2078,7 +2084,7 @@ func exportTree(tree *parse.Tree, wysiwyg, keepFold, avHiddenCol bool,
|
|||
blockRefMode, blockEmbedMode, fileAnnotationRefMode int,
|
||||
tagOpenMarker, tagCloseMarker string,
|
||||
blockRefTextLeft, blockRefTextRight string,
|
||||
addTitle bool) (ret *parse.Tree) {
|
||||
addTitle, addDocAnchorSpan bool) (ret *parse.Tree) {
|
||||
luteEngine := NewLute()
|
||||
ret = tree
|
||||
id := tree.Root.ID
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
|
@ -442,163 +441,6 @@ func ListDocTree(boxID, listPath string, sortMode int, flashcard, showHidden boo
|
|||
return
|
||||
}
|
||||
|
||||
func ContentStat(content string) (ret *util.BlockStatResult) {
|
||||
luteEngine := util.NewLute()
|
||||
return contentStat(content, luteEngine)
|
||||
}
|
||||
|
||||
func contentStat(content string, luteEngine *lute.Lute) (ret *util.BlockStatResult) {
|
||||
tree := luteEngine.BlockDOM2Tree(content)
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat()
|
||||
return &util.BlockStatResult{
|
||||
RuneCount: runeCnt,
|
||||
WordCount: wordCnt,
|
||||
LinkCount: linkCnt,
|
||||
ImageCount: imgCnt,
|
||||
RefCount: refCnt,
|
||||
}
|
||||
}
|
||||
|
||||
func BlocksWordCount(ids []string) (ret *util.BlockStatResult) {
|
||||
ret = &util.BlockStatResult{}
|
||||
trees := filesys.LoadTrees(ids)
|
||||
for _, id := range ids {
|
||||
tree := trees[id]
|
||||
if nil == tree {
|
||||
continue
|
||||
}
|
||||
|
||||
node := treenode.GetNodeInTree(tree, id)
|
||||
if nil == node {
|
||||
continue
|
||||
}
|
||||
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := node.Stat()
|
||||
ret.RuneCount += runeCnt
|
||||
ret.WordCount += wordCnt
|
||||
ret.LinkCount += linkCnt
|
||||
ret.ImageCount += imgCnt
|
||||
ret.RefCount += refCnt
|
||||
}
|
||||
ret.BlockCount = len(ids)
|
||||
return
|
||||
}
|
||||
|
||||
func StatTree(id string) (ret *util.BlockStatResult) {
|
||||
FlushTxQueue()
|
||||
|
||||
tree, _ := LoadTreeByBlockID(id)
|
||||
if nil == tree {
|
||||
return
|
||||
}
|
||||
|
||||
blockCount := 0
|
||||
var databaseBlockNodes []*ast.Node
|
||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
if n.IsBlock() {
|
||||
blockCount++
|
||||
}
|
||||
|
||||
if ast.NodeAttributeView != n.Type {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
databaseBlockNodes = append(databaseBlockNodes, n)
|
||||
return ast.WalkContinue
|
||||
})
|
||||
|
||||
luteEngine := util.NewLute()
|
||||
var dbRuneCnt, dbWordCnt, dbLinkCnt, dbImgCnt, dbRefCnt int
|
||||
for _, n := range databaseBlockNodes {
|
||||
if "" == n.AttributeViewID {
|
||||
continue
|
||||
}
|
||||
|
||||
attrView, _ := av.ParseAttributeView(n.AttributeViewID)
|
||||
if nil == attrView {
|
||||
continue
|
||||
}
|
||||
|
||||
content := bytes.Buffer{}
|
||||
for _, kValues := range attrView.KeyValues {
|
||||
for _, v := range kValues.Values {
|
||||
switch kValues.Key.Type {
|
||||
case av.KeyTypeURL:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
dbLinkCnt++
|
||||
content.WriteString(v.URL.Content)
|
||||
case av.KeyTypeMAsset:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, asset := range v.MAsset {
|
||||
if av.AssetTypeImage == asset.Type {
|
||||
dbImgCnt++
|
||||
}
|
||||
}
|
||||
case av.KeyTypeBlock:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !v.IsDetached {
|
||||
dbRefCnt++
|
||||
}
|
||||
content.WriteString(v.Block.Content)
|
||||
case av.KeyTypeText:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
content.WriteString(v.Text.Content)
|
||||
case av.KeyTypeNumber:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
v.Number.FormatNumber()
|
||||
content.WriteString(v.Number.FormattedContent)
|
||||
case av.KeyTypeEmail:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
content.WriteString(v.Email.Content)
|
||||
case av.KeyTypePhone:
|
||||
if v.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
content.WriteString(v.Phone.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dbStat := contentStat(content.String(), luteEngine)
|
||||
dbRuneCnt += dbStat.RuneCount
|
||||
dbWordCnt += dbStat.WordCount
|
||||
}
|
||||
|
||||
runeCnt, wordCnt, linkCnt, imgCnt, refCnt := tree.Root.Stat()
|
||||
runeCnt += dbRuneCnt
|
||||
wordCnt += dbWordCnt
|
||||
linkCnt += dbLinkCnt
|
||||
imgCnt += dbImgCnt
|
||||
refCnt += dbRefCnt
|
||||
return &util.BlockStatResult{
|
||||
RuneCount: runeCnt,
|
||||
WordCount: wordCnt,
|
||||
LinkCount: linkCnt,
|
||||
ImageCount: imgCnt,
|
||||
RefCount: refCnt,
|
||||
BlockCount: blockCount,
|
||||
}
|
||||
}
|
||||
|
||||
func GetDoc(startID, endID, id string, index int, query string, queryTypes map[string]bool, queryMethod, mode int, size int, isBacklink, highlight bool) (
|
||||
blockCount int, dom, parentID, parent2ID, rootID, typ string, eof, scroll bool, boxID, docPath string, isBacklinkExpand bool, keywords []string, err error) {
|
||||
//os.MkdirAll("pprof", 0755)
|
||||
|
@ -795,13 +637,13 @@ func GetDoc(startID, endID, id string, index int, query string, queryTypes map[s
|
|||
|
||||
query = filterQueryInvisibleChars(query)
|
||||
if "" != query && (0 == queryMethod || 1 == queryMethod || 3 == queryMethod) { // 只有关键字、查询语法和正则表达式搜索支持高亮
|
||||
if 0 == queryMethod {
|
||||
query = stringQuery(query)
|
||||
}
|
||||
typeFilter := buildTypeFilter(queryTypes)
|
||||
if 0 == queryMethod || 1 == queryMethod {
|
||||
switch queryMethod {
|
||||
case 0:
|
||||
keywords = strings.Split(query, " ")
|
||||
case 1:
|
||||
keywords = highlightByFTS(query, typeFilter, rootID)
|
||||
} else {
|
||||
case 3:
|
||||
keywords = highlightByRegexp(query, typeFilter, rootID)
|
||||
}
|
||||
}
|
||||
|
@ -1077,21 +919,16 @@ func writeTreeUpsertQueue(tree *parse.Tree) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func writeTreeIndexQueue(tree *parse.Tree) (err error) {
|
||||
size, err := filesys.WriteTree(tree)
|
||||
func indexWriteTreeIndexQueue(tree *parse.Tree) (err error) {
|
||||
treenode.IndexBlockTree(tree)
|
||||
_, err = filesys.WriteTree(tree)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sql.IndexTreeQueue(tree)
|
||||
refreshDocInfo(tree, size)
|
||||
return
|
||||
}
|
||||
|
||||
func indexWriteTreeIndexQueue(tree *parse.Tree) (err error) {
|
||||
treenode.IndexBlockTree(tree)
|
||||
return writeTreeIndexQueue(tree)
|
||||
}
|
||||
|
||||
func indexWriteTreeUpsertQueue(tree *parse.Tree) (err error) {
|
||||
treenode.UpsertBlockTree(tree)
|
||||
return writeTreeUpsertQueue(tree)
|
||||
|
@ -2226,3 +2063,36 @@ func (box *Box) addSort(previousPath, id string) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (box *Box) setSort(sortIDVals map[string]int) {
|
||||
confPath := filepath.Join(util.DataDir, box.ID, ".siyuan", "sort.json")
|
||||
if !filelock.IsExist(confPath) {
|
||||
return
|
||||
}
|
||||
|
||||
data, err := filelock.ReadFile(confPath)
|
||||
if err != nil {
|
||||
logging.LogErrorf("read sort conf failed: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
fullSortIDs := map[string]int{}
|
||||
if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); err != nil {
|
||||
logging.LogErrorf("unmarshal sort conf failed: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
for sortID := range sortIDVals {
|
||||
fullSortIDs[sortID] = sortIDVals[sortID]
|
||||
}
|
||||
|
||||
data, err = gulu.JSON.MarshalJSON(fullSortIDs)
|
||||
if err != nil {
|
||||
logging.LogErrorf("marshal sort conf failed: %s", err)
|
||||
return
|
||||
}
|
||||
if err = filelock.WriteFile(confPath, data); err != nil {
|
||||
logging.LogErrorf("write sort conf failed: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue