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

This commit is contained in:
Vanessa 2024-11-01 08:34:18 +08:00
commit 3eff91d30e
7 changed files with 76 additions and 51 deletions

View file

@ -42,6 +42,7 @@
* [安装包](#安装包)
* [Docker 部署](#docker-部署)
* [Unraid 部署](#unraid-部署)
* [宝塔面板 部署](#宝塔面板部署)
* [内部预览版](#内部预览版)
* [🏘️ 社区](#-社区)
* [🛠️ 开发指南](#-开发指南)
@ -300,6 +301,38 @@ Publish parameters: --accessAuthCode=******(访问授权码)
</details>
### 宝塔面板部署
<details>
<summary>宝塔面板 部署文档</summary>
#### 前提
* 仅适用于宝塔面板9.2.0及以上版本
* 安装宝塔面板,前往[宝塔面板](https://www.bt.cn/new/download.html)官网,选择正式版的脚本下载安装
#### 部署
1. 登录宝塔面板,在左侧菜单栏中点击 `Docker`
2. 首次会提示安装 `Docker``Docker Compose` 服务,点击立即安装,若已安装请忽略
3. 安装完成后在 `Docker-应用商店-实用工具` 中找到 `思源笔记`,点击`安装`,也可以在搜索框直接搜索
4. 设置域名等基本信息,点击 `确定`
* 名称:应用名称,默认 `siyuan_随机字符`
* 版本选择:默认 `latest`
* 域名:如你需要通过域名访问,请在此处填写你的域名
* 允许外部访问:如你需通过 `IP+Port` 直接访问,请勾选,如你已经设置了域名,请不要勾选此处
* 端口:默认 `6806`,可自行修改
* 访问授权码:默认随机生成
* 内存限制0为不限制根据实际需要设置
5. 提交后面板会自动进行应用初始化,大概需要`1-3`分钟,初始化完成后即可访问
#### 访问思源笔记
* 如果你填写了域名,请在浏览器输入域名访问
* 如你选择了 `IP+端口`,请在浏览器地输入 `http://<宝塔面板IP>:6806` 访问
</details>
### 内部预览版
我们会在有重大更新前发布内部预览版,请访问 [https://github.com/siyuan-note/insider](https://github.com/siyuan-note/insider)。

View file

@ -37,6 +37,7 @@ export const initBlockPopover = (app: App) => {
if (aElement.firstElementChild?.getAttribute("data-type") === "url") {
if (aElement.firstElementChild.textContent.indexOf("...") > -1) {
tip = Lute.EscapeHTMLStr(aElement.firstElementChild.getAttribute("data-href"));
tooltipClass = "href";
}
}
if (!tip && aElement.dataset.wrap !== "true" && event.target.dataset.type !== "block-more" && !hasClosestByClassName(event.target, "block__icon")) {
@ -49,6 +50,7 @@ export const initBlockPopover = (app: App) => {
}
} else if (aElement.classList.contains("av__celltext--url")) {
tip = tip ? `<span style="word-break: break-all">${tip.substring(0, Constants.SIZE_TITLE)}</span><div class="fn__hr"></div>${aElement.getAttribute("data-name")}` : aElement.getAttribute("data-name");
tooltipClass = "href";
} else if (aElement.classList.contains("av__calc--ashow") && aElement.clientWidth + 2 < aElement.scrollWidth) {
tip = aElement.lastChild.textContent + " " + aElement.firstElementChild.textContent;
}
@ -76,7 +78,7 @@ export const initBlockPopover = (app: App) => {
} else {
assetTip += ` ${response.data.hSize}${title ? '<div class="fn__hr"></div>' + title : ""}<br>${window.siyuan.languages.modifiedAt} ${response.data.hUpdated}<br>${window.siyuan.languages.createdAt} ${response.data.hCreated}`;
}
showTooltip(assetTip, aElement);
showTooltip(assetTip, aElement, tooltipClass);
});
tip = "";
} else if (title) {

View file

@ -150,29 +150,22 @@ func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *p
parentAbsPath += ".sy"
parentPath := parentAbsPath
parentAbsPath = filepath.Join(util.DataDir, boxID, parentAbsPath)
parentData, readErr := filelock.ReadFile(parentAbsPath)
if nil != readErr {
if os.IsNotExist(readErr) {
// 子文档缺失父文档时自动补全 https://github.com/siyuan-note/siyuan/issues/7376
parentTree := treenode.NewTree(boxID, parentPath, hPathBuilder.String()+"Untitled", "Untitled")
if _, writeErr := WriteTree(parentTree); nil != writeErr {
logging.LogErrorf("rebuild parent tree [%s] failed: %s", parentAbsPath, writeErr)
} else {
logging.LogInfof("rebuilt parent tree [%s]", parentAbsPath)
treenode.UpsertBlockTree(parentTree)
}
parentDocIAL := DocIAL(parentAbsPath)
if 1 > len(parentDocIAL) {
// 子文档缺失父文档时自动补全 https://github.com/siyuan-note/siyuan/issues/7376
parentTree := treenode.NewTree(boxID, parentPath, hPathBuilder.String()+"Untitled", "Untitled")
if _, writeErr := WriteTree(parentTree); nil != writeErr {
logging.LogErrorf("rebuild parent tree [%s] failed: %s", parentAbsPath, writeErr)
} else {
logging.LogWarnf("read parent tree data [%s] failed: %s", parentAbsPath, readErr)
logging.LogInfof("rebuilt parent tree [%s]", parentAbsPath)
treenode.UpsertBlockTree(parentTree)
}
hPathBuilder.WriteString("Untitled/")
continue
}
ial := ReadDocIAL(parentData)
if 1 > len(ial) {
logging.LogWarnf("tree [%s] is corrupted", filepath.Join(boxID, p))
}
title := ial["title"]
title := parentDocIAL["title"]
if "" == title {
title = "Untitled"
}
@ -185,6 +178,29 @@ func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *p
return
}
func DocIAL(absPath string) (ret map[string]string) {
filelock.Lock(absPath)
file, err := os.Open(absPath)
if err != nil {
logging.LogErrorf("open file [%s] failed: %s", absPath, err)
filelock.Unlock(absPath)
return nil
}
iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, file, 512)
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
if field == "Properties" {
iter.ReadVal(&ret)
break
} else {
iter.Skip()
}
}
file.Close()
filelock.Unlock(absPath)
return
}
func WriteTree(tree *parse.Tree) (size uint64, err error) {
data, filePath, err := prepareWriteTree(tree)
if err != nil {

View file

@ -37,7 +37,6 @@ import (
"github.com/88250/lute/html"
"github.com/88250/lute/parse"
util2 "github.com/88250/lute/util"
jsoniter "github.com/json-iterator/go"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/riff"
@ -116,29 +115,9 @@ func (box *Box) docIAL(p string) (ret map[string]string) {
}
filePath := filepath.Join(util.DataDir, box.ID, p)
filelock.Lock(filePath)
file, err := os.Open(filePath)
if err != nil {
logging.LogErrorf("open file [%s] failed: %s", p, err)
filelock.Unlock(filePath)
return nil
}
iter := jsoniter.Parse(jsoniter.ConfigCompatibleWithStandardLibrary, file, 512)
for field := iter.ReadObject(); field != ""; field = iter.ReadObject() {
if field == "Properties" {
iter.ReadVal(&ret)
break
} else {
iter.Skip()
}
}
file.Close()
filelock.Unlock(filePath)
ret = filesys.DocIAL(filePath)
if 1 > len(ret) {
logging.LogWarnf("properties not found in file [%s]", p)
logging.LogWarnf("properties not found in file [%s]", filePath)
box.moveCorruptedData(filePath)
return nil
}

View file

@ -17,10 +17,8 @@
package model
import (
"github.com/88250/lute/html"
"time"
"github.com/88250/lute/ast"
"github.com/88250/lute/html"
"github.com/88250/lute/parse"
"github.com/emirpasic/gods/stacks/linkedliststack"
"github.com/siyuan-note/siyuan/kernel/treenode"
@ -209,7 +207,6 @@ func (tx *Transaction) doMoveOutlineHeading(operation *Operation) (ret *TxErr) {
}
func Outline(rootID string, preview bool) (ret []*Path, err error) {
time.Sleep(util.FrontendQueueInterval)
FlushTxQueue()
ret = []*Path{}

View file

@ -228,10 +228,11 @@ func Tesseract(imgAbsPath string) (ret []map[string]interface{}) {
}
tsv := string(output)
logging.LogInfof("tesseract [path=%s, size=%d] success", imgAbsPath, info.Size())
//logging.LogInfof("tesseract [path=%s] success [%s]", imgAbsPath, tsv)
// 按行分割 TSV 数据
lines := strings.Split(tsv, "\r\n")
tsv = strings.ReplaceAll(tsv, "\r", "")
lines := strings.Split(tsv, "\n")
// 解析 TSV 数据 跳过标题行,从第二行开始处理
for _, line := range lines[1:] {
@ -262,7 +263,7 @@ func GetOcrJsonText(jsonData []map[string]interface{}) (ret string) {
if text, ok := dataMap["text"]; ok {
// 确保 text 是字符串类型
if textStr, ok := text.(string); ok {
ret += " " + textStr
ret += " " + strings.ReplaceAll(textStr, "\r", "")
}
}
}

View file

@ -132,9 +132,6 @@ func SetNetworkProxy(proxyURL string) {
}
const (
// FrontendQueueInterval 为前端请求队列轮询间隔。
FrontendQueueInterval = 512 * time.Millisecond
// SQLFlushInterval 为数据库事务队列写入间隔。
SQLFlushInterval = 3000 * time.Millisecond
)