generated from obsidianmd/obsidian-sample-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconverter.ts
139 lines (117 loc) · 4.33 KB
/
converter.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import {TFile, Notice, App, normalizePath, TAbstractFile, TFolder} from "obsidian"
import {unified} from "unified"
import remarkParse from "remark-parse"
import remarkGfm from "remark-gfm"
import remarkFrontmatter from "remark-frontmatter"
import remarkStringify from "remark-stringify"
import remarkWikiLink from "remark-wiki-link"
import {map as mapAst} from "unist-util-map"
import Plugin from "main"
export const convertLinksInVault = async (plugin: Plugin) => {
let mdFiles: TFile[] = plugin.app.vault.getMarkdownFiles()
let notice = new Notice("Starting to fix links", 0)
mdFiles = mdFiles.filter(
mdFile =>
!hasFrontmatter(plugin.app, mdFile.path, "excalidraw-plugin") &&
!hasFrontmatter(plugin.app, mdFile.path, "kanban-plugin")
)
try {
let totalCount = mdFiles.length
let counter = 0
for (let mdFile of mdFiles) {
counter++
notice.setMessage(`Fixing wiki links in notes ${counter}/${totalCount}.`)
await convertLinksAndSaveInSingleFile(mdFiles, mdFile, plugin)
}
} catch (err) {
console.log(err)
} finally {
notice.hide()
}
}
export const convertLinksAndSaveInSingleFile = async (
allFiles: TFile[],
mdFile: TFile,
plugin: Plugin
) => {
let fileText = await plugin.app.vault.read(mdFile)
let newFileText = convertLinks(allFiles, mdFile, fileText, plugin)
let fileStat = await plugin.app.vault.adapter.stat(normalizePath(mdFile.path))
await plugin.app.vault.modify(mdFile, newFileText, fileStat ?? undefined)
}
const hasFrontmatter = (app: App, filePath: string, keyToCheck: string) => {
let metaCache = app.metadataCache.getCache(filePath)
return metaCache?.frontmatter && metaCache?.frontmatter[keyToCheck]
}
export const convertLinks = (
allFiles: TFile[],
currentFile: TFile,
md: string,
plugin: Plugin
): string => {
const MdProcessor = unified()
.use(remarkParse)
.use(remarkGfm)
.use(remarkFrontmatter, ["yaml"])
.use(remarkWikiLink, {aliasDivider: "|"})
.use(remarkStringify)
try {
const rootAst = MdProcessor.parse(md)
// The wikilink extension isn't typed =/
const next = mapAst(rootAst, (node: any) => {
if (node.type !== "wikiLink") {
return node
}
const linkFile = findFile(plugin, allFiles, node.value)
// `node.value` is the link text
// `node.data.alias` is the displayed text
if (linkFile) {
return {
...node,
value: buildPath(linkFile),
data: {
...node.data,
alias: node.value === node.data.value ? linkFile.basename : node.data.alias,
},
}
}
const parts: string[] = node.value.split("/")
const folders = parts.slice(0, -1)
const name = parts[parts.length - 1]
const newFilesFolder = buildFolderPath(
plugin.app.fileManager.getNewFileParent(
`${buildPath(currentFile)}.${currentFile.extension}`
)
)
return {
...node,
value: folders.length === 0 ? `${newFilesFolder}/${node.value}` : node.value,
data: {
...node.data,
alias: node.value === node.data.value ? name : node.data.alias,
},
}
})
return MdProcessor.stringify(next)
} catch (err) {
console.log(err)
return md
}
}
const findFile = (plugin: Plugin, files: TFile[], name: string): TFile | null => {
const file = plugin.app.vault.getAbstractFileByPath(`${name}.md`)
if (file instanceof TFile) {
return file
}
return files.find(file => file.basename === name) ?? null
}
const buildPath = (file: TAbstractFile): string =>
file instanceof TFile
? file.parent
? `${buildPath(file.parent)}${file.basename}`
: file.basename
: file.parent
? `${buildPath(file.parent)}${file.name}/`
: ""
const buildFolderPath = (file: TFolder): string =>
file.parent ? `${buildPath(file.parent)}${file.name}` : file.name === "" ? "" : `${file.name}/`