diff --git a/kernel/model/box.go b/kernel/model/box.go index 4f7ad2f3c..ba51b81dc 100644 --- a/kernel/model/box.go +++ b/kernel/model/box.go @@ -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" @@ -566,22 +567,62 @@ 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 { + tree.Root.SetIALAttr("title", fmt.Sprint(attrV)) + continue + } + if "date" == attrK { + created, parseTimeErr := dateparse.ParseIn(fmt.Sprint(attrV), time.Local) + if nil == parseTimeErr { + docID := created.Format("20060102150405") + "-" + gulu.Rand.String(7) + tree.Root.ID = docID + tree.Root.SetIALAttr("id", docID) + } + continue + } + if "lastmod" == attrK { + updated, parseTimeErr := dateparse.ParseIn(fmt.Sprint(attrV), time.Local) + if nil == parseTimeErr { + tree.Root.SetIALAttr("updated", updated.Format("20060102150405")) + } + 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)) } } diff --git a/kernel/model/import.go b/kernel/model/import.go index 14ab361b4..16d39c2ad 100644 --- a/kernel/model/import.go +++ b/kernel/model/import.go @@ -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" @@ -765,6 +762,17 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) { return nil } + if "" != tree.Root.ID { + id = tree.Root.ID + } + if "" != tree.Root.IALAttr("title") { + title = tree.Root.IALAttr("title") + } + updated := tree.Root.IALAttr("updated") + 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 @@ -871,6 +879,16 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) { return errors.New(msg) } + if "" != tree.Root.ID { + id = tree.Root.ID + } + if "" != tree.Root.IALAttr("title") { + title = tree.Root.IALAttr("title") + } + updated := tree.Root.IALAttr("updated") + 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) } @@ -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 ""