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

This commit is contained in:
Vanessa 2025-11-22 17:46:59 +08:00
commit 079917633c
2 changed files with 56 additions and 32 deletions

View file

@ -343,6 +343,10 @@ func (tx *Transaction) processUndoInsertWithFoldedHeading() {
// 删除折叠标题后撤销,需要调整 insert 顺序和 previousID // 删除折叠标题后撤销,需要调整 insert 顺序和 previousID
// https://github.com/siyuan-note/siyuan/issues/16120 // https://github.com/siyuan-note/siyuan/issues/16120
if 1 > len(tx.DoOperations) {
return
}
// 所有操作均为 insert 才处理 // 所有操作均为 insert 才处理
for _, op := range tx.DoOperations { for _, op := range tx.DoOperations {
if "insert" != op.Action { if "insert" != op.Action {
@ -350,6 +354,8 @@ func (tx *Transaction) processUndoInsertWithFoldedHeading() {
} }
} }
// 找到 ignoreProcess=true 的区间 [j, k]
var j, k int
for i := 0; i < len(tx.DoOperations); i++ { for i := 0; i < len(tx.DoOperations); i++ {
op := tx.DoOperations[i] op := tx.DoOperations[i]
ignoreProcess := false ignoreProcess := false
@ -361,38 +367,26 @@ func (tx *Transaction) processUndoInsertWithFoldedHeading() {
return return
} }
} }
if ignoreProcess {
// 找到从当前 i 到下个 ignoreProcess=false 的区间,整体反转
j := i + 1
if j >= len(tx.DoOperations) {
return
}
for ; j < len(tx.DoOperations); j++ { if !ignoreProcess {
nextOp := tx.DoOperations[j] if 0 != j && 0 != k {
nextIgnoreProcess := false break
if nil != nextOp.Context["ignoreProcess"] {
var convErr error
nextIgnoreProcess, convErr = strconv.ParseBool(nextOp.Context["ignoreProcess"].(string))
if nil != convErr {
logging.LogErrorf("parse ignoreProcess failed: %s", convErr)
return
}
}
if !nextIgnoreProcess {
break
}
} }
for _, nextOp := range tx.DoOperations[i:j] { continue
nextOp.PreviousID = tx.DoOperations[j].ID
}
slices.Reverse(tx.DoOperations[i : j+1])
i = j
} }
if i >= len(tx.DoOperations) {
return if 0 == j && 0 == k {
j = i
} }
k = i
} }
// 调整 [j, k] 区间内的操作顺序和 previousID
for x := j; x <= k; x++ {
opx := tx.DoOperations[x]
opx.PreviousID = tx.DoOperations[k].PreviousID
}
slices.Reverse(tx.DoOperations[j : k+1])
} }
func (tx *Transaction) processLargeInsert() bool { func (tx *Transaction) processLargeInsert() bool {

View file

@ -19,6 +19,7 @@ package util
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
@ -182,9 +183,29 @@ func RemoveAssetText(asset string) {
assetsTextsChanged.Store(true) assetsTextsChanged.Store(true)
} }
var tesseractExts = []string{
".png",
".jpg",
".jpeg",
".tif",
".tiff",
".bmp",
".gif",
".webp",
".pbm",
".pgm",
".ppm",
".pnm",
}
func IsTesseractExtractable(p string) bool { func IsTesseractExtractable(p string) bool {
lowerName := strings.ToLower(p) lowerName := strings.ToLower(p)
return strings.HasSuffix(lowerName, ".png") || strings.HasSuffix(lowerName, ".jpg") || strings.HasSuffix(lowerName, ".jpeg") for _, ext := range tesseractExts {
if strings.HasSuffix(lowerName, ext) {
return true
}
}
return false
} }
// tesseractOCRLock 用于 Tesseract OCR 加锁串行执行提升稳定性 https://github.com/siyuan-note/siyuan/issues/7265 // tesseractOCRLock 用于 Tesseract OCR 加锁串行执行提升稳定性 https://github.com/siyuan-note/siyuan/issues/7265
@ -214,14 +235,23 @@ func Tesseract(imgAbsPath string) (ret []map[string]interface{}) {
defer logging.Recover() defer logging.Recover()
ctx, cancel := context.WithTimeout(context.Background(), 7*time.Second) timeout := 7000
timeoutEnv := os.Getenv("SIYUAN_TESSERACT_TIMEOUT")
if "" != timeoutEnv {
if timeoutParsed, parseErr := strconv.Atoi(timeoutEnv); nil == parseErr {
timeout = timeoutParsed
} else {
logging.LogWarnf("parse tesseract timeout [%s] failed: %s", timeoutEnv, parseErr)
}
}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Millisecond)
defer cancel() defer cancel()
cmd := exec.CommandContext(ctx, TesseractBin, "-c", "debug_file=/dev/null", imgAbsPath, "stdout", "-l", strings.Join(TesseractLangs, "+"), "tsv") cmd := exec.CommandContext(ctx, TesseractBin, "-c", "debug_file=/dev/null", imgAbsPath, "stdout", "-l", strings.Join(TesseractLangs, "+"), "tsv")
gulu.CmdAttr(cmd) gulu.CmdAttr(cmd)
output, err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
if ctx.Err() == context.DeadlineExceeded { if errors.Is(ctx.Err(), context.DeadlineExceeded) {
logging.LogWarnf("tesseract [path=%s, size=%d] timeout", imgAbsPath, info.Size()) logging.LogWarnf("tesseract [path=%s, size=%d] timeout [%dms]", imgAbsPath, info.Size(), timeout)
return return
} }
@ -300,7 +330,7 @@ func InitTesseract() {
langs := getTesseractLangs() langs := getTesseractLangs()
if 1 > len(langs) { if 1 > len(langs) {
logging.LogWarnf("no tesseract langs found") logging.LogWarnf("no tesseract langs found, disabling tesseract-ocr")
TesseractEnabled = false TesseractEnabled = false
tesseractInited.Store(true) tesseractInited.Store(true)
return return