Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
3eff91d30e
7 changed files with 76 additions and 51 deletions
|
@ -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)。
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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{}
|
||||
|
|
|
@ -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", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,9 +132,6 @@ func SetNetworkProxy(proxyURL string) {
|
|||
}
|
||||
|
||||
const (
|
||||
// FrontendQueueInterval 为前端请求队列轮询间隔。
|
||||
FrontendQueueInterval = 512 * time.Millisecond
|
||||
|
||||
// SQLFlushInterval 为数据库事务队列写入间隔。
|
||||
SQLFlushInterval = 3000 * time.Millisecond
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue