🎨 Convert [[wikilink]]
and #Tag
syntax when importing Markdown https://github.com/siyuan-note/siyuan/issues/8603
This commit is contained in:
parent
1d3925b1b5
commit
24f6f63379
1 changed files with 181 additions and 11 deletions
|
@ -502,7 +502,6 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
|
|||
assetsDone := map[string]string{}
|
||||
|
||||
// md 转换 sy
|
||||
i := 0
|
||||
filepath.Walk(localPath, func(currentPath string, info os.FileInfo, walkErr error) error {
|
||||
if strings.HasPrefix(info.Name(), ".") {
|
||||
if info.IsDir() {
|
||||
|
@ -538,9 +537,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
|
|||
|
||||
if info.IsDir() {
|
||||
tree = treenode.NewTree(boxID, targetPath, hPath, title)
|
||||
if err = indexWriteJSONQueue(tree); nil != err {
|
||||
return io.EOF
|
||||
}
|
||||
importTrees = append(importTrees, tree)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -623,12 +620,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
|
|||
})
|
||||
|
||||
reassignIDUpdated(tree)
|
||||
indexWriteJSONQueue(tree)
|
||||
|
||||
i++
|
||||
if 0 == i%4 {
|
||||
util.PushEndlessProgress(fmt.Sprintf(Conf.Language(66), fmt.Sprintf("%d ", i)+util.ShortPathForBootingDisplay(tree.Path)))
|
||||
}
|
||||
importTrees = append(importTrees, tree)
|
||||
return nil
|
||||
})
|
||||
} else { // 导入单个文件
|
||||
|
@ -707,7 +699,23 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
|
|||
})
|
||||
|
||||
reassignIDUpdated(tree)
|
||||
indexWriteJSONQueue(tree)
|
||||
importTrees = append(importTrees, tree)
|
||||
}
|
||||
|
||||
if 0 < len(importTrees) {
|
||||
initSearchLinks()
|
||||
convertWikiLinksAndTags()
|
||||
buildBlockRefInText()
|
||||
|
||||
for i, tree := range importTrees {
|
||||
indexWriteJSONQueue(tree)
|
||||
if 0 == i%4 {
|
||||
util.PushEndlessProgress(fmt.Sprintf(Conf.Language(66), fmt.Sprintf("%d/%d ", i, len(importTrees))+tree.HPath))
|
||||
}
|
||||
}
|
||||
|
||||
importTrees = []*parse.Tree{}
|
||||
searchLinks = map[string]string{}
|
||||
}
|
||||
|
||||
IncSync()
|
||||
|
@ -909,3 +917,165 @@ func domAttrValue(n *html.Node, attrName string) string {
|
|||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var importTrees []*parse.Tree
|
||||
var searchLinks = map[string]string{}
|
||||
|
||||
func initSearchLinks() {
|
||||
for _, tree := range importTrees {
|
||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering || (ast.NodeDocument != n.Type && ast.NodeHeading != n.Type) {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
nodePath := tree.HPath + "#"
|
||||
if ast.NodeHeading == n.Type {
|
||||
nodePath += n.Text()
|
||||
}
|
||||
|
||||
searchLinks[nodePath] = n.ID
|
||||
return ast.WalkContinue
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func convertWikiLinksAndTags() {
|
||||
for _, tree := range importTrees {
|
||||
convertWikiLinksAndTags0(tree)
|
||||
}
|
||||
}
|
||||
|
||||
func convertWikiLinksAndTags0(tree *parse.Tree) {
|
||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering || ast.NodeText != n.Type {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
text := n.TokensStr()
|
||||
length := len(text)
|
||||
start, end := 0, length
|
||||
for {
|
||||
part := text[start:end]
|
||||
if idx := strings.Index(part, "]]"); 0 > idx {
|
||||
break
|
||||
} else {
|
||||
end = start + idx
|
||||
}
|
||||
if idx := strings.Index(part, "[["); 0 > idx {
|
||||
break
|
||||
} else {
|
||||
start += idx
|
||||
}
|
||||
if end <= start {
|
||||
break
|
||||
}
|
||||
|
||||
link := path.Join(path.Dir(tree.HPath), text[start+2:end]) // 统一转为绝对路径方便后续查找
|
||||
linkText := path.Base(link)
|
||||
if linkParts := strings.Split(link, "|"); 1 < len(linkParts) {
|
||||
link = linkParts[0]
|
||||
linkText = linkParts[1]
|
||||
}
|
||||
link, linkText = strings.TrimSpace(link), strings.TrimSpace(linkText)
|
||||
if !strings.Contains(link, "#") {
|
||||
link += "#" // 在结尾统一带上锚点方便后续查找
|
||||
}
|
||||
|
||||
id := searchLinkID(link)
|
||||
if "" == id {
|
||||
start, end = end, length
|
||||
continue
|
||||
}
|
||||
|
||||
linkText = strings.TrimPrefix(linkText, "/")
|
||||
repl := "((" + id + " '" + linkText + "'))"
|
||||
end += 2
|
||||
text = text[:start] + repl + text[end:]
|
||||
start, end = start+len(repl), len(text)
|
||||
length = end
|
||||
}
|
||||
|
||||
text = convertTags(text) // 导入标签语法
|
||||
n.Tokens = gulu.Str.ToBytes(text)
|
||||
return ast.WalkContinue
|
||||
})
|
||||
}
|
||||
|
||||
func convertTags(text string) (ret string) {
|
||||
pos, i := -1, 0
|
||||
tokens := []byte(text)
|
||||
for ; i < len(tokens); i++ {
|
||||
if '#' == tokens[i] && (0 == i || ' ' == tokens[i-1] || (-1 < pos && '#' == tokens[pos])) {
|
||||
if i < len(tokens)-1 && '#' == tokens[i+1] {
|
||||
pos = -1
|
||||
continue
|
||||
}
|
||||
pos = i
|
||||
continue
|
||||
}
|
||||
|
||||
if -1 < pos && ' ' == tokens[i] {
|
||||
tokens = append(tokens, 0)
|
||||
copy(tokens[i+1:], tokens[i:])
|
||||
tokens[i] = '#'
|
||||
pos = -1
|
||||
i++
|
||||
}
|
||||
}
|
||||
if -1 < pos && pos < i {
|
||||
tokens = append(tokens, '#')
|
||||
}
|
||||
return string(tokens)
|
||||
}
|
||||
|
||||
// buildBlockRefInText 将文本节点进行结构化处理。
|
||||
func buildBlockRefInText() {
|
||||
lute := NewLute()
|
||||
for _, tree := range importTrees {
|
||||
var unlinkTextNodes []*ast.Node
|
||||
ast.Walk(tree.Root, func(n *ast.Node, entering bool) ast.WalkStatus {
|
||||
if !entering || ast.NodeText != n.Type {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
if nil == n.Tokens {
|
||||
return ast.WalkContinue
|
||||
}
|
||||
|
||||
t := parse.Inline("", n.Tokens, lute.ParseOptions) // 使用行级解析
|
||||
var children []*ast.Node
|
||||
for c := t.Root.FirstChild.FirstChild; nil != c; c = c.Next {
|
||||
children = append(children, c)
|
||||
}
|
||||
for _, c := range children {
|
||||
n.InsertBefore(c)
|
||||
}
|
||||
unlinkTextNodes = append(unlinkTextNodes, n)
|
||||
return ast.WalkContinue
|
||||
})
|
||||
|
||||
for _, node := range unlinkTextNodes {
|
||||
node.Unlink()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func searchLinkID(link string) (id string) {
|
||||
id = searchLinks[link]
|
||||
if "" != id {
|
||||
return
|
||||
}
|
||||
|
||||
baseName := path.Base(link)
|
||||
for searchLink, searchID := range searchLinks {
|
||||
if path.Base(searchLink) == baseName {
|
||||
return searchID
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func cleanImport() {
|
||||
importTrees = []*parse.Tree{}
|
||||
searchLinks = map[string]string{}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue