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

This commit is contained in:
Vanessa 2024-10-30 11:17:53 +08:00
commit 427cb613e0
3 changed files with 98 additions and 50 deletions

View file

@ -34,6 +34,7 @@ import (
"github.com/88250/lute/html"
"github.com/88250/lute/lex"
"github.com/88250/lute/parse"
"github.com/araddon/dateparse"
"github.com/siyuan-note/filelock"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/cache"
@ -493,7 +494,7 @@ func parseKTree(kramdown []byte) (ret *parse.Tree) {
return
}
func normalizeTree(tree *parse.Tree) {
func normalizeTree(tree *parse.Tree) (yfmRootID, yfmTitle, yfmUpdated string) {
if nil == tree.Root.FirstChild {
tree.Root.AppendChild(treenode.NewParagraph())
}
@ -566,22 +567,64 @@ func normalizeTree(tree *parse.Tree) {
parseErr := yaml.Unmarshal(n.Tokens, &attrs)
if parseErr != nil {
logging.LogWarnf("parse YAML front matter [%s] failed: %s", n.Tokens, parseErr)
} else {
for attrK, attrV := range attrs {
validKeyName := true
for i := 0; i < len(attrK); i++ {
if !lex.IsASCIILetterNumHyphen(attrK[i]) {
validKeyName = false
break
return ast.WalkContinue
}
for attrK, attrV := range attrs {
// Improve parsing of YAML Front Matter when importing Markdown https://github.com/siyuan-note/siyuan/issues/12962
if "title" == attrK {
yfmTitle = fmt.Sprint(attrV)
tree.Root.SetIALAttr("title", yfmTitle)
continue
}
if "date" == attrK {
created, parseTimeErr := dateparse.ParseIn(fmt.Sprint(attrV), time.Local)
if nil == parseTimeErr {
yfmRootID = created.Format("20060102150405") + "-" + gulu.Rand.String(7)
tree.Root.ID = yfmRootID
tree.Root.SetIALAttr("id", yfmRootID)
}
continue
}
if "lastmod" == attrK {
updated, parseTimeErr := dateparse.ParseIn(fmt.Sprint(attrV), time.Local)
if nil == parseTimeErr {
yfmUpdated = updated.Format("20060102150405")
tree.Root.SetIALAttr("updated", yfmUpdated)
}
continue
}
if "tags" == attrK {
var tags string
for i, tag := range attrV.([]any) {
tagStr := strings.TrimSpace(tag.(string))
if "" == tag {
continue
}
tagStr = strings.TrimLeft(tagStr, "#,'\"")
tagStr = strings.TrimRight(tagStr, "#,'\"")
tags += tagStr
if i < len(attrV.([]any))-1 {
tags += ","
}
}
if !validKeyName {
logging.LogWarnf("invalid YAML key [%s] in [%s]", attrK, n.ID)
continue
}
tree.Root.SetIALAttr("custom-"+attrK, fmt.Sprint(attrV))
tree.Root.SetIALAttr("tags", tags)
continue
}
validKeyName := true
for i := 0; i < len(attrK); i++ {
if !lex.IsASCIILetterNumHyphen(attrK[i]) {
validKeyName = false
break
}
}
if !validKeyName {
logging.LogWarnf("invalid YAML key [%s] in [%s]", attrK, n.ID)
continue
}
tree.Root.SetIALAttr("custom-"+attrK, fmt.Sprint(attrV))
}
}

View file

@ -1434,8 +1434,9 @@ func BatchExportMarkdown(boxID, folderPath string) (zipPath string) {
func yfm(docIAL map[string]string) string {
// 导出 Markdown 文件时开头附上一些元数据 https://github.com/siyuan-note/siyuan/issues/6880
// 导出 Markdown 时在文档头添加 YFM 开关https://github.com/siyuan-note/siyuan/issues/7727
if !Conf.Export.MarkdownYFM {
// 导出 Markdown 时在文档头添加 YFM 开关 https://github.com/siyuan-note/siyuan/issues/7727
return ""
}

View file

@ -22,24 +22,21 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/88250/lute"
"image"
"image/jpeg"
"image/png"
"io"
"io/fs"
"math/rand"
"os"
"path"
"path/filepath"
"regexp"
"runtime/debug"
"sort"
"strconv"
"strings"
"time"
"github.com/88250/gulu"
"github.com/88250/lute"
"github.com/88250/lute/ast"
"github.com/88250/lute/html"
"github.com/88250/lute/html/atom"
@ -759,12 +756,23 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
return io.EOF
}
tree = parseStdMd(data)
tree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)
if nil == tree {
logging.LogErrorf("parse tree [%s] failed", currentPath)
return nil
}
if "" != yfmRootID {
id = yfmRootID
}
if "" != yfmTitle {
title = yfmTitle
}
updated := yfmUpdated
fname := path.Base(targetPath)
targetPath = strings.ReplaceAll(targetPath, fname, id+".sy")
targetPaths[curRelPath] = targetPath
tree.ID = id
tree.Root.ID = id
tree.Root.SetIALAttr("id", tree.Root.ID)
@ -841,7 +849,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
return ast.WalkContinue
})
reassignIDUpdated(tree)
reassignIDUpdated(tree, id, updated)
importTrees = append(importTrees, tree)
hPathsIDs[tree.HPath] = tree.ID
@ -864,13 +872,23 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
if err != nil {
return err
}
tree := parseStdMd(data)
tree, yfmRootID, yfmTitle, yfmUpdated := parseStdMd(data)
if nil == tree {
msg := fmt.Sprintf("parse tree [%s] failed", localPath)
logging.LogErrorf(msg)
return errors.New(msg)
}
if "" != yfmRootID {
id = yfmRootID
}
if "" != yfmTitle {
title = yfmTitle
}
updated := yfmUpdated
fname := path.Base(targetPath)
targetPath = strings.ReplaceAll(targetPath, fname, id+".sy")
tree.ID = id
tree.Root.ID = id
tree.Root.SetIALAttr("id", tree.Root.ID)
@ -937,7 +955,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
return ast.WalkContinue
})
reassignIDUpdated(tree)
reassignIDUpdated(tree, id, updated)
importTrees = append(importTrees, tree)
}
@ -974,14 +992,14 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
return
}
func parseStdMd(markdown []byte) (ret *parse.Tree) {
func parseStdMd(markdown []byte) (ret *parse.Tree, yfmRootID, yfmTitle, yfmUpdated string) {
luteEngine := util.NewStdLute()
luteEngine.SetYamlFrontMatter(true) // 解析 YAML Front Matter https://github.com/siyuan-note/siyuan/issues/10878
ret = parse.Parse("", markdown, luteEngine.ParseOptions)
if nil == ret {
return
}
normalizeTree(ret)
yfmRootID, yfmTitle, yfmUpdated = normalizeTree(ret)
imgHtmlBlock2InlineImg(ret)
parse.NestedInlines2FlattedSpansHybrid(ret, false)
return
@ -1120,7 +1138,7 @@ func imgHtmlBlock2InlineImg(tree *parse.Tree) {
return
}
func reassignIDUpdated(tree *parse.Tree) {
func reassignIDUpdated(tree *parse.Tree, rootID, updated string) {
var blockCount int
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering || "" == n.ID {
@ -1131,23 +1149,22 @@ func reassignIDUpdated(tree *parse.Tree) {
return ast.WalkContinue
})
ids := make([]string, blockCount)
min, _ := strconv.ParseInt(time.Now().Add(-1*time.Duration(blockCount)*time.Second).Format("20060102150405"), 10, 64)
for i := 0; i < blockCount; i++ {
ids[i] = newID(fmt.Sprintf("%d", min))
min++
}
var i int
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
if !entering || "" == n.ID {
return ast.WalkContinue
}
n.ID = ids[i]
n.ID = ast.NewNodeID()
if ast.NodeDocument == n.Type && "" != rootID {
n.ID = rootID
}
n.SetIALAttr("id", n.ID)
n.SetIALAttr("updated", util.TimeFromID(n.ID))
i++
if "" != updated {
n.SetIALAttr("updated", updated)
} else {
n.SetIALAttr("updated", util.TimeFromID(n.ID))
}
return ast.WalkContinue
})
tree.ID = tree.Root.ID
@ -1155,19 +1172,6 @@ func reassignIDUpdated(tree *parse.Tree) {
tree.Root.SetIALAttr("id", tree.Root.ID)
}
func newID(t string) string {
return t + "-" + randStr(7)
}
func randStr(length int) string {
letter := []rune("abcdefghijklmnopqrstuvwxyz0123456789")
b := make([]rune, length)
for i := range b {
b[i] = letter[rand.Intn(len(letter))]
}
return string(b)
}
func domAttrValue(n *html.Node, attrName string) string {
if nil == n {
return ""