Merge branch 'dev' into markmap

This commit is contained in:
Achuan-2 2025-11-25 09:41:27 +08:00 committed by GitHub
commit 95f2c7eec0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
113 changed files with 895 additions and 518 deletions

View file

@ -21,7 +21,7 @@ mkdir /artifacts
mv appearance stage guide changelogs /artifacts/
EORUN
FROM golang:1.24-alpine AS go-build
FROM golang:1.25-alpine AS go-build
RUN <<EORUN
#!/bin/sh -e

View file

@ -918,6 +918,7 @@
"moveToRight": "تحريك لليمين",
"copyProtocol": "نسخ الرابط التشعبي للكتلة",
"copyProtocolInMd": "‫نسخ رابط Markdown للكتلة‬",
"copyWebURL": "نسخ رابط الويب",
"uploadAssets2CDN": "رفع ملفات الأصول إلى السحابة",
"uploadAssets2CDNConfirmTip": "هل أنت متأكد من رفع الأصول في هذا المستند إلى السحابة؟",
"notSupport1": "لا يمكن السحب والإسقاط عبر الدفاتر",

View file

@ -918,6 +918,7 @@
"moveToRight": "Nach rechts bewegen",
"copyProtocol": "Blockhyperlink kopieren",
"copyProtocolInMd": "Block-Markdown-Link kopieren",
"copyWebURL": "Web-URL kopieren",
"uploadAssets2CDN": "Asset-Dateien in die Cloud hochladen",
"uploadAssets2CDNConfirmTip": "Sind Sie sicher, dass Sie die Assets in diesem Dokument in die Cloud hochladen möchten?",
"notSupport1": "Unterstützt kein Drag & Drop über Notizen hinweg.",

View file

@ -918,6 +918,7 @@
"moveToRight": "Move Right",
"copyProtocol": "Copy block hyperlink",
"copyProtocolInMd": "Copy block Markdown link",
"copyWebURL": "Copy web URL",
"uploadAssets2CDN": "Upload asset files to cloud",
"uploadAssets2CDNConfirmTip": "Are you sure to upload the assets in this document to the cloud?",
"notSupport1": "Does not support drag and drop across notebooks",

View file

@ -918,6 +918,7 @@
"moveToRight": "Mover a la derecha",
"copyProtocol": "Copiar hipervínculo de bloque",
"copyProtocolInMd": "Copiar enlace de bloque de Markdown",
"copyWebURL": "Copiar URL web",
"uploadAssets2CDN": "Subir archivos de activos a la nube",
"uploadAssets2CDNConfirmTip": "¿Está seguro de cargar los recursos de este documento en la nube?",
"notSupport1": "No admite la función de arrastrar y soltar en los cuadernos",

View file

@ -918,6 +918,7 @@
"moveToRight": "vers la Droite",
"copyProtocol": "Copier bloc d'hyperliens",
"copyProtocolInMd": "Copier le lien Markdown du bloc",
"copyWebURL": "Copier l'URL web",
"uploadAssets2CDN": "Transférer les fichiers asset vers le Cloud",
"uploadAssets2CDNConfirmTip": "Êtes-vous sûr de télécharger les ressources de ce document dans le cloud ?",
"notSupport1": "Le glisser-déposer entre carnets n'est pas pris en charge",

View file

@ -918,6 +918,7 @@
"moveToRight": "העבר ימינה",
"copyProtocol": "העתק היפר-קישור בלוק",
"copyProtocolInMd": "העתק קישור Markdown של בלוק",
"copyWebURL": "העתק URL אינטרנט",
"uploadAssets2CDN": "העלה קבצי נכסים לענן",
"uploadAssets2CDNConfirmTip": "האם אתה בטוח להעלות את הנכסים במסמך זה לענן?",
"notSupport1": "לא תומך בגרירת מסמכים בין מחברות",

View file

@ -918,6 +918,7 @@
"moveToRight": "Sposta a Destra",
"copyProtocol": "Copia il collegamento del blocco",
"copyProtocolInMd": "Copia collegamento Markdown del blocco",
"copyWebURL": "Copia URL web",
"uploadAssets2CDN": "Carica file di asset su cloud",
"uploadAssets2CDNConfirmTip": "Sei sicuro di voler caricare gli asset di questo documento sul cloud?",
"notSupport1": "Non supporta il trascinamento tra taccuini",

View file

@ -918,6 +918,7 @@
"moveToRight": "右に移動",
"copyProtocol": "ハイパーリンクとしてコピー",
"copyProtocolInMd": "Markdown リンクとしてコピー",
"copyWebURL": "ウェブURLをコピー",
"uploadAssets2CDN": "アセットファイルをクラウドにアップロード",
"uploadAssets2CDNConfirmTip": "このドキュメントのアセットをクラウドにアップロードしてもよろしいですか?",
"notSupport1": "ノートブック間でのドラッグ&ドロップはサポートされていません",

View file

@ -918,6 +918,7 @@
"moveToRight": "Przenieś w prawo",
"copyProtocol": "Kopiuj hiperlink bloku",
"copyProtocolInMd": "Kopiuj link Markdown bloku",
"copyWebURL": "Kopiuj URL internetowy",
"uploadAssets2CDN": "Prześlij pliki zasobów do chmury",
"uploadAssets2CDNConfirmTip": "Czy na pewno chcesz przesłać zasoby w tym dokumencie do chmury?",
"notSupport1": "Nie wspiera przeciągania i upuszczania między notesami",

View file

@ -918,6 +918,7 @@
"moveToRight": "Mover para Direita",
"copyProtocol": "Copiar hiperlink do bloco",
"copyProtocolInMd": "Copiar link Markdown do bloco",
"copyWebURL": "Copiar URL da web",
"uploadAssets2CDN": "Enviar arquivos de ativos para a nuvem",
"uploadAssets2CDNConfirmTip": "Tem certeza que deseja enviar os ativos neste documento para a nuvem?",
"notSupport1": "Não suporta arrastar e soltar entre blocos de notas",

View file

@ -918,6 +918,7 @@
"moveToRight": "Переместить направо",
"copyProtocol": "Скопировать гиперссылку блока",
"copyProtocolInMd": "Скопировать ссылку блока в Markdown",
"copyWebURL": "Скопировать веб-ссылку",
"uploadAssets2CDN": "Загрузить файлы ресурсов в облако",
"uploadAssets2CDNConfirmTip": "Вы уверены, что хотите загрузить ресурсы в этом документе в облако?",
"notSupport1": "Не поддерживает перетаскивание между блокнотами",

View file

@ -918,6 +918,7 @@
"moveToRight": "向右移",
"copyProtocol": "複製塊超連結",
"copyProtocolInMd": "複製塊 Markdown 連結",
"copyWebURL": "複製網頁連結",
"uploadAssets2CDN": "上傳資料檔到圖床",
"uploadAssets2CDNConfirmTip": "確定將該文檔內的資源文件上傳到圖床嗎?",
"notSupport1": "不支援跨筆記本進行拖拽",

View file

@ -918,6 +918,7 @@
"moveToRight": "向右移",
"copyProtocol": "复制块超链接",
"copyProtocolInMd": "复制块 Markdown 链接",
"copyWebURL": "复制网页链接",
"uploadAssets2CDN": "上传资源文件到图床",
"uploadAssets2CDNConfirmTip": "确定将该文档内的资源文件上传到图床吗?",
"notSupport1": "不支持跨笔记本进行拖拽",

View file

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

View file

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

View file

@ -0,0 +1,40 @@
## Overview
This version improves some details.
## Changelogs
Below are the detailed changes in this version.
### Enhancement
* [The database-bound block no longer automatically adds to the database after being copied as a replica](https://github.com/siyuan-note/siyuan/issues/12294)
* [Improve iframe/widget rendering](https://github.com/siyuan-note/siyuan/issues/16239)
* [Support calling system printing on iOS](https://github.com/siyuan-note/siyuan/issues/16247)
* [Supports executing JS snippets in the export interface.](https://github.com/siyuan-note/siyuan/issues/16300)
* [The shortcut search does not include key conditions](https://github.com/siyuan-note/siyuan/issues/16356)
* [Improve exit on Android](https://github.com/siyuan-note/siyuan/issues/16377)
* [Center and highlight the block when opening search results.](https://github.com/siyuan-note/siyuan/issues/16379)
* [Improve database operation interaction](https://github.com/siyuan-note/siyuan/issues/16381)
* [Improve printing on mobile](https://github.com/siyuan-note/siyuan/issues/16385)
* [Improve interface loading after switching themes and updating code snippets](https://github.com/siyuan-note/siyuan/issues/16390)
* [Improve data indexing performance](https://github.com/siyuan-note/siyuan/issues/16397)
* [Improve outline positioning](https://github.com/siyuan-note/siyuan/issues/16402)
* [Improve HTML svg clipping](https://github.com/siyuan-note/siyuan/issues/16413)
* [Add "Copy web URL" command to the Copy context menu on browser](https://github.com/siyuan-note/siyuan/pull/16415)
* [Improve left and right arrow keys in ZWSP at the beginning of block](https://github.com/siyuan-note/siyuan/issues/16416)
* [Image OCR supports more formats](https://github.com/siyuan-note/siyuan/issues/16418)
* [Image OCR supports setting the timeout via the environment variable `SIYUAN_TESSERACT_TIMEOUT`](https://github.com/siyuan-note/siyuan/issues/16419)
### Bugfix
* [Using S3 data synchronization may cause kernel boot crashes](https://github.com/siyuan-note/siyuan/issues/16388)
### Development
* [Add `filetreeSortChanged` and `notebookSortChanged` to eventbus](https://github.com/siyuan-note/siyuan/issues/16383)
## Download
* [B3log](https://b3log.org/siyuan/en/download.html)
* [GitHub](https://github.com/siyuan-note/siyuan/releases)

View file

@ -0,0 +1,40 @@
## 概述
此版本改進了一些細節。
## 變更記錄
以下是此版本中的詳細變更。
### 改進功能
* [資料庫綁定的區塊在複製為副本後不再自動加入資料庫](https://github.com/siyuan-note/siyuan/issues/12294)
* [改良 iframe/掛飾 的渲染](https://github.com/siyuan-note/siyuan/issues/16239)
* [支援在 iOS 上呼叫系統列印](https://github.com/siyuan-note/siyuan/issues/16247)
* [支援在匯出介面執行 JS 程式碼片段](https://github.com/siyuan-note/siyuan/issues/16300)
* [快速搜尋不包含鍵位條件](https://github.com/siyuan-note/siyuan/issues/16356)
* [改進 Android 上的退出](https://github.com/siyuan-note/siyuan/issues/16377)
* [開啟搜尋結果時將區塊置中並加亮](https://github.com/siyuan-note/siyuan/issues/16379)
* [改進資料庫操作互動](https://github.com/siyuan-note/siyuan/issues/16381)
* [改進行動版列印](https://github.com/siyuan-note/siyuan/issues/16385)
* [切換主題和更新程式碼片段後改進介面載入](https://github.com/siyuan-note/siyuan/issues/16390)
* [改進資料索引效能](https://github.com/siyuan-note/siyuan/issues/16397)
* [改進大綱定位](https://github.com/siyuan-note/siyuan/issues/16402)
* [改進 HTML SVG 剪藏](https://github.com/siyuan-note/siyuan/issues/16413)
* [在瀏覽器的複製上下文選單中新增「複製網頁 URL」](https://github.com/siyuan-note/siyuan/pull/16415)
* [在區塊開頭的零寬空格ZWSP處改進左右箭頭鍵的行為](https://github.com/siyuan-note/siyuan/issues/16416)
* [圖片 OCR 支援更多格式](https://github.com/siyuan-note/siyuan/issues/16418)
* [圖片 OCR 支援透過環境變數 `SIYUAN_TESSERACT_TIMEOUT` 設定逾時](https://github.com/siyuan-note/siyuan/issues/16419)
### 修復缺陷
* [使用 S3 資料同步可能導致內核啟動時崩潰](https://github.com/siyuan-note/siyuan/issues/16388)
### 開發者
* [向 eventbus 新增 `filetreeSortChanged` 和 `notebookSortChanged`](https://github.com/siyuan-note/siyuan/issues/16383)
## 下載
* [B3log](https://b3log.org/siyuan/download.html)
* [GitHub](https://github.com/siyuan-note/siyuan/releases)

View file

@ -0,0 +1,40 @@
## 概述
此版本改进了一些细节。
## 变更记录
以下是此版本中的详细变更。
### 改进功能
* [数据库绑定的块在被复制为副本后不再自动添加到数据库](https://github.com/siyuan-note/siyuan/issues/12294)
* [改进 iframe/挂件 的渲染](https://github.com/siyuan-note/siyuan/issues/16239)
* [支持在 iOS 上调用系统打印](https://github.com/siyuan-note/siyuan/issues/16247)
* [支持在导出界面执行 JS 代码片段](https://github.com/siyuan-note/siyuan/issues/16300)
* [快捷搜索不包含键位条件](https://github.com/siyuan-note/siyuan/issues/16356)
* [改进 Android 上的退出](https://github.com/siyuan-note/siyuan/issues/16377)
* [打开搜索结果时将块居中并高亮](https://github.com/siyuan-note/siyuan/issues/16379)
* [改进数据库操作交互](https://github.com/siyuan-note/siyuan/issues/16381)
* [改进移动端打印](https://github.com/siyuan-note/siyuan/issues/16385)
* [切换主题和更新代码片段后改进界面加载](https://github.com/siyuan-note/siyuan/issues/16390)
* [改进数据索引性能](https://github.com/siyuan-note/siyuan/issues/16397)
* [改进大纲定位](https://github.com/siyuan-note/siyuan/issues/16402)
* [改进 HTML SVG 剪藏](https://github.com/siyuan-note/siyuan/issues/16413)
* [在浏览器的复制上下文菜单中添加“复制网页 URL”](https://github.com/siyuan-note/siyuan/pull/16415)
* [在块开头的零宽空格ZWSP处改进左右箭头键的行为](https://github.com/siyuan-note/siyuan/issues/16416)
* [图片 OCR 支持更多格式](https://github.com/siyuan-note/siyuan/issues/16418)
* [图片 OCR 支持通过环境变量 `SIYUAN_TESSERACT_TIMEOUT` 设置超时](https://github.com/siyuan-note/siyuan/issues/16419)
### 修复缺陷
* [使用 S3 数据同步可能导致内核启动时崩溃](https://github.com/siyuan-note/siyuan/issues/16388)
### 开发者
* [向 eventbus 添加 `filetreeSortChanged` 和 `notebookSortChanged`](https://github.com/siyuan-note/siyuan/issues/16383)
## 下载
* [B3log](https://b3log.org/siyuan/download.html)
* [GitHub](https://github.com/siyuan-note/siyuan/releases)

View file

@ -1051,25 +1051,6 @@ app.whenReady().then(() => {
ipcMain.on("siyuan-quit", (event, port) => {
exitApp(port);
});
ipcMain.on("siyuan-reload-window", (event, port) => {
BrowserWindow.getAllWindows().forEach((item) => {
try {
const currentURL = new URL(item.getURL());
if (port.toString() === currentURL.port.toString()) {
const hasMain = workspaces.find((workspaceItem) => {
if (workspaceItem.browserWindow.id === item.id) {
return true;
}
});
if (!hasMain) {
item.reload();
}
}
} catch (e) {
// load file is not a url
}
});
});
ipcMain.on("siyuan-show-window", (event) => {
const mainWindow = getWindowByContentId(event.sender.id);
if (!mainWindow) {

View file

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

View file

@ -276,7 +276,6 @@
display: flex;
flex-direction: column;
position: relative;
min-height: 40px;
&::before {
transition: background 100ms ease-out;
@ -379,7 +378,7 @@
flex: 1;
white-space: nowrap;
font-size: 85%;
min-height: 23px;
min-height: calc(1.625em + 4px);
padding: 5px 4px;
&:hover {
@ -484,6 +483,8 @@
cursor: pointer;
transition: background 100ms ease-out, color 100ms ease-out;
position: relative;
font-size: 85%;
padding: 4px 0;
&:hover {
background-color: var(--b3-theme-surface-light);
@ -941,7 +942,7 @@
.b3-chip {
padding: 0 6px;
line-height: 1.625;
font-size: 87.5%;
font-size: 1em;
float: left;
margin-right: 8px;

View file

@ -34,15 +34,6 @@
border: 0;
}
iframe {
border: 1px solid var(--b3-theme-surface-lighter);
width: 765px;
box-sizing: border-box;
height: 256px;
max-width: 100%;
vertical-align: bottom;
}
span[data-type~="sup"],
span[data-type~="sub"] {
position: relative;
@ -415,6 +406,29 @@
text-align: center;
}
[data-type="NodeIFrame"],
[data-type="NodeWidget"] {
height: 256px;
width: 100%;
max-width: 100%;
.iframe-content {
position: relative;
height: 100%;
width: 100%;
}
iframe {
width: 100%;
height: 100%;
border: 1px solid var(--b3-theme-surface-lighter);
box-sizing: border-box;
max-width: 100%;
min-height: 100%;
max-height: 100%;
}
}
[data-subtype="flowchart"] > [spin="1"],
[data-subtype="plantuml"] > [spin="1"],
[data-subtype="mermaid"] > [spin="1"] {

View file

@ -508,14 +508,11 @@
&.iframe {
// https://ld246.com/article/1644827326901
// https://github.com/siyuan-note/siyuan/issues/4172
&[data-type="NodeWidget"] .iframe-content,
&[data-type="NodeIFrame"] .iframe-content {
-webkit-user-modify: read-only;
}
.iframe-content {
display: inline-block;
position: relative;
&[data-type="NodeWidget"],
&[data-type="NodeIFrame"] {
.iframe-content {
-webkit-user-modify: read-only;
}
}
&--drag {

View file

@ -99,13 +99,15 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
if (searchType !== "asset") {
if (matchHotKey(window.siyuan.config.keymap.editor.general.insertRight.custom, event)) {
const id = currentList.getAttribute("data-node-id");
checkFold(id, (zoomIn, action) => {
checkFold(id, (zoomIn) => {
openFileById({
app,
id,
position: "right",
action,
zoomIn
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] :
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL],
zoomIn,
scrollPosition: "center"
});
if (dialog) {
dialog.destroy({focus: "false"});
@ -221,12 +223,14 @@ export const searchKeydown = (app: App, event: KeyboardEvent) => {
replace(element, config, edit, false);
} else {
const id = currentList.getAttribute("data-node-id");
checkFold(id, (zoomIn, action) => {
checkFold(id, (zoomIn) => {
openFileById({
app,
id,
action,
zoomIn
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] :
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL],
zoomIn,
scrollPosition: "center"
});
if (dialog) {
dialog.destroy({focus: "false"});

View file

@ -12,7 +12,6 @@ import {resetFloatDockSize} from "../layout/dock/util";
import {confirmDialog} from "../dialog/confirmDialog";
import {useShell} from "../util/pathName";
import {Dialog} from "../dialog";
import {reloadOtherWindow} from "../dialog/processSystem";
export const appearance = {
element: undefined as Element,
@ -207,46 +206,7 @@ export const appearance = {
msgTaskAssetDatabaseIndexCommitDisabled: statusBar ? statusBar.msgTaskAssetDatabaseIndexCommitDisabled : window.siyuan.config.appearance.statusBar.msgTaskAssetDatabaseIndexCommitDisabled,
msgTaskHistoryGenerateFileDisabled: statusBar ? statusBar.msgTaskHistoryGenerateFileDisabled : window.siyuan.config.appearance.statusBar.msgTaskHistoryGenerateFileDisabled,
}
}, async response => {
if (response.data.mode !== window.siyuan.config.appearance.mode ||
(response.data.mode === window.siyuan.config.appearance.mode && (
(response.data.mode === 0 && window.siyuan.config.appearance.themeLight !== response.data.themeLight) ||
(response.data.mode === 1 && window.siyuan.config.appearance.themeDark !== response.data.themeDark))
) || response.data.lang !== window.siyuan.config.appearance.lang) {
reloadOtherWindow();
}
if (window.siyuan.config.appearance.themeJS) {
if (response.data.mode !== window.siyuan.config.appearance.mode ||
(response.data.mode === window.siyuan.config.appearance.mode && (
(response.data.mode === 0 && window.siyuan.config.appearance.themeLight !== response.data.themeLight) ||
(response.data.mode === 1 && window.siyuan.config.appearance.themeDark !== response.data.themeDark))
)
) {
if (window.destroyTheme) {
try {
await window.destroyTheme();
window.destroyTheme = undefined;
document.getElementById("themeScript").remove();
} catch (e) {
console.error("destroyTheme error: " + e);
}
} else {
exportLayout({
errorExit: false,
cb() {
window.location.reload();
},
});
return;
}
}
}
appearance.onSetAppearance(response.data);
if (response.data.hideStatusBar) {
document.getElementById("status").classList.add("fn__none");
} else {
document.getElementById("status").classList.remove("fn__none");
}
}, () => {
resetFloatDockSize();
});
},

View file

@ -1,9 +1,8 @@
import {appearance} from "./appearance";
import {showMessage} from "../dialog/message";
import {fetchPost} from "../util/fetch";
import {confirmDialog} from "../dialog/confirmDialog";
import {highlightRender} from "../protyle/render/highlightRender";
import {exportLayout, saveLayout} from "../layout/util";
import {saveLayout} from "../layout/util";
import {Constants} from "../constants";
/// #if !BROWSER
import * as path from "path";
@ -16,10 +15,7 @@ import {App} from "../index";
import {escapeAttr} from "../util/escape";
import {uninstall} from "../plugin/uninstall";
import {afterLoadPlugin, loadPlugin, loadPlugins, reloadPlugin} from "../plugin/loader";
import {loadAssets} from "../util/assets";
import {addScript} from "../protyle/util/addScript";
import {useShell} from "../util/pathName";
import {reloadOtherWindow} from "../dialog/processSystem";
export const bazaar = {
element: undefined as Element,
@ -674,28 +670,7 @@ export const bazaar = {
mode: dataObj.themeMode === "dark" ? 1 : 0,
frontend: getFrontend()
}, async response => {
if (window.siyuan.config.appearance.themeJS && bazaarType === "themes") {
if (window.destroyTheme) {
try {
await window.destroyTheme();
window.destroyTheme = undefined;
document.getElementById("themeScript").remove();
} catch (e) {
console.error("destroyTheme error: " + e);
}
window.siyuan.config.appearance = response.data.appearance;
loadAssets(window.siyuan.config.appearance);
} else {
exportLayout({
cb() {
window.location.reload();
},
errorExit: false,
});
return;
}
}
bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType));
bazaar._onBazaar(response, bazaarType);
bazaar._genMyHTML(bazaarType, app, false);
if (bazaarType === "plugins") {
if (window.siyuan.config.bazaar.petalDisabled) {
@ -757,45 +732,14 @@ export const bazaar = {
frontend: getFrontend()
}, async response => {
this._genMyHTML(bazaarType, app);
bazaar._onBazaar(response, bazaarType, ["icons"].includes(bazaarType));
bazaar._onBazaar(response, bazaarType);
// https://github.com/siyuan-note/siyuan/issues/15177
if (bazaarType === "themes" && response.data.appearance?.themeVer) {
window.siyuan.config.appearance.themeVer = response.data.appearance.themeVer;
}
// 更新主题后不需要对该主题进行切换 https://github.com/siyuan-note/siyuan/issues/4966
// https://github.com/siyuan-note/siyuan/issues/5411
if (bazaarType === "themes" && (
(window.siyuan.config.appearance.mode === 0 && window.siyuan.config.appearance.themeLight === dataObj.name) ||
(window.siyuan.config.appearance.mode === 1 && window.siyuan.config.appearance.themeDark === dataObj.name)
)) {
const currentTheme = window.siyuan.config.appearance.mode === 1 ? window.siyuan.config.appearance.themeDark : window.siyuan.config.appearance.themeLight;
if (window.siyuan.config.appearance.themeJS) {
if (window.destroyTheme) {
try {
await window.destroyTheme();
window.destroyTheme = undefined;
document.getElementById("themeScript").remove();
addScript(`/appearance/themes/${currentTheme}/theme.js?v=${response.data.appearance.themeVer}`, "themeScript");
} catch (e) {
console.error("destroyTheme error: " + e);
}
} else {
exportLayout({
cb() {
window.location.reload();
},
errorExit: false,
});
return;
}
}
if ((window.siyuan.config.appearance.mode === 1 && currentTheme === "midnight") ||
(window.siyuan.config.appearance.mode !== 1 && currentTheme === "daylight")) {
(document.getElementById("themeDefaultStyle") as HTMLLinkElement).href = `/appearance/themes/${window.siyuan.config.appearance.mode === 1 ? "midnight" : "daylight"}/theme.css?v=${Constants.SIYUAN_VERSION}`;
} else {
(document.getElementById("themeStyle") as HTMLLinkElement).href = `/appearance/themes/${currentTheme}/theme.css?v=${response.data.appearance.themeVer}`;
}
} else if (bazaarType === "plugins") {
if (bazaarType === "plugins") {
app.plugins.find((item: Plugin) => {
if (item.name === dataObj.name) {
reloadPlugin(app, {
@ -838,7 +782,7 @@ export const bazaar = {
frontend: getFrontend()
}, response => {
this._genMyHTML(bazaarType, app);
bazaar._onBazaar(response, bazaarType, ["themes", "icons"].includes(bazaarType));
bazaar._onBazaar(response, bazaarType);
});
});
}
@ -856,9 +800,8 @@ export const bazaar = {
this._genMyHTML(bazaarType, app, false);
fetchPost("/api/bazaar/getBazaarIcon", {}, response => {
response.data.appearance = appearanceResponse.data;
bazaar._onBazaar(response, "icons", true);
bazaar._onBazaar(response, "icons");
bazaar._data.icons = response.data.packages;
reloadOtherWindow();
});
});
} else if (bazaarType === "themes") {
@ -868,35 +811,10 @@ export const bazaar = {
themeDark: mode === 1 ? packageName : window.siyuan.config.appearance.themeDark,
themeLight: mode === 0 ? packageName : window.siyuan.config.appearance.themeLight,
}), async (appearanceResponse) => {
reloadOtherWindow();
if ((mode !== window.siyuan.config.appearance.mode ||
(mode === 1 && window.siyuan.config.appearance.themeDark !== packageName) ||
(mode === 0 && window.siyuan.config.appearance.themeLight !== packageName)) &&
window.siyuan.config.appearance.themeJS) {
if (window.destroyTheme) {
try {
await window.destroyTheme();
window.destroyTheme = undefined;
document.getElementById("themeScript").remove();
} catch (e) {
console.error("destroyTheme error: " + e);
}
window.siyuan.config.appearance = appearanceResponse.data;
loadAssets(window.siyuan.config.appearance);
} else {
exportLayout({
cb() {
window.location.reload();
},
errorExit: false,
});
return;
}
}
this._genMyHTML("themes", app, false);
fetchPost("/api/bazaar/getBazaarTheme", {}, response => {
response.data.appearance = appearanceResponse.data;
bazaar._onBazaar(response, "themes", true);
bazaar._onBazaar(response, "themes");
bazaar._data.themes = response.data.packages;
});
});
@ -993,29 +911,29 @@ export const bazaar = {
if (!item.getAttribute("data-init")) {
if (type === "template") {
fetchPost("/api/bazaar/getBazaarTemplate", {}, response => {
bazaar._onBazaar(response, "templates", false);
bazaar._onBazaar(response, "templates");
bazaar._data.templates = response.data.packages;
});
} else if (type === "icon") {
fetchPost("/api/bazaar/getBazaarIcon", {}, response => {
bazaar._onBazaar(response, "icons", false);
bazaar._onBazaar(response, "icons");
bazaar._data.icons = response.data.packages;
});
} else if (type === "widget") {
fetchPost("/api/bazaar/getBazaarWidget", {}, response => {
bazaar._onBazaar(response, "widgets", false);
bazaar._onBazaar(response, "widgets");
bazaar._data.widgets = response.data.packages;
});
} else if (type === "theme") {
fetchPost("/api/bazaar/getBazaarTheme", {}, response => {
bazaar._onBazaar(response, "themes", false);
bazaar._onBazaar(response, "themes");
bazaar._data.themes = response.data.packages;
});
} else if (type === "plugin") {
fetchPost("/api/bazaar/getBazaarPlugin", {
frontend: getFrontend()
}, response => {
bazaar._onBazaar(response, "plugins", false);
bazaar._onBazaar(response, "plugins");
bazaar._data.plugins = response.data.packages;
});
}
@ -1048,22 +966,22 @@ export const bazaar = {
const type = (hasClosestByClassName(inputElement, "config-bazaar__panel") as HTMLElement).getAttribute("data-type");
if (type === "template") {
fetchPost("/api/bazaar/getBazaarTemplate", {keyword}, response => {
bazaar._onBazaar(response, "templates", false);
bazaar._onBazaar(response, "templates");
bazaar._data.templates = response.data.packages;
});
} else if (type === "icon") {
fetchPost("/api/bazaar/getBazaarIcon", {keyword}, response => {
bazaar._onBazaar(response, "icons", false);
bazaar._onBazaar(response, "icons");
bazaar._data.icons = response.data.packages;
});
} else if (type === "widget") {
fetchPost("/api/bazaar/getBazaarWidget", {keyword}, response => {
bazaar._onBazaar(response, "widgets", false);
bazaar._onBazaar(response, "widgets");
bazaar._data.widgets = response.data.packages;
});
} else if (type === "theme") {
fetchPost("/api/bazaar/getBazaarTheme", {keyword}, response => {
bazaar._onBazaar(response, "themes", false);
bazaar._onBazaar(response, "themes");
bazaar._data.themes = response.data.packages;
});
} else if (type === "plugin") {
@ -1071,7 +989,7 @@ export const bazaar = {
frontend: getFrontend(),
keyword
}, response => {
bazaar._onBazaar(response, "plugins", false);
bazaar._onBazaar(response, "plugins");
bazaar._data.plugins = response.data.packages;
});
} else if (type === "downloaded") {
@ -1148,7 +1066,7 @@ export const bazaar = {
});
});
},
_onBazaar(response: IWebSocketData, bazaarType: TBazaarType, reload: boolean) {
_onBazaar(response: IWebSocketData, bazaarType: TBazaarType) {
if (bazaar.element.querySelector("#configBazaarReadme").classList.contains("config-bazaar__readme--show")) {
const dataObj = JSON.parse(bazaar.element.querySelector("#configBazaarReadme > .item__side").getAttribute("data-obj"));
bazaar._renderReadme((dataObj.bazaarType) as TBazaarType,
@ -1206,8 +1124,5 @@ export const bazaar = {
html += '<div class="fn__flex-1" style="margin-left: 15px;min-width: 342px;"></div><div class="fn__flex-1" style="margin-left: 15px;min-width: 342px;"></div>';
}
element.innerHTML = `<div class="b3-cards">${html}</div>`;
if (reload) {
appearance.onSetAppearance(response.data.appearance);
}
}
};

View file

@ -143,7 +143,7 @@ export const keymap = {
<div class="fn__space"></div>
<label class="b3-form__icon fn__block searchByKeyLabel">
<svg class="b3-form__icon-icon"><use xlink:href="#iconKeymap"></use></svg>
<input id="searchByKey" data-value="" class="b3-form__icon-input b3-text-field fn__block" spellcheck="false" placeholder="${window.siyuan.languages.keymap}">
<input id="searchByKey" data-keymap="" class="b3-form__icon-input b3-text-field fn__block" spellcheck="false" placeholder="${window.siyuan.languages.keymap}">
</label>
<div class="fn__space"></div>
<button id="clearSearchBtn" class="b3-button b3-button--outline fn__flex-center fn__size200">
@ -337,13 +337,13 @@ export const keymap = {
const searchElement = keymap.element.querySelector("#keymapInput") as HTMLInputElement;
const searchKeymapElement = keymap.element.querySelector("#searchByKey") as HTMLInputElement;
searchElement.addEventListener("compositionend", () => {
keymap.search(searchElement.value, searchKeymapElement.dataset.value);
keymap.search(searchElement.value, searchKeymapElement.dataset.keymap);
});
searchElement.addEventListener("input", (event: InputEvent) => {
if (event.isComposing) {
return;
}
keymap.search(searchElement.value, searchKeymapElement.dataset.value);
keymap.search(searchElement.value, searchKeymapElement.dataset.keymap);
});
/// #if !BROWSER
searchKeymapElement.addEventListener("focus", () => {

View file

@ -3,7 +3,6 @@ import {Dialog} from "../../dialog";
import {objEquals} from "../../util/functions";
import {confirmDialog} from "../../dialog/confirmDialog";
import {Constants} from "../../constants";
import {reloadOtherWindow} from "../../dialog/processSystem";
export const renderSnippet = () => {
fetchPost("/api/snippet/getSnippet", {type: "all", enabled: 2}, (response) => {
@ -225,10 +224,7 @@ const setSnippetPost = (dialog: Dialog, snippets: ISnippet[], removeIds: string[
});
window.siyuan.config.snippet.enabledCSS = (dialog.element.querySelector('.b3-switch[data-action="toggleCSS"]') as HTMLInputElement).checked;
window.siyuan.config.snippet.enabledJS = (dialog.element.querySelector('.b3-switch[data-action="toggleJS"]') as HTMLInputElement).checked;
fetchPost("/api/setting/setSnippet", window.siyuan.config.snippet, () => {
reloadOtherWindow();
});
renderSnippet();
fetchPost("/api/setting/setSnippet", window.siyuan.config.snippet);
dialog.destroy({cancel: "true"});
});
};

View file

@ -0,0 +1,40 @@
import IAppearance = Config.IAppearance;
import {exportLayout} from "../../layout/util";
import {appearance} from "../appearance";
export const updateAppearance = async (data:IAppearance) => {
if (window.siyuan.config.appearance.themeJS) {
if (data.mode !== window.siyuan.config.appearance.mode ||
(data.mode === window.siyuan.config.appearance.mode && (
(data.mode === 0 && window.siyuan.config.appearance.themeLight !== data.themeLight) ||
(data.mode === 1 && window.siyuan.config.appearance.themeDark !== data.themeDark))
)
) {
if (window.destroyTheme) {
try {
await window.destroyTheme();
window.destroyTheme = undefined;
document.getElementById("themeScript").remove();
} catch (e) {
console.error("destroyTheme error: " + e);
}
} else {
exportLayout({
errorExit: false,
cb() {
window.location.reload();
},
});
return;
}
}
}
if (data.hideStatusBar !== window.siyuan.config.appearance.hideStatusBar) {
if (data.hideStatusBar) {
document.getElementById("status").classList.add("fn__none");
} else {
document.getElementById("status").classList.remove("fn__none");
}
}
appearance.onSetAppearance(data);
};

View file

@ -57,7 +57,6 @@ export abstract class Constants {
public static readonly SIYUAN_CONTEXT_MENU: string = "siyuan-context-menu";
public static readonly SIYUAN_SHOW_WINDOW: string = "siyuan-show-window";
public static readonly SIYUAN_RELOAD_WINDOW: string = "siyuan-reload-window";
// custom
public static readonly CUSTOM_SY_READONLY: string = "custom-sy-readonly";

View file

@ -280,12 +280,6 @@ export const kernelError = () => {
}
};
export const reloadOtherWindow = () => {
/// #if !BROWSER
ipcRenderer.send(Constants.SIYUAN_RELOAD_WINDOW, location.port);
/// #endif
};
export const exitSiYuan = async () => {
hideAllElements(["util"]);
/// #if MOBILE

View file

@ -53,9 +53,9 @@ export const showTooltip = (message: string, target: Element, tooltipClass?: str
if (left < 0) {
left = targetRect.right;
}
} else if (position === "north") {
// north: av 视图,列,多选描述
const positionDiff = 0.5;
} else if (position?.endsWith("north")) {
// north: av 视图,列,多选描述, protyle-icon
const positionDiff = parseInt(position) || 0.5;
left = Math.max(0, targetRect.left - (messageElement.clientWidth - targetRect.width) / 2);
top = targetRect.top - messageElement.clientHeight - positionDiff;
if (top < 0) {

View file

@ -23,6 +23,7 @@ export class Editor extends Model {
mode?: TEditorMode,
action?: TProtyleAction[],
afterInitProtyle?: (editor: Protyle) => void,
scrollPosition?: ScrollLogicalPosition
}) {
super({
app: options.app,
@ -43,6 +44,7 @@ export class Editor extends Model {
action?: TProtyleAction[]
rootId: string,
mode?: TEditorMode,
scrollPosition?: ScrollLogicalPosition,
afterInitProtyle?: (editor: Protyle) => void,
}) {
this.editor = new Protyle(this.app, this.element, {
@ -56,6 +58,7 @@ export class Editor extends Model {
scroll: true,
},
typewriterMode: true,
scrollPosition: options.scrollPosition,
after: (editor) => {
if (window.siyuan.editorIsFullscreen) {
fullscreen(editor.protyle.element);

View file

@ -46,7 +46,8 @@ export const openFileById = async (options: {
zoomIn?: boolean
removeCurrentTab?: boolean
openNewTab?: boolean
afterOpen?: (model: Model) => void
afterOpen?: (model: Model) => void,
scrollPosition?: ScrollLogicalPosition
}) => {
const response = await fetchSyncPost("/api/block/getBlockInfo", {id: options.id});
if (response.code === -1) {
@ -70,7 +71,8 @@ export const openFileById = async (options: {
keepCursor: options.keepCursor,
removeCurrentTab: options.removeCurrentTab,
afterOpen: options.afterOpen,
openNewTab: options.openNewTab
openNewTab: options.openNewTab,
scrollPosition: options.scrollPosition,
});
};
@ -337,6 +339,7 @@ const getUnInitTab = (options: IOpenFileOptions) => {
} else {
initObj.action = options.action;
}
initObj.scrollPosition = options.scrollPosition;
item.headElement.setAttribute("data-initdata", JSON.stringify(initObj));
item.parent.switchTab(item.headElement);
return true;
@ -376,7 +379,12 @@ const switchEditor = (editor: Editor, options: IOpenFileOptions, allModels: IMod
mode: (options.action && options.action.includes(Constants.CB_GET_CONTEXT)) ? 3 : 0,
size: window.siyuan.config.editor.dynamicLoadBlocks,
}, getResponse => {
onGet({data: getResponse, protyle: editor.editor.protyle, action: options.action});
onGet({
data: getResponse,
protyle: editor.editor.protyle,
action: options.action,
scrollPosition: options.scrollPosition
});
// 大纲点击折叠标题下的内容时,需更新反链面板
updateBacklinkGraph(allModels, editor.editor.protyle);
});
@ -386,13 +394,14 @@ const switchEditor = (editor: Editor, options: IOpenFileOptions, allModels: IMod
editor.editor.protyle.observerLoad?.disconnect();
if (options.action?.includes(Constants.CB_GET_HL)) {
highlightById(editor.editor.protyle, options.id, "start");
} else if (options.action?.includes(Constants.CB_GET_FOCUS)) {
}
if (options.action?.includes(Constants.CB_GET_FOCUS)) {
if (nodeElement) {
const newRange = focusBlock(nodeElement, undefined, !options.action?.includes(Constants.CB_GET_OUTLINE));
if (newRange) {
editor.editor.protyle.toolbar.range = newRange;
}
scrollCenter(editor.editor.protyle);
scrollCenter(editor.editor.protyle, (editor.editor.protyle.disabled || options.scrollPosition) ? nodeElement : null, options.scrollPosition);
editor.editor.protyle.observerLoad = new ResizeObserver(() => {
if (document.contains(nodeElement)) {
scrollCenter(editor.editor.protyle);
@ -504,6 +513,7 @@ const newTab = (options: IOpenFileOptions) => {
blockId: options.id,
rootId: options.rootID,
action: [Constants.CB_GET_ALL, Constants.CB_GET_FOCUS],
scrollPosition: options.scrollPosition,
});
} else {
editor = new Editor({
@ -513,6 +523,7 @@ const newTab = (options: IOpenFileOptions) => {
rootId: options.rootID,
mode: options.mode,
action: options.action,
scrollPosition: options.scrollPosition,
});
}
tab.addModel(editor);

View file

@ -38,6 +38,8 @@ import {setLocalShorthandCount} from "./util/noRelyPCFunction";
import {getDockByType} from "./layout/tabUtil";
import {Tag} from "./layout/dock/Tag";
import {updateControlAlt} from "./protyle/util/hotKey";
import {updateAppearance} from "./config/util/updateAppearance";
import {renderSnippet} from "./config/util/snippets";
export class App {
public plugins: import("./plugin").Plugin[] = [];
@ -69,6 +71,13 @@ export class App {
});
if (data) {
switch (data.cmd) {
case "setAppearance":
updateAppearance(data.data);
break;
case "setSnippet":
window.siyuan.config.snippet = data.data;
renderSnippet();
break;
case "setDefRefCount":
setDefRefCount(data.data);
break;

View file

@ -777,6 +777,9 @@ export class Files extends Model {
if (liElement) {
liElement.setAttribute("data-count", data.data.subFileCount);
liElement.querySelector(".ariaLabel")?.setAttribute("aria-label", this.genDocAriaLabel(data.data, escapeGreat));
if (data.data.subFileCount === 0) {
liElement.querySelector(".b3-list-item__toggle")?.classList.add("fn__hidden");
}
}
}

View file

@ -177,6 +177,7 @@ export class Outline extends Model {
openFileById({
app: options.app,
id,
scrollPosition: "start",
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HTML, Constants.CB_GET_OUTLINE] : [Constants.CB_GET_FOCUS, Constants.CB_GET_OUTLINE, Constants.CB_GET_SETID, Constants.CB_GET_CONTEXT, Constants.CB_GET_HTML],
});
});
@ -331,7 +332,7 @@ export class Outline extends Model {
preview: this.isPreview
}, response => {
this.update(response);
this.updateDocTitle((options.tab.model as Editor)?.editor.protyle?.background?.ial, response.data?.length || 0);
this.updateDocTitle((options.tab.model as Editor)?.editor?.protyle?.background?.ial, response.data?.length || 0);
});
}
@ -930,6 +931,7 @@ export class Outline extends Model {
openFileById({
app: this.app,
id,
scrollPosition: "start",
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HTML, Constants.CB_GET_OUTLINE] : [Constants.CB_GET_FOCUS, Constants.CB_GET_OUTLINE, Constants.CB_GET_SETID, Constants.CB_GET_CONTEXT, Constants.CB_GET_HTML],
});
});

View file

@ -750,6 +750,7 @@ export const newModelByInitData = (app: App, tab: Tab, json: any) => {
rootId: json.rootId,
blockId: json.blockId,
mode: json.mode,
scrollPosition: json.scrollPosition,
action: typeof json.action === "string" ? (json.action ? [json.action, Constants.CB_GET_FOCUS] : [Constants.CB_GET_FOCUS]) : json.action.concat(Constants.CB_GET_FOCUS),
});
}

View file

@ -6,7 +6,7 @@ import {getSearch, isMobile, isValidAttrName} from "../util/functions";
import {isLocalPath, movePathTo, moveToPath, pathPosix} from "../util/pathName";
import {MenuItem} from "./Menu";
import {onExport, saveExport} from "../protyle/export";
import {isInAndroid, isInHarmony, openByMobile, writeText} from "../protyle/util/compatibility";
import {isInAndroid, isInHarmony, isInIOS, openByMobile, writeText} from "../protyle/util/compatibility";
import {fetchPost, fetchSyncPost} from "../util/fetch";
import {hideMessage, showMessage} from "../dialog/message";
import {Dialog} from "../dialog";
@ -443,7 +443,21 @@ export const copySubMenu = (ids: string[], accelerator = true, focusElement?: El
focusBlock(focusElement);
}
}
}, {
},
/// #if BROWSER
{
id: "copyWebURL",
iconHTML: "",
label: window.siyuan.languages.copyWebURL,
click: () => {
copyTextByType(ids, "webURL");
if (focusElement) {
focusBlock(focusElement);
}
}
},
/// #endif
{
id: "copyHPath",
iconHTML: "",
label: window.siyuan.languages.copyHPath,
@ -758,7 +772,7 @@ export const exportMd = (id: string) => {
id: "exportPDF",
label: window.siyuan.languages.print,
icon: "iconPDF",
ignore: !isInAndroid() && !isInHarmony(),
ignore: !isInAndroid() && !isInHarmony() && !isInIOS(),
click: () => {
const msgId = showMessage(window.siyuan.languages.exporting);
const localData = window.siyuan.storage[Constants.LOCAL_EXPORTPDF];
@ -770,9 +784,11 @@ export const exportMd = (id: string) => {
const servePath = window.location.protocol + "//" + window.location.host + "/";
const html = await onExport(response, undefined, servePath, {type: "pdf", id});
if (isInAndroid()) {
window.JSAndroid.print(html);
window.JSAndroid.print(response.data.name, html);
} else if (isInHarmony()) {
window.JSHarmony.print(html);
window.JSHarmony.print(response.data.name, html);
} else if (isInIOS()) {
window.webkit.messageHandlers.print.postMessage(response.data.name + Constants.ZWSP + html);
}
setTimeout(() => {

View file

@ -61,7 +61,7 @@ import {popSearch} from "../mobile/menu/search";
import {showMessage} from "../dialog/message";
import {img3115} from "../boot/compatibleVersion";
import {hideTooltip} from "../dialog/tooltip";
import {clearSelect} from "../protyle/util/clearSelect";
import {clearSelect} from "../protyle/util/clear";
import {scrollCenter} from "../util/highlightById";
const renderAssetList = (element: Element, k: string, position: IPosition, exts: string[] = []) => {

View file

@ -19,7 +19,7 @@ export const getCurrentEditor = () => {
return window.siyuan.mobile.popEditor || window.siyuan.mobile.editor;
};
export const openMobileFileById = (app: App, id: string, action: TProtyleAction[] = [Constants.CB_GET_HL]) => {
export const openMobileFileById = (app: App, id: string, action: TProtyleAction[] = [Constants.CB_GET_HL], scrollPosition?: ScrollLogicalPosition) => {
window.siyuan.storage[Constants.LOCAL_DOCINFO] = {id};
setStorageVal(Constants.LOCAL_DOCINFO, window.siyuan.storage[Constants.LOCAL_DOCINFO]);
const avPanelElement = document.querySelector(".av__panel");
@ -44,7 +44,7 @@ export const openMobileFileById = (app: App, id: string, action: TProtyleAction[
if (action.includes(Constants.CB_GET_HL)) {
highlightById(window.siyuan.mobile.editor.protyle, id);
} else {
scrollCenter(window.siyuan.mobile.editor.protyle, blockElement);
scrollCenter(window.siyuan.mobile.editor.protyle, blockElement, scrollPosition);
}
closePanel();
// 更新文档浏览时间

View file

@ -1,7 +1,6 @@
import {fetchPost} from "../../util/fetch";
import {genLangOptions, genOptions} from "../../util/genOptions";
import {openModel} from "../menu/model";
import {reloadOtherWindow} from "../../dialog/processSystem";
export const initAppearance = () => {
openModel({
@ -55,10 +54,7 @@ export const initAppearance = () => {
themeDark: (modelMainElement.querySelector("#themeDark") as HTMLSelectElement).value,
themeLight: (modelMainElement.querySelector("#themeLight") as HTMLSelectElement).value,
lang: (modelMainElement.querySelector("#lang") as HTMLSelectElement).value,
}), () => {
reloadOtherWindow();
window.location.reload();
});
}));
});
});
}

View file

@ -11,10 +11,18 @@ import {reloadPlugin} from "../../plugin/loader";
import {reloadEmoji} from "../../emoji";
import {setLocalShorthandCount} from "../../util/noRelyPCFunction";
import {updateControlAlt} from "../../protyle/util/hotKey";
import {renderSnippet} from "../../config/util/snippets";
export const onMessage = (app: App, data: IWebSocketData) => {
if (data) {
switch (data.cmd) {
case "setAppearance":
window.location.reload();
break;
case "setSnippet":
window.siyuan.config.snippet = data.data;
renderSnippet();
break;
case "setDefRefCount":
setDefRefCount(data.data);
break;

View file

@ -244,7 +244,8 @@ export const handleTouchMove = (event: TouchEvent) => {
} else if (scrollElement.classList.contains("code-block")) {
scrollElement = scrollElement.firstElementChild.nextElementSibling as HTMLElement;
} else if (scrollElement.classList.contains("av")) {
scrollElement = hasClosestByClassName(target, "layout-tab-bar") || hasClosestByClassName(target, "av__scroll");
scrollElement = hasClosestByClassName(target, "layout-tab-bar") || hasClosestByClassName(target, "av__scroll") ||
hasClosestByClassName(target, "av__kanban");
} else if (scrollElement.dataset.type === "NodeMathBlock") {
scrollElement = target;
while (scrollElement && scrollElement.dataset.type !== "NodeMathBlock") {

View file

@ -11,7 +11,7 @@ import {getThemeMode, setInlineStyle} from "../../util/assets";
import {fetchPost, fetchSyncPost} from "../../util/fetch";
import {Dialog} from "../../dialog";
import {replaceLocalPath} from "../../editor/rename";
import {getScreenWidth, isInAndroid, isInHarmony, setStorageVal} from "../util/compatibility";
import {getScreenWidth, isInAndroid, isInHarmony, isInIOS, setStorageVal} from "../util/compatibility";
import {getFrontend} from "../../util/functions";
const getPluginStyle = async () => {
@ -117,13 +117,23 @@ export const saveExport = (option: IExportOptions) => {
const getSnippetCSS = () => {
let snippetCSS = "";
document.querySelectorAll("style").forEach((item) => {
if (item.id.startsWith("snippet")) {
if (item.id.startsWith("snippetCSS")) {
snippetCSS += item.outerHTML;
}
});
return snippetCSS;
};
const getSnippetJS = () => {
let snippetScript = "";
document.querySelectorAll("script").forEach((item) => {
if (item.id.startsWith("snippetJS")) {
snippetScript += item.outerHTML;
}
});
return snippetScript;
};
/// #if !BROWSER
const renderPDF = async (id: string) => {
const localData = window.siyuan.storage[Constants.LOCAL_EXPORTPDF];
@ -624,7 +634,9 @@ ${getIconScript(servePath)}
}
})
});
</script></body></html>`;
</script>
${getSnippetJS()}
</body></html>`;
fetchPost("/api/export/exportTempContent", {content: html}, (response) => {
ipcRenderer.send(Constants.SIYUAN_EXPORT_NEWWINDOW, response.data.url);
});
@ -705,13 +717,14 @@ export const onExport = async (data: IWebSocketData, filePath: string, servePath
themeStyle = `<link rel="stylesheet" type="text/css" id="themeStyle" href="${servePath}appearance/themes/${themeName}/theme.css?${Constants.SIYUAN_VERSION}"/>`;
}
const screenWidth = getScreenWidth();
const mobileHtml = isInAndroid() || isInHarmony() ? {
const isInMobile = isInAndroid() || isInHarmony() || isInIOS();
const mobileHtml = isInMobile ? {
js: `document.body.style.minWidth = "${screenWidth}px";`,
css: `@page { size: A4; margin: 10mm 0 10mm 0; }
.protyle-wysiwyg {padding: 0; margin: 0;}`
} : {js: "", css: ""};
const html = `<!DOCTYPE html>
<html lang="${window.siyuan.config.appearance.lang}" data-theme-mode="${getThemeMode()}" data-light-theme="${window.siyuan.config.appearance.themeLight}" data-dark-theme="${window.siyuan.config.appearance.themeDark}">
<html lang="${window.siyuan.config.appearance.lang}" data-theme-mode="${isInMobile ? "light" : getThemeMode()}" data-light-theme="${window.siyuan.config.appearance.themeLight}" data-dark-theme="${window.siyuan.config.appearance.themeDark}">
<head>
<base href="${servePath}">
<meta charset="utf-8">
@ -775,7 +788,8 @@ ${getIconScript(servePath)}
event.stopPropagation();
})
});
</script></body></html>`;
</script>
${getSnippetJS()}</body></html>`;
// 移动端导出 pdf、浏览器导出 HTML
if (typeof filePath === "undefined") {
return html;

View file

@ -62,7 +62,7 @@ import {openFileById} from "../../editor/util";
import * as path from "path";
/// #endif
import {checkFold} from "../../util/noRelyPCFunction";
import {clearSelect} from "../util/clearSelect";
import {clearSelect} from "../util/clear";
export class Gutter {
public element: HTMLElement;
@ -2102,6 +2102,8 @@ export class Gutter {
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
if (e.classList.contains("av")) {
e.style.justifyContent = "";
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
e.style.margin = "";
} else {
e.style.textAlign = "left";
}
@ -2116,6 +2118,8 @@ export class Gutter {
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
if (e.classList.contains("av")) {
e.style.justifyContent = "center";
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
e.style.margin = "0 auto";
} else {
e.style.textAlign = "center";
}
@ -2130,6 +2134,8 @@ export class Gutter {
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
if (e.classList.contains("av")) {
e.style.justifyContent = "flex-end";
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
e.style.margin = "0 0 0 auto";
} else {
e.style.textAlign = "right";
}
@ -2180,6 +2186,8 @@ export class Gutter {
this.genClick(nodeElements, protyle, (e: HTMLElement) => {
if (e.classList.contains("av")) {
e.style.justifyContent = "";
} else if (["NodeIFrame", "NodeWidget"].includes(e.getAttribute("data-type"))) {
e.style.margin = "";
} else {
e.style.textAlign = "";
e.style.direction = "";

View file

@ -209,8 +209,24 @@ ${unicode2Emoji(emoji.unicode)}</button>`;
if (this.element.classList.contains("fn__none")) {
this.element.innerHTML = '<div class="fn__loading" style="height: 128px;position: initial"><img width="64px" src="/stage/loading-pure.svg"></div>';
this.element.classList.remove("fn__none");
const textareaPosition = getSelectionPosition(protyle.wysiwyg.element);
setPosition(this.element, textareaPosition.left, textareaPosition.top + 26, 30);
if (this.source === "av") {
const cellElement = hasClosestByClassName(protyle.toolbar.range.startContainer, "av__cell");
if (cellElement) {
/// #if !MOBILE
const cellRect = cellElement.getBoundingClientRect();
setPosition(this.element, cellRect.left, cellRect.bottom, cellRect.height);
/// #else
setPosition(this.element, 0, 0);
/// #endif
}
} else {
/// #if !MOBILE
const textareaPosition = getSelectionPosition(protyle.wysiwyg.element);
setPosition(this.element, textareaPosition.left, textareaPosition.top + 26, 30);
/// #else
setPosition(this.element, 0, 0);
/// #endif
}
} else {
this.element.insertAdjacentHTML("beforeend", '<div class="fn__loading"><img width="64px" src="/stage/loading-pure.svg"></div>');
}

View file

@ -347,6 +347,7 @@ export class Protyle {
data: getResponse,
protyle: this.protyle,
action: mergedOptions.action,
scrollPosition: mergedOptions.scrollPosition,
afterCB: () => {
this.afterOnGet(mergedOptions);
}

View file

@ -36,9 +36,10 @@ import {fetchPost, fetchSyncPost} from "../../../util/fetch";
import {scrollCenter} from "../../../util/highlightById";
import {escapeHtml} from "../../../util/escape";
import {editGalleryItem, openGalleryItemMenu} from "./gallery/util";
import {clearSelect} from "../../util/clearSelect";
import {clearSelect} from "../../util/clear";
import {removeCompressURL} from "../../../util/image";
let foldTimeout: number;
export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLElement }) => {
if (isOnlyMeta(event)) {
return false;
@ -228,9 +229,17 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
event.stopPropagation();
return true;
} else if (type === "av-group-fold") {
if (target.getAttribute("data-folding") !== "true") {
target.setAttribute("data-folding", "true");
const isOpen = target.firstElementChild.classList.contains("av__group-arrow--open");
target.setAttribute("data-processed", "true");
const isOpen = target.firstElementChild.classList.contains("av__group-arrow--open");
if (isOpen) {
target.firstElementChild.classList.remove("av__group-arrow--open");
target.parentElement.nextElementSibling.classList.add("fn__none");
} else {
target.firstElementChild.classList.add("av__group-arrow--open");
target.parentElement.nextElementSibling.classList.remove("fn__none");
}
clearTimeout(foldTimeout);
foldTimeout = window.setTimeout(() => {
transaction(protyle, [{
action: "foldAttrViewGroup",
avID: blockElement.dataset.avId,
@ -244,14 +253,7 @@ export const avClick = (protyle: IProtyle, event: MouseEvent & { target: HTMLEle
id: target.dataset.id,
data: !isOpen
}]);
if (isOpen) {
target.firstElementChild.classList.remove("av__group-arrow--open");
target.parentElement.nextElementSibling.classList.add("fn__none");
} else {
target.firstElementChild.classList.add("av__group-arrow--open");
target.parentElement.nextElementSibling.classList.remove("fn__none");
}
}
}, Constants.TIMEOUT_COUNT);
event.preventDefault();
event.stopPropagation();
return true;

View file

@ -2,7 +2,7 @@ import {genCellValue, getTypeByCellElement, renderCell, renderCellAttr} from "..
import {fetchPost} from "../../../../util/fetch";
import {setPage} from "../row";
import {Constants} from "../../../../constants";
import {clearSelect} from "../../../util/clearSelect";
import {clearSelect} from "../../../util/clear";
export const insertGalleryItemAnimation = (options: {
blockElement: HTMLElement;

View file

@ -104,8 +104,8 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex,
});
galleryHTML += `</div>
<div class="av__gallery-actions">
<span class="protyle-icon protyle-icon--first b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
<span class="protyle-icon protyle-icon--last b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
<span class="protyle-icon protyle-icon--first ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
<span class="protyle-icon protyle-icon--last ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
</div>
</div>`;
});

View file

@ -29,7 +29,7 @@ const getKanbanTitleHTML = (group: IAVView, counter: number) => {
// av__group-name 为第三方需求,本应用内没有使用,但不能移除 https://github.com/siyuan-note/siyuan/issues/15736
return `<div class="av__group-title">
<span class="av__group-name fn__ellipsis" style="white-space: nowrap;">${nameHTML}</span>
${counter === 0 ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
${(!counter || counter === 0) ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
<span class="fn__flex-1"></span>
<span class="av__group-icon av__group-icon--hover ariaLabel" data-type="av-add-top" data-position="north" aria-label="${window.siyuan.languages.newRow}"><svg><use xlink:href="#iconAdd"></use></svg></span>
</div>`;
@ -100,8 +100,8 @@ ${cell.color ? `color:${cell.color};` : ""}">${renderCell(cell.value, rowIndex,
});
galleryHTML += `</div>
<div class="av__gallery-actions">
<span class="protyle-icon protyle-icon--first b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
<span class="protyle-icon protyle-icon--last b3-tooltips b3-tooltips__n" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
<span class="protyle-icon protyle-icon--first ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.displayEmptyFields}" data-type="av-gallery-edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
<span class="protyle-icon protyle-icon--last ariaLabel" data-position="4north" aria-label="${window.siyuan.languages.more}" data-type="av-gallery-more"><svg><use xlink:href="#iconMore"></use></svg></span>
</div>
</div>`;
});

View file

@ -5,7 +5,7 @@ import {avContextmenu} from "./action";
import {hasClosestByClassName} from "../../util/hasClosest";
import {Constants} from "../../../constants";
import {upDownHint} from "../../../util/upDownHint";
import {clearSelect} from "../../util/clearSelect";
import {clearSelect} from "../../util/clear";
export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement, protyle: IProtyle) => {
if (!nodeElement.classList.contains("av") || !window.siyuan.menus.menu.element.classList.contains("fn__none")) {

View file

@ -218,7 +218,7 @@ export const bindLayoutEvent = (options: {
return;
}
const toggleBgElement = options.menuElement.querySelector('.b3-switch[data-type="toggle-kanban-bg"]') as HTMLInputElement;
toggleBgElement.addEventListener("change", () => {
toggleBgElement?.addEventListener("change", () => {
const checked = toggleBgElement.checked;
transaction(options.protyle, [{
action: "setAttrViewFillColBackgroundColor",

View file

@ -17,7 +17,7 @@ import {renderGallery} from "./gallery/render";
import {getFieldsByData, getViewIcon} from "./view";
import {openMenuPanel} from "./openMenuPanel";
import {getPageSize} from "./groups";
import {clearSelect} from "../../util/clearSelect";
import {clearSelect} from "../../util/clear";
import {showMessage} from "../../../dialog/message";
import {renderKanban} from "./kanban/render";
@ -251,7 +251,7 @@ export const getGroupTitleHTML = (group: IAVView, counter: number) => {
</div>
<span class="fn__space"></span>
<span class="av__group-name">${nameHTML}</span>
${counter === 0 ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
${(!counter || counter === 0) ? '<span class="fn__space"></span>' : `<span aria-label="${window.siyuan.languages.entryNum}" data-position="north" class="av__group-counter ariaLabel">${counter}</span>`}
<span class="av__group-icon av__group-icon--hover ariaLabel" data-type="av-add-top" data-position="north" aria-label="${window.siyuan.languages.newRow}"><svg><use xlink:href="#iconAdd"></use></svg></span>
</div>`;
};
@ -784,6 +784,10 @@ export const refreshAV = (protyle: IProtyle, operation: IOperation) => {
getAVElements(protyle, operation.avID).forEach((item) => {
const foldElement = item.querySelector(`[data-type="av-group-fold"][data-id="${operation.id}"]`);
if (foldElement) {
if (foldElement.getAttribute("data-processed") === "true") {
foldElement.removeAttribute("data-processed");
return;
}
if (operation.data) {
foldElement.firstElementChild.classList.remove("av__group-arrow--open");
foldElement.parentElement.nextElementSibling.classList.add("fn__none");

View file

@ -7,7 +7,7 @@ import {fetchPost} from "../../../util/fetch";
import * as dayjs from "dayjs";
import {Constants} from "../../../constants";
import {insertGalleryItemAnimation} from "./gallery/item";
import {clearSelect} from "../../util/clearSelect";
import {clearSelect} from "../../util/clear";
import {isCustomAttr} from "./blockAttr";
export const getFieldIdByCellElement = (cellElement: Element, viewType: TAVView): string => {

View file

@ -12,7 +12,7 @@ export const genIconHTML = (element?: false | HTMLElement, actions = ["edit", "m
}
}
const mapActionToHTML = (action: string, isFirst: boolean, isLast: boolean) => {
const classList = ["b3-tooltips__nw", "b3-tooltips", "protyle-icon"];
const classList = ["ariaLabel", "protyle-icon"];
if (isFirst) classList.push("protyle-icon--first");
if (isLast) classList.push("protyle-icon--last");
let aria = "";
@ -45,7 +45,7 @@ export const genIconHTML = (element?: false | HTMLElement, actions = ["edit", "m
}
// Only the edit button honors read-only enable
const hidden = (action === "edit" && !enable) ? " fn__none" : "";
return `<span aria-label="${aria}" class="${classList.join(" ")} ${className}${hidden}"><svg><use xlink:href="#${icon}"></use></svg></span>`;
return `<span aria-label="${aria}" data-position="4north" class="${classList.join(" ")} ${className}${hidden}"><svg><use xlink:href="#${icon}"></use></svg></span>`;
};
const res: string[] = [];
for (let i = 0; i < actions.length; i++) {
@ -65,9 +65,9 @@ export const genRenderFrame = (renderElement: Element) => {
const type = renderElement.getAttribute("data-type");
if (type === "NodeBlockQueryEmbed") {
renderElement.insertAdjacentHTML("afterbegin", `<div class="protyle-icons${isInEmbedBlock(renderElement) ? " fn__none" : ""}">
<span aria-label="${window.siyuan.languages.refresh}" class="b3-tooltips__nw b3-tooltips protyle-icon protyle-action__reload protyle-icon--first"><svg class="fn__rotate"><use xlink:href="#iconRefresh"></use></svg></span>
<span aria-label="${window.siyuan.languages.update} SQL" class="b3-tooltips__nw b3-tooltips protyle-icon protyle-action__edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
<span aria-label="${window.siyuan.languages.more}" class="b3-tooltips__nw b3-tooltips protyle-icon protyle-action__menu protyle-icon--last"><svg><use xlink:href="#iconMore"></use></svg></span>
<span aria-label="${window.siyuan.languages.refresh}" data-position="4north" class="ariaLabel protyle-icon protyle-action__reload protyle-icon--first"><svg class="fn__rotate"><use xlink:href="#iconRefresh"></use></svg></span>
<span aria-label="${window.siyuan.languages.update} SQL" data-position="4north" class="ariaLabel protyle-icon protyle-action__edit"><svg><use xlink:href="#iconEdit"></use></svg></span>
<span aria-label="${window.siyuan.languages.more}" data-position="4north" class="ariaLabel protyle-icon protyle-action__menu protyle-icon--last"><svg><use xlink:href="#iconMore"></use></svg></span>
</div><div class="protyle-cursor">${Constants.ZWSP}</div>`);
} else if (type === "NodeMathBlock" || renderElement.getAttribute("data-subtype") === "math") {
renderElement.firstElementChild.innerHTML = `<span></span><span class="protyle-cursor">${Constants.ZWSP}</span>`;

View file

@ -216,7 +216,7 @@ export const toolbarKeyToMenu = (toolbar: Array<string | IMenuItem>) => {
};
export const copyTextByType = async (ids: string[],
type: "ref" | "blockEmbed" | "protocol" | "protocolMd" | "hPath" | "id") => {
type: "ref" | "blockEmbed" | "protocol" | "protocolMd" | "hPath" | "id" | "webURL") => {
let text = "";
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
@ -236,6 +236,8 @@ export const copyTextByType = async (ids: string[],
} else if (type === "hPath") {
const response = await fetchSyncPost("/api/filetree/getHPathByID", {id});
text += response.data;
} else if (type === "webURL") {
text += `${window.location.origin}?id=${id}`;
} else if (type === "id") {
text += id;
}

View file

@ -1,4 +1,19 @@
import {updateHeader} from "../render/av/row";
import {Constants} from "../../constants";
export const clearBlockElement = (element: Element) => {
element.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl");
element.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
element.removeAttribute("refcount");
element.querySelector(".protyle-attr--av")?.remove();
element.querySelector(".protyle-attr--refcount")?.remove();
element.removeAttribute("custom-avs");
element.getAttributeNames().forEach(attr => {
if (attr.startsWith("custom-sy-av-s-text-")) {
element.removeAttribute(attr);
}
});
};
export const clearSelect = (types: ("av" | "img" | "cell" | "row" | "galleryItem")[], element: Element) => {
if (types.includes("cell")) {

View file

@ -34,7 +34,7 @@ import {webUtils} from "electron";
import {addDragFill, getTypeByCellElement} from "../render/av/cell";
import {processClonePHElement} from "../render/util";
import {insertGalleryItemAnimation} from "../render/av/gallery/item";
import {clearSelect} from "./clearSelect";
import {clearSelect} from "./clear";
import {dragoverTab} from "../render/av/view";
// position: afterbegin 为拖拽成超级块; "afterend", "beforebegin" 一般拖拽

View file

@ -26,7 +26,8 @@ export const onGet = (options: {
protyle: IProtyle,
action?: TProtyleAction[],
scrollAttr?: IScrollAttr
updateReadonly?: boolean
updateReadonly?: boolean,
scrollPosition?: ScrollLogicalPosition,
afterCB?: () => void
}) => {
if (!options.action) {
@ -96,6 +97,7 @@ export const onGet = (options: {
updateReadonly: options.updateReadonly,
isSyncing: options.data.data.isSyncing,
afterCB: options.afterCB,
scrollPosition: options.scrollPosition
}, options.protyle);
removeLoading(options.protyle);
return;
@ -122,6 +124,7 @@ export const onGet = (options: {
updateReadonly: options.updateReadonly,
isSyncing: options.data.data.isSyncing,
afterCB: options.afterCB,
scrollPosition: options.scrollPosition
}, options.protyle);
removeLoading(options.protyle);
});
@ -133,7 +136,8 @@ const setHTML = (options: {
isSyncing: boolean,
expand: boolean,
updateReadonly?: boolean,
scrollAttr?: IScrollAttr
scrollAttr?: IScrollAttr,
scrollPosition?: ScrollLogicalPosition,
afterCB?: () => void
}, protyle: IProtyle) => {
if (protyle.contentElement.classList.contains("fn__none") && protyle.wysiwyg.element.innerHTML !== "") {
@ -256,7 +260,7 @@ const setHTML = (options: {
}
}
focusElementById(protyle, options.action, options.scrollAttr);
focusElementById(protyle, options.action, options.scrollAttr, options.scrollPosition);
if (options.action.includes(Constants.CB_GET_SETID)) {
// 点击大纲后,如果需要动态加载,在定位后,需要重置 block.id https://github.com/siyuan-note/siyuan/issues/4487
@ -448,7 +452,7 @@ export const enableProtyle = (protyle: IProtyle) => {
hideTooltip();
};
const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScrollAttr) => {
const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScrollAttr, scrollPosition?: ScrollLogicalPosition) => {
let focusElement: Element;
if (scrollAttr && scrollAttr.focusId) {
focusElement = protyle.wysiwyg.element.querySelector(`[data-node-id="${scrollAttr.focusId}"]`);
@ -460,6 +464,9 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr
}
});
}
if (!focusElement && protyle.block.id === protyle.block.rootID) {
focusElement = protyle.title.editElement;
}
if (protyle.block.mode === 4) {
preventScroll(protyle);
focusElement = protyle.wysiwyg.element.lastElementChild;
@ -491,7 +498,7 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr
protyle.observerLoad?.disconnect();
if (action.includes(Constants.CB_GET_FOCUS) || action.includes(Constants.CB_GET_SCROLL) || action.includes(Constants.CB_GET_HL) || action.includes(Constants.CB_GET_FOCUSFIRST)) {
if (!hasScrollTop) {
scrollCenter(protyle, focusElement);
scrollCenter(protyle, focusElement, scrollPosition);
}
} else {
return;
@ -503,7 +510,7 @@ const focusElementById = (protyle: IProtyle, action: string[], scrollAttr?: IScr
}
if (action.includes(Constants.CB_GET_FOCUS) || action.includes(Constants.CB_GET_HL) || action.includes(Constants.CB_GET_FOCUSFIRST)) {
if (!hasScrollTop) {
scrollCenter(protyle, focusElement);
scrollCenter(protyle, focusElement, scrollPosition);
}
}
});

View file

@ -14,6 +14,7 @@ import {hideElements} from "../ui/hideElements";
import {avRender} from "../render/av/render";
import {cellScrollIntoView, getCellText} from "../render/av/cell";
import {getContenteditableElement} from "../wysiwyg/getBlock";
import {clearBlockElement} from "./clear";
export const getTextStar = (blockElement: HTMLElement) => {
const dataType = blockElement.dataset.type;
@ -407,10 +408,7 @@ export const paste = async (protyle: IProtyle, event: (ClipboardEvent | DragEven
tempElement.querySelectorAll("[data-node-id]").forEach((e) => {
const newId = Lute.NewNodeID();
e.setAttribute("data-node-id", newId);
e.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
e.classList.remove("protyle-wysiwyg--select", "protyle-wysiwyg--hl");
e.setAttribute("updated", newId.split("-")[0]);
e.removeAttribute("refcount");
clearBlockElement(e);
isBlock = true;
});
if (nodeElement.classList.contains("table")) {

View file

@ -15,6 +15,7 @@ import {processClonePHElement} from "../render/util";
import {copyTextByType} from "../toolbar/util";
import {hasClosestByTag, hasTopClosestByClassName} from "../util/hasClosest";
import {removeEmbed} from "./removeEmbed";
import {clearBlockElement} from "../util/clear";
export const commonHotkey = (protyle: IProtyle, event: KeyboardEvent, nodeElement?: HTMLElement) => {
if (matchHotKey(window.siyuan.config.keymap.editor.general.netImg2LocalAsset.custom, event)) {
@ -313,19 +314,14 @@ export const duplicateBlock = async (nodeElements: Element[], protyle: IProtyle)
focusElement = tempElement;
}
tempElement.setAttribute("data-node-id", newId);
tempElement.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
tempElement.classList.remove("protyle-wysiwyg--hl");
tempElement.setAttribute("updated", newId.split("-")[0]);
tempElement.removeAttribute("refcount");
tempElement.lastElementChild.querySelector(".protyle-attr--refcount")?.remove();
clearBlockElement(tempElement);
tempElement.classList.add("protyle-wysiwyg--select");
tempElement.querySelectorAll("[data-node-id]").forEach(childItem => {
const subNewId = Lute.NewNodeID();
childItem.setAttribute("data-node-id", subNewId);
childItem.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
childItem.classList.remove("protyle-wysiwyg--hl");
childItem.setAttribute("updated", subNewId.split("-")[0]);
childItem.removeAttribute("refcount");
childItem.lastElementChild.querySelector(".protyle-attr--refcount")?.remove();
clearBlockElement(childItem);
});
if (typeof starIndex === "number") {
const orderIndex = starIndex + index + 1;
@ -354,13 +350,11 @@ export const duplicateBlock = async (nodeElements: Element[], protyle: IProtyle)
}
childItem.querySelectorAll("[data-node-id]").forEach(subItem => {
subItem.setAttribute("data-node-id", Lute.NewNodeID());
subItem.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
subItem.removeAttribute("refcount");
clearBlockElement(subItem);
});
const newChildId = Lute.NewNodeID();
childItem.setAttribute("data-node-id", newChildId);
childItem.removeAttribute(Constants.CUSTOM_RIFF_DECKS);
childItem.removeAttribute("refcount");
clearBlockElement(childItem);
doOperations.push({
context: {
ignoreProcess: "true"

View file

@ -101,6 +101,16 @@ import { hideTooltip } from "../../dialog/tooltip";
import { openGalleryItemMenu } from "../render/av/gallery/util";
import { clearSelect } from "../util/clearSelect";
import { chartRender } from "../render/chartRender";
import {openEmojiPanel, unicode2Emoji} from "../../emoji";
import {openLink} from "../../editor/openLink";
import {mathRender} from "../render/mathRender";
import {editAssetItem} from "../render/av/asset";
import {img3115} from "../../boot/compatibleVersion";
import {globalClickHideMenu} from "../../boot/globalEvent/click";
import {hideTooltip} from "../../dialog/tooltip";
import {openGalleryItemMenu} from "../render/av/gallery/util";
import {clearSelect} from "../util/clear";
import {chartRender} from "../render/chartRender";
export class WYSIWYG {
public lastHTMLs: { [key: string]: string } = {};
@ -152,7 +162,7 @@ export class WYSIWYG {
}
}
ialKeys.forEach((key: string) => {
if (!["title-img", "title", "updated", "icon", "id", "type", "class", "spellcheck", "contenteditable", "data-doc-type", "style", "data-realwidth", "data-readonly"].includes(key)) {
if (!["title-img", "title", "updated", "icon", "id", "type", "class", "spellcheck", "contenteditable", "data-doc-type", "style", "data-realwidth", "data-readonly", "av-names"].includes(key)) {
this.element.setAttribute(key, ial[key]);
}
});
@ -655,8 +665,13 @@ export class WYSIWYG {
}
if (isOnlyMeta(event) && !event.shiftKey && !event.altKey) {
let ctrlElement = nodeElement;
if (!hasSelectClassElement && galleryItemElement) {
galleryItemElement.classList.toggle("av__gallery-item--select");
const rowElement = hasClosestByClassName(target, "av__row");
if (!hasSelectClassElement && (galleryItemElement || (rowElement && !rowElement.classList.contains("av__row--header")))) {
if (galleryItemElement) {
galleryItemElement.classList.toggle("av__gallery-item--select");
} else if (rowElement) {
selectRow(rowElement.querySelector(".av__firstcol"), "toggle");
}
} else if (ctrlElement) {
const embedBlockElement = isInEmbedBlock(ctrlElement);
if (embedBlockElement) {
@ -917,15 +932,20 @@ export class WYSIWYG {
};
return false;
}
// 图片、iframe、video 缩放
// 图片、iframe、video、挂件缩放
if (!protyle.disabled && target.classList.contains("protyle-action__drag")) {
if (!nodeElement) {
return;
}
let isCenter = true;
if (["NodeIFrame", "NodeWidget", "NodeVideo"].includes(nodeElement.getAttribute("data-type"))) {
if ("NodeVideo" === nodeElement.dataset.type) {
nodeElement.classList.add("iframe--drag");
if (nodeElement.style.textAlign === "left" || nodeElement.style.textAlign === "right") {
if (["left", "right", ""].includes(nodeElement.style.textAlign)) {
isCenter = false;
}
} else if (["NodeIFrame", "NodeWidget"].includes(nodeElement.dataset.type)) {
nodeElement.classList.add("iframe--drag");
if (!nodeElement.style.margin) {
isCenter = false;
}
} else if (target.parentElement.parentElement.getAttribute("data-type") === "img") {
@ -943,6 +963,11 @@ export class WYSIWYG {
if (dragElement.tagName === "IMG") {
img3115(imgElement);
}
// 3.4.1 以前历史数据兼容
if (dragElement.tagName === "IFRAME") {
dragElement.style.height = "";
dragElement.style.width = "";
}
documentSelf.onmousemove = (moveEvent: MouseEvent) => {
if (dragElement.tagName === "IMG") {
dragElement.style.height = "";
@ -951,13 +976,19 @@ export class WYSIWYG {
const multiple = ((dragElement.tagName === "IMG" && !imgElement.style.minWidth && nodeElement.style.textAlign !== "center") || !isCenter) ? 1 : 2;
if (dragElement.tagName === "IMG") {
dragElement.parentElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * multiple) + "px";
} else if (dragElement.tagName === "IFRAME") {
nodeElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * multiple) + "px";
} else {
dragElement.style.width = Math.max(17, dragWidth + (moveEvent.clientX - x) * multiple) + "px";
}
}
if (dragElement.tagName !== "IMG") {
if (moveEvent.clientY > y - dragHeight + 8 && moveEvent.clientY < mostBottom) {
dragElement.style.height = (dragHeight + (moveEvent.clientY - y)) + "px";
if (dragElement.tagName === "IFRAME") {
nodeElement.style.height = (dragHeight + (moveEvent.clientY - y)) + "px";
} else {
dragElement.style.height = (dragHeight + (moveEvent.clientY - y)) + "px";
}
}
}
};

View file

@ -763,6 +763,16 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => {
}
}
}
if (selectText === "" && event.key === "ArrowLeft" && position.start === 1 &&
range.startContainer.textContent === Constants.ZWSP) {
range.setStart(range.startContainer, 0);
range.collapse(true);
}
if (selectText === "" && event.key === "ArrowRight" && position.start === 0 &&
range.startContainer.textContent === Constants.ZWSP) {
range.setStart(range.startContainer, 1);
range.collapse(true);
}
return;
}

View file

@ -276,7 +276,7 @@ export const breakList = (protyle: IProtyle, blockElement: Element, range: Range
action: "delete"
});
Array.from(listItemElement.children).reverse().forEach((item) => {
Array.from(listItemElement.children).reverse().forEach((item, index) => {
if (!item.classList.contains("protyle-action") && !item.classList.contains("protyle-attr")) {
doOperations.push({
id: item.getAttribute("data-node-id"),
@ -286,7 +286,8 @@ export const breakList = (protyle: IProtyle, blockElement: Element, range: Range
undoOperations.push({
id: item.getAttribute("data-node-id"),
action: "move",
parentID: listItemId
parentID: listItemId,
data: index === listItemElement.childElementCount - 2 ? "focus" : null
});
listItemElement.parentElement.after(item);
}

View file

@ -611,13 +611,14 @@ export const onTransaction = (protyle: IProtyle, operation: IOperation, isUndo:
data.new.style += ";animation:addCard 450ms linear";
}
Object.keys(data.new).forEach(key => {
if ("id" === key) {
if ("id" === key || "av-names" === key) {
// 设置属性以后不应该给块元素添加 id 属性 No longer add the `id` attribute to block elements after setting the attribute https://github.com/siyuan-note/siyuan/issues/15327
// av-names 属性仅用于生成角标,不添加到元素
return;
}
item.setAttribute(key, data.new[key]);
if (key === Constants.CUSTOM_RIFF_DECKS && data.new[Constants.CUSTOM_RIFF_DECKS] !== data.old[Constants.CUSTOM_RIFF_DECKS]) {
if (key === Constants.CUSTOM_RIFF_DECKS && key !== data.old[Constants.CUSTOM_RIFF_DECKS]) {
item.style.animation = "addCard 450ms linear";
setTimeout(() => {
if (item.parentElement) {

View file

@ -815,13 +815,15 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
} else {
if (event.altKey) {
const id = target.getAttribute("data-node-id");
checkFold(id, (zoomIn, action) => {
checkFold(id, (zoomIn) => {
openFileById({
app,
id,
action,
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] :
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL],
zoomIn,
position: "right"
position: "right",
scrollPosition: "center"
});
if (closeCB) {
closeCB();
@ -855,12 +857,14 @@ export const genSearch = (app: App, config: Config.IUILayoutTabSearchConfig, ele
/// #endif
} else {
const id = target.getAttribute("data-node-id");
checkFold(id, (zoomIn, action) => {
checkFold(id, (zoomIn) => {
openFileById({
app,
id,
action,
zoomIn
action: zoomIn ? [Constants.CB_GET_FOCUS, Constants.CB_GET_ALL, Constants.CB_GET_HL] :
[Constants.CB_GET_FOCUS, Constants.CB_GET_CONTEXT, Constants.CB_GET_HL],
zoomIn,
scrollPosition: "center"
});
if (closeCB) {
closeCB();

View file

@ -228,6 +228,7 @@ interface Window {
changeStatusBar: { postMessage: (url: string) => void }
setClipboard: { postMessage: (url: string) => void }
purchase: { postMessage: (url: string) => void }
print: { postMessage: (html: string) => void }
}
};
htmlToImage: {
@ -248,7 +249,7 @@ interface Window {
readHTMLClipboard(): string
getBlockURL(): string
hideKeyboard(): void
print(html: string): void
print(title: string, html: string): void
getScreenWidthPx(): number
};
JSHarmony: {
@ -260,7 +261,7 @@ interface Window {
readClipboard(): string
readHTMLClipboard(): string
returnDesktop(): void
print(html: string): void
print(title: string, html: string): void
getScreenWidthPx(): number
};
@ -662,6 +663,7 @@ interface IOpenFileOptions {
data: any,
}) => import("../layout/Model").Model, // plugin 0.8.3 历史兼容
}
scrollPosition?: ScrollLogicalPosition,
assetPath?: string, // asset 必填
fileName?: string, // file 必填
rootIcon?: string, // 文档图标

View file

@ -446,6 +446,7 @@ interface IProtyleOptions {
expand: boolean
}[],
action?: TProtyleAction[],
scrollPosition?: ScrollLogicalPosition,
mode?: TEditorMode,
blockId?: string
rootId?: string

View file

@ -6,9 +6,7 @@ import {getAllModels} from "../layout/getAll";
import {exportLayout} from "../layout/util";
/// #endif
import {fetchPost} from "./fetch";
import {appearance} from "../config/appearance";
import {isInAndroid, isInHarmony, isInIOS, isIPad, isIPhone, isMac, isWin11} from "../protyle/util/compatibility";
import {reloadOtherWindow} from "../dialog/processSystem";
export const loadAssets = (data: Config.IAppearance) => {
const htmlElement = document.getElementsByTagName("html")[0];
@ -357,42 +355,7 @@ export const setMode = (modeElementValue: number) => {
fetchPost("/api/setting/setAppearance", Object.assign({}, window.siyuan.config.appearance, {
mode,
modeOS: modeElementValue === 2,
}), async response => {
if (response.data.mode !== window.siyuan.config.appearance.mode ||
(response.data.mode === window.siyuan.config.appearance.mode && (
(response.data.mode === 0 && window.siyuan.config.appearance.themeLight !== response.data.themeLight) ||
(response.data.mode === 1 && window.siyuan.config.appearance.themeDark !== response.data.themeDark))
)) {
reloadOtherWindow();
}
if (window.siyuan.config.appearance.themeJS) {
if (response.data.mode !== window.siyuan.config.appearance.mode ||
(response.data.mode === window.siyuan.config.appearance.mode && (
(response.data.mode === 0 && window.siyuan.config.appearance.themeLight !== response.data.themeLight) ||
(response.data.mode === 1 && window.siyuan.config.appearance.themeDark !== response.data.themeDark))
)
) {
if (window.destroyTheme) {
try {
await window.destroyTheme();
window.destroyTheme = undefined;
document.getElementById("themeScript").remove();
} catch (e) {
console.error("destroyTheme error: " + e);
}
} else {
exportLayout({
errorExit: false,
cb() {
window.location.reload();
},
});
return;
}
}
}
appearance.onSetAppearance(response.data);
});
}));
/// #endif
};

View file

@ -27,6 +27,8 @@ import {loadPlugins, reloadPlugin} from "../plugin/loader";
import {hideAllElements} from "../protyle/ui/hideElements";
import {reloadEmoji} from "../emoji";
import {updateControlAlt} from "../protyle/util/hotKey";
import {updateAppearance} from "../config/util/updateAppearance";
import {renderSnippet} from "../config/util/snippets";
class App {
public plugins: import("../plugin").Plugin[] = [];
@ -56,6 +58,13 @@ class App {
});
if (data) {
switch (data.cmd) {
case "setAppearance":
updateAppearance(data.data);
break;
case "setSnippet":
window.siyuan.config.snippet = data.data;
renderSnippet();
break;
case "setDefRefCount":
setDefRefCount(data.data);
break;

File diff suppressed because one or more lines are too long

View file

@ -79,6 +79,7 @@ func setConfSnippet(c *gin.Context) {
model.Conf.Save()
ret.Data = snippet
util.BroadcastByType("main", "setSnippet", 0, "", snippet)
}
func addVirtualBlockRefExclude(c *gin.Context) {
@ -548,6 +549,7 @@ func setAppearance(c *gin.Context) {
}
ret.Data = model.Conf.Appearance
util.BroadcastByType("main", "setAppearance", 0, "", model.Conf.Appearance)
}
func setPublish(c *gin.Context) {

View file

@ -745,6 +745,13 @@ func (av *AttributeView) Clone() (ret *AttributeView) {
oldKeyIDs = append(oldKeyIDs, kv.Key.ID)
kv.Key.ID = newID
kv.Values = []*Value{}
if KeyTypeRelation == kv.Key.Type {
// 断开关联
kv.Key.Relation.IsTwoWay = false
kv.Key.Relation.AvID = ""
kv.Key.Relation.BackKeyID = ""
}
}
oldKeyIDs = gulu.Str.RemoveDuplicatedElem(oldKeyIDs)

View file

@ -1,19 +1,19 @@
module github.com/siyuan-note/siyuan/kernel
go 1.24.4
go 1.25.4
require (
code.sajari.com/docconv v1.3.8
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.20251107023402-569f52804e3b
github.com/88250/lute v1.7.7-0.20251118033948-b406b36288e1
github.com/88250/gulu v1.2.3-0.20251119142510-7b1583ab4aa0
github.com/88250/lute v1.7.7-0.20251123021544-94b4c1bd297c
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4
github.com/ConradIrwin/font v0.2.1
github.com/Masterminds/sprig/v3 v3.3.0
github.com/PuerkitoBio/goquery v1.10.3
github.com/PuerkitoBio/goquery v1.11.0
github.com/Xuanwo/go-locale v1.1.3
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef
@ -58,11 +58,11 @@ require (
github.com/sashabaranov/go-openai v1.41.2
github.com/shirou/gopsutil/v4 v4.25.10
github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3
github.com/siyuan-note/dejavu v0.0.0-20251114012636-adbd1a1e802f
github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec
github.com/siyuan-note/dejavu v0.0.0-20251124044105-c3bb4f6c9658
github.com/siyuan-note/encryption v0.0.0-20251120032857-3ddc3c2cc49f
github.com/siyuan-note/eventbus v0.0.0-20240627125516-396fdb0f0f97
github.com/siyuan-note/filelock v0.0.0-20251107023958-207cad31f0dd
github.com/siyuan-note/httpclient v0.0.0-20251114005335-cf847d29b3e9
github.com/siyuan-note/httpclient v0.0.0-20251119144307-63b815d7d198
github.com/siyuan-note/logging v0.0.0-20251107023700-cd4339891032
github.com/siyuan-note/riff v0.0.0-20251022131846-228528e70754
github.com/spf13/cast v1.10.0
@ -94,23 +94,23 @@ require (
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2 v1.39.6 // indirect
github.com/aws/aws-sdk-go-v2 v1.39.5 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.31.20 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.18.24 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 // indirect
github.com/aws/aws-sdk-go-v2/config v1.31.16 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.18.20 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.12 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.13 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.12 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.7 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.40.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.12 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.12 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.30.0 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.39.0 // indirect
github.com/aws/smithy-go v1.23.2 // indirect
github.com/bytedance/gopkg v0.1.3 // indirect
github.com/bytedance/sonic v1.14.1 // indirect
@ -183,7 +183,7 @@ require (
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/arch v0.22.0 // indirect
golang.org/x/crypto v0.44.0 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/sync v0.18.0 // indirect
golang.org/x/tools v0.38.0 // indirect
google.golang.org/protobuf v1.36.10 // indirect

View file

@ -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.20251107023402-569f52804e3b h1:b6Rp0KiGIkEs5O5skKFeUngQ2grxRWZ4um2Xn01ZFzs=
github.com/88250/gulu v1.2.3-0.20251107023402-569f52804e3b/go.mod h1:Wz/JGuHPqxmvGSBtXrXNWklMxNdCADIrL5+VjSgCZyo=
github.com/88250/lute v1.7.7-0.20251118033948-b406b36288e1 h1:bSoqJjIgMsOxfEU4k8oBozbIMLjHjuHyl5s6gCKegvM=
github.com/88250/lute v1.7.7-0.20251118033948-b406b36288e1/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o=
github.com/88250/gulu v1.2.3-0.20251119142510-7b1583ab4aa0 h1:ip0IQCJCLtJEDHil+2XSnh3NP39i98SYV5qhWoUeMnA=
github.com/88250/gulu v1.2.3-0.20251119142510-7b1583ab4aa0/go.mod h1:IQ5dXW9CjVmx6B7OfK1Y4ZBKTPMe9q1AkVoLGGzRbS8=
github.com/88250/lute v1.7.7-0.20251123021544-94b4c1bd297c h1:BdeFrAfvftow7HIfVe10BrIhxUaVWKgT+TnbmV2TK2M=
github.com/88250/lute v1.7.7-0.20251123021544-94b4c1bd297c/go.mod h1:WYyUw//5yVw9BJnoVjx7rI/3szsISxNZCYGOqTIrV0o=
github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46 h1:Bq1JsDfVbHKUxNL/B2JXd8cC/1h6aFjrlXpGycnh0Hk=
github.com/88250/pdfcpu v0.3.14-0.20250424122812-f10e8d9d8d46/go.mod h1:fVfOloBzs2+W2VJCCbq60XIxc3yJHAZ0Gahv1oO0gyI=
github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=
@ -36,8 +36,8 @@ github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lpr
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/PuerkitoBio/goquery v1.4.1/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA=
github.com/PuerkitoBio/goquery v1.10.3 h1:pFYcNSqHxBD06Fpj/KsbStFRsgRATgnf3LeXiUkhzPo=
github.com/PuerkitoBio/goquery v1.10.3/go.mod h1:tMUX0zDMHXYlAQk6p35XxQMqMweEKB7iK7iLNd4RH4Y=
github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw=
github.com/PuerkitoBio/goquery v1.11.0/go.mod h1:wQHgxUOU3JGuj3oD/QFfxUdlzW6xPHfqyHre6VMY4DQ=
github.com/Xuanwo/go-locale v1.1.3 h1:EWZZJJt5rqPHHbqPRH1zFCn5D7xHjjebODctA4aUO3A=
github.com/Xuanwo/go-locale v1.1.3/go.mod h1:REn+F/c+AtGSWYACBSYZgl23AP+0lfQC+SEFPN+hj30=
github.com/advancedlogic/GoOse v0.0.0-20231203033844-ae6b36caf275 h1:Kuhf+w+ilOGoXaR4O4nZ6Dp+ZS83LdANUjwyMXsPGX4=
@ -56,40 +56,40 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef h1:2JGTg6JapxP9/R33ZaagQtAM4EkkSYnIAlOG5EI8gkM=
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII=
github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk=
github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE=
github.com/aws/aws-sdk-go-v2 v1.39.5 h1:e/SXuia3rkFtapghJROrydtQpfQaaUgd1cUvyO1mp2w=
github.com/aws/aws-sdk-go-v2 v1.39.5/go.mod h1:yWSxrnioGUZ4WVv9TgMrNUeLV3PFESn/v+6T/Su8gnM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3 h1:DHctwEM8P8iTXFxC/QK0MRjwEpWQeM9yzidCRjldUz0=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.3/go.mod h1:xdCzcZEtnSTKVDOmUZs4l/j3pSV6rpo1WXl5ugNsL8Y=
github.com/aws/aws-sdk-go-v2/config v1.31.20 h1:/jWF4Wu90EhKCgjTdy1DGxcbcbNrjfBHvksEL79tfQc=
github.com/aws/aws-sdk-go-v2/config v1.31.20/go.mod h1:95Hh1Tc5VYKL9NJ7tAkDcqeKt+MCXQB1hQZaRdJIZE0=
github.com/aws/aws-sdk-go-v2/credentials v1.18.24 h1:iJ2FmPT35EaIB0+kMa6TnQ+PwG5A1prEdAw+PsMzfHg=
github.com/aws/aws-sdk-go-v2/credentials v1.18.24/go.mod h1:U91+DrfjAiXPDEGYhh/x29o4p0qHX5HDqG7y5VViv64=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 h1:T1brd5dR3/fzNFAQch/iBKeX07/ffu/cLu+q+RuzEWk=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13/go.mod h1:Peg/GBAQ6JDt+RoBf4meB1wylmAipb7Kg2ZFakZTlwk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 h1:a+8/MLcWlIxo1lF9xaGt3J/u3yOZx+CdSveSNwjhD40=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13/go.mod h1:oGnKwIYZ4XttyU2JWxFrwvhF6YKiK/9/wmE3v3Iu9K8=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 h1:HBSI2kDkMdWz4ZM7FjwE7e/pWDEZ+nR95x8Ztet1ooY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13/go.mod h1:YE94ZoDArI7awZqJzBAZ3PDD2zSfuP7w6P2knOzIn8M=
github.com/aws/aws-sdk-go-v2/config v1.31.16 h1:E4Tz+tJiPc7kGnXwIfCyUj6xHJNpENlY11oKpRTgsjc=
github.com/aws/aws-sdk-go-v2/config v1.31.16/go.mod h1:2S9hBElpCyGMifv14WxQ7EfPumgoeCPZUpuPX8VtW34=
github.com/aws/aws-sdk-go-v2/credentials v1.18.20 h1:KFndAnHd9NUuzikHjQ8D5CfFVO+bgELkmcGY8yAw98Q=
github.com/aws/aws-sdk-go-v2/credentials v1.18.20/go.mod h1:9mCi28a+fmBHSQ0UM79omkz6JtN+PEsvLrnG36uoUv0=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.12 h1:VO3FIM2TDbm0kqp6sFNR0PbioXJb/HzCDW6NtIZpIWE=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.12/go.mod h1:6C39gB8kg82tx3r72muZSrNhHia9rjGkX7ORaS2GKNE=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.12 h1:p/9flfXdoAnwJnuW9xHEAFY22R3A6skYkW19JFF9F+8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.12/go.mod h1:ZTLHakoVCTtW8AaLGSwJ3LXqHD9uQKnOcv1TrpO6u2k=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.12 h1:2lTWFvRcnWFFLzHWmtddu5MTchc5Oj2OOey++99tPZ0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.12/go.mod h1:hI92pK+ho8HVcWMHKHrK3Uml4pfG7wvL86FzO0LVtQQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.13 h1:eg/WYAa12vqTphzIdWMzqYRVKKnCboVPRlvaybNCqPA=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.13/go.mod h1:/FDdxWhz1486obGrKKC1HONd7krpk38LBt+dutLcN9k=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.12 h1:itu4KHu8JK/N6NcLIISlf3LL1LccMqruLUXZ9y7yBZw=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.12/go.mod h1:i+6vTU3xziikTY3vcox23X8pPGW5X3wVgd1VZ7ha+x8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.4 h1:NvMjwvv8hpGUILarKw7Z4Q0w1H9anXKsesMxtw++MA4=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.4/go.mod h1:455WPHSwaGj2waRSpQp7TsnpOnBfw8iDfPfbwl7KPJE=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 h1:kDqdFvMY4AtKoACfzIGD8A0+hbT41KTKF//gq7jITfM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13/go.mod h1:lmKuogqSU3HzQCwZ9ZtcqOc5XGMqtDK7OIc2+DxiUEg=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13 h1:zhBJXdhWIFZ1acfDYIhu4+LCzdUS2Vbcum7D01dXlHQ=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.13/go.mod h1:JaaOeCE368qn2Hzi3sEzY6FgAZVCIYcC2nwbro2QCh8=
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.2 h1:DhdbtDl4FdNlj31+xiRXANxEE+eC7n8JQz+/ilwQ8Uc=
github.com/aws/aws-sdk-go-v2/service/s3 v1.90.2/go.mod h1:+wArOOrcHUevqdto9k1tKOF5++YTe9JEcPSc9Tx2ZSw=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.3 h1:NjShtS1t8r5LUfFVtFeI8xLAHQNTa7UI0VawXlrBMFQ=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.3/go.mod h1:fKvyjJcz63iL/ftA6RaM8sRCtN4r4zl4tjL3qw5ec7k=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.7 h1:gTsnx0xXNQ6SBbymoDvcoRHL+q4l/dAFsQuKfDWSaGc=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.7/go.mod h1:klO+ejMvYsB4QATfEOIXk8WAEwN4N0aBfJpvC+5SZBo=
github.com/aws/aws-sdk-go-v2/service/sts v1.40.2 h1:HK5ON3KmQV2HcAunnx4sKLB9aPf3gKGwVAf7xnx0QT0=
github.com/aws/aws-sdk-go-v2/service/sts v1.40.2/go.mod h1:E19xDjpzPZC7LS2knI9E6BaRFDK43Eul7vd6rSq2HWk=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.3 h1:NEe7FaViguRQEm8zl8Ay/kC/QRsMtWUiCGZajQIsLdc=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.3/go.mod h1:JLuCKu5VfiLBBBl/5IzZILU7rxS0koQpHzMOCzycOJU=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.12 h1:MM8imH7NZ0ovIVX7D2RxfMDv7Jt9OiUXkcQ+GqywA7M=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.12/go.mod h1:gf4OGwdNkbEsb7elw2Sy76odfhwNktWII3WgvQgQQ6w=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.12 h1:R3uW0iKl8rgNEXNjVGliW/oMEh9fO/LlUEV8RvIFr1I=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.12/go.mod h1:XEttbEr5yqsw8ebi7vlDoGJJjMXRez4/s9pibpJyL5s=
github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1 h1:Dq82AV+Qxpno/fG162eAhnD8d48t9S+GZCfz7yv1VeA=
github.com/aws/aws-sdk-go-v2/service/s3 v1.89.1/go.mod h1:MbKLznDKpf7PnSonNRUVYZzfP0CeLkRIUexeblgKcU4=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.0 h1:xHXvxst78wBpJFgDW07xllOx0IAzbryrSdM4nMVQ4Dw=
github.com/aws/aws-sdk-go-v2/service/sso v1.30.0/go.mod h1:/e8m+AO6HNPPqMyfKRtzZ9+mBF5/x1Wk8QiDva4m07I=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.4 h1:tBw2Qhf0kj4ZwtsVpDiVRU3zKLvjvjgIjHMKirxXg8M=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.4/go.mod h1:Deq4B7sRM6Awq/xyOBlxBdgW8/Z926KYNNaGMW2lrkA=
github.com/aws/aws-sdk-go-v2/service/sts v1.39.0 h1:C+BRMnasSYFcgDw8o9H5hzehKzXyAb9GY5v/8bP9DUY=
github.com/aws/aws-sdk-go-v2/service/sts v1.39.0/go.mod h1:4EjU+4mIx6+JqKQkruye+CaigV7alL3thVPfDd9VlMs=
github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM=
github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
@ -374,16 +374,16 @@ github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d/go.mod h1:05Ut
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3 h1:EH063L0HD1f82DvddurUmEXS0obXypv8pQrcaC/zNgI=
github.com/siyuan-note/dataparser v0.0.0-20250804100744-b41253b236f3/go.mod h1:8lb+SsWAPQblGbjmwEBsBdJszMCcLeECtB95fv6mReg=
github.com/siyuan-note/dejavu v0.0.0-20251114012636-adbd1a1e802f h1:bKCQWFAc8KSCMZfUEMD8DBURruqrVU2aAhl7ox/GxLc=
github.com/siyuan-note/dejavu v0.0.0-20251114012636-adbd1a1e802f/go.mod h1:e+tA+MFN24jnQH4OBUEUmg9Wmnaiwly4eCWC5ZxYAR0=
github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec h1:D8Sjwa+7WxP3XrIBscT4PxBZZddZ83/O+5nX1sq6g6g=
github.com/siyuan-note/encryption v0.0.0-20250326023622-24a67e6956ec/go.mod h1:6iAxXPOOAG3+M4bCiKQZTQ+n4gSUx/OyHhsP57dJlS8=
github.com/siyuan-note/dejavu v0.0.0-20251124044105-c3bb4f6c9658 h1:7ao04pWUpRucgA+w+X8BBFIbxGHIq06K3V7St9qX9ns=
github.com/siyuan-note/dejavu v0.0.0-20251124044105-c3bb4f6c9658/go.mod h1:8B0hXnplhO+Xvxm1i25Odu9L8rWjm4VGM1o7N7Catzs=
github.com/siyuan-note/encryption v0.0.0-20251120032857-3ddc3c2cc49f h1:HSgJKIAMgokJDAvBBfRj47SzRSm6mNGssY0Wv7rcEtg=
github.com/siyuan-note/encryption v0.0.0-20251120032857-3ddc3c2cc49f/go.mod h1:JE3S9VuJqTggyfhjesNDuqvqrRvwG3IctFjXXchLx1M=
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-20251107023958-207cad31f0dd h1:7Rr+wH2hy/goTMe5EAZHjpfEudZZXVVaZOkhs/xzX+I=
github.com/siyuan-note/filelock v0.0.0-20251107023958-207cad31f0dd/go.mod h1:jFSEENJoE+SRZ7xtSpiflL3RMfnxE6CAJFUfBuuGs1A=
github.com/siyuan-note/httpclient v0.0.0-20251114005335-cf847d29b3e9 h1:chfAacuGlcrY7YfubIOIi80wKurczgPftxmnoZxHhn0=
github.com/siyuan-note/httpclient v0.0.0-20251114005335-cf847d29b3e9/go.mod h1:w8ZKhKvcOr6lXsfxGmXQQTcIlVYWKhesB5IaXC+3OkA=
github.com/siyuan-note/httpclient v0.0.0-20251119144307-63b815d7d198 h1:NCFtk65n+a6oo+nIXnYPx3jCgs3O2uvvihnD7aRy/ZE=
github.com/siyuan-note/httpclient v0.0.0-20251119144307-63b815d7d198/go.mod h1:w8ZKhKvcOr6lXsfxGmXQQTcIlVYWKhesB5IaXC+3OkA=
github.com/siyuan-note/logging v0.0.0-20251107023700-cd4339891032 h1:z1r9ZhSTISDom1lvqKuiykfI7YtPCIELABj8onc0n3A=
github.com/siyuan-note/logging v0.0.0-20251107023700-cd4339891032/go.mod h1:UVFePdmdasN+fLDEYFr2X734G2AIJb6nYS9WcWK5740=
github.com/siyuan-note/riff v0.0.0-20251022131846-228528e70754 h1:6QYpy7s5HlRSge09TyM/mT0vz1RDcWYZdkxEh7hmbH4=
@ -459,8 +459,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
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.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q=
golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=

View file

@ -1314,6 +1314,10 @@ func GetAttributeViewPrimaryKeyValues(avID, keyword string, page, pageSize int)
}
keyValues.Values = values
sort.Slice(keyValues.Values, func(i, j int) bool {
return keyValues.Values[i].Block.Updated > keyValues.Values[j].Block.Updated
})
if 1 > pageSize {
pageSize = 16
}
@ -1323,10 +1327,6 @@ func GetAttributeViewPrimaryKeyValues(avID, keyword string, page, pageSize int)
end = len(keyValues.Values)
}
keyValues.Values = keyValues.Values[start:end]
sort.Slice(keyValues.Values, func(i, j int) bool {
return keyValues.Values[i].Block.Updated > keyValues.Values[j].Block.Updated
})
return
}
@ -2970,6 +2970,7 @@ func (tx *Transaction) setAttributeViewName(operation *Operation) (err error) {
oldAttrs := parse.IAL2Map(node.KramdownIAL)
node.SetIALAttr(av.NodeAttrViewNames, avNames)
pushBroadcastAttrTransactions(oldAttrs, node)
node.RemoveIALAttr(av.NodeAttrViewNames)
}
return
}
@ -3561,6 +3562,7 @@ func removeNodeAvID(node *ast.Node, avID string, tx *Transaction, tree *parse.Tr
node.RemoveIALAttr("custom-hidden")
}
var avNames string
if avs := attrs[av.NodeAttrNameAvs]; "" != avs {
avIDs := strings.Split(avs, ",")
avIDs = gulu.Str.RemoveElem(avIDs, avID)
@ -3577,7 +3579,7 @@ func removeNodeAvID(node *ast.Node, avID string, tx *Transaction, tree *parse.Tr
} else {
attrs[av.NodeAttrNameAvs] = strings.Join(avIDs, ",")
node.SetIALAttr(av.NodeAttrNameAvs, strings.Join(avIDs, ","))
avNames := getAvNames(node.IALAttr(av.NodeAttrNameAvs))
avNames = getAvNames(node.IALAttr(av.NodeAttrNameAvs))
attrs[av.NodeAttrViewNames] = avNames
}
}
@ -3591,6 +3593,9 @@ func removeNodeAvID(node *ast.Node, avID string, tx *Transaction, tree *parse.Tr
return
}
}
if "" != avNames {
node.RemoveIALAttr(av.NodeAttrViewNames)
}
return
}
@ -4843,14 +4848,10 @@ func updateAttributeViewValue(tx *Transaction, attrView *av.AttributeView, keyID
if av.KeyTypeRelation == val.Type {
// 关联字段得 content 是自动渲染的,所以不需要保存
val.Relation.Contents = nil
// 去重
val.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(val.Relation.BlockIDs)
// 计算关联变更模式
if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) {
relationChangeMode = 0
} else {
if !slices.Equal(oldRelationBlockIDs, val.Relation.BlockIDs) {
if len(oldRelationBlockIDs) > len(val.Relation.BlockIDs) {
relationChangeMode = 2
} else {
@ -5050,6 +5051,9 @@ func unbindBlockAv(tx *Transaction, avID, nodeID string) {
logging.LogWarnf("set node [%s] attrs failed: %s", nodeID, err)
return
}
if "" != avNames {
node.RemoveIALAttr(av.NodeAttrViewNames)
}
return
}
@ -5089,6 +5093,9 @@ func bindBlockAv0(tx *Transaction, avID string, node *ast.Node, tree *parse.Tree
logging.LogWarnf("set node [%s] attrs failed: %s", node.ID, err)
return
}
if "" != avNames {
node.RemoveIALAttr(av.NodeAttrViewNames)
}
return
}
@ -5521,6 +5528,9 @@ func updateBoundBlockAvsAttribute(avIDs []string) {
}
cache.PutBlockIAL(node.ID, parse.IAL2Map(node.KramdownIAL))
pushBroadcastAttrTransactions(oldAttrs, node)
if "" != avNames {
node.RemoveIALAttr(av.NodeAttrViewNames)
}
}
}

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