Skip to content

Commit 5fd1eb4

Browse files
committed
feat: add bulk rename
1 parent 9f65de1 commit 5fd1eb4

File tree

1 file changed

+47
-13
lines changed

1 file changed

+47
-13
lines changed

src/main.ts

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Notice, Plugin, normalizePath } from "obsidian";
1+
import { Notice, Plugin, TFile, TFolder, normalizePath } from "obsidian";
22
import { fetchTitleFromUrl } from "./utils/http-utils";
33
import { formatTitleForMacOS } from "./utils/title-utils";
44
interface TitleFetcherSettings {
@@ -19,6 +19,20 @@ export default class TitleFetcherPlugin extends Plugin {
1919
this.renameToUrlTitle();
2020
});
2121

22+
this.registerEvent(
23+
this.app.workspace.on("file-menu", (menu, file) => {
24+
if (file instanceof TFolder) {
25+
menu.addItem((item) => {
26+
item.setTitle("Rename notes to URL titles")
27+
.setIcon("file-code-2")
28+
.onClick(async () => {
29+
await this.renameFolderNotesToUrlTitle(file);
30+
});
31+
});
32+
}
33+
})
34+
);
35+
2236
this.addCommand({
2337
id: "rename-to-url-title",
2438
name: "Rename to URL title",
@@ -33,15 +47,38 @@ export default class TitleFetcherPlugin extends Plugin {
3347

3448
onunload() {}
3549

36-
private async renameToUrlTitle() {
37-
const activeFile = this.app.workspace.getActiveFile();
38-
if (!activeFile) {
39-
new Notice("No file is open");
40-
return;
50+
private async renameFolderNotesToUrlTitle(folder: TFolder) {
51+
const markdownFiles = this.app.vault
52+
.getMarkdownFiles()
53+
.filter((file) => file.parent === folder);
54+
55+
const BATCH_SIZE = 3; // Process 3 files at a time
56+
57+
for (let i = 0; i < markdownFiles.length; i += BATCH_SIZE) {
58+
const batch = markdownFiles.slice(i, i + BATCH_SIZE);
59+
await Promise.allSettled(
60+
batch.map((file) => this.renameToUrlTitle(file))
61+
);
62+
63+
// Optional: small delay between batches to be respectful
64+
if (i + BATCH_SIZE < markdownFiles.length) {
65+
await new Promise((resolve) => setTimeout(resolve, 100));
66+
}
67+
}
68+
}
69+
70+
private async renameToUrlTitle(file?: TFile) {
71+
if (!file) {
72+
const activeFile = this.app.workspace.getActiveFile();
73+
if (!activeFile) {
74+
new Notice("No file is open");
75+
return;
76+
}
77+
file = activeFile;
4178
}
4279

4380
const frontmatter =
44-
this.app.metadataCache.getFileCache(activeFile)?.frontmatter;
81+
this.app.metadataCache.getFileCache(file)?.frontmatter;
4582
if (!frontmatter) {
4683
new Notice("No frontmatter found in the current file");
4784
return;
@@ -63,18 +100,15 @@ export default class TitleFetcherPlugin extends Plugin {
63100
const formattedTitle = formatTitleForMacOS(title);
64101

65102
let formattedTitleWithExtension = "";
66-
if (activeFile.parent) {
103+
if (file.parent) {
67104
formattedTitleWithExtension = normalizePath(
68-
`${activeFile.parent.path}/${formattedTitle}.md`
105+
`${file.parent.path}/${formattedTitle}.md`
69106
);
70107
} else {
71108
formattedTitleWithExtension = `${formattedTitle}.md`;
72109
}
73110

74-
await this.app.vault.rename(
75-
activeFile,
76-
formattedTitleWithExtension
77-
);
111+
await this.app.vault.rename(file, formattedTitleWithExtension);
78112
new Notice(`Renamed file to ${formattedTitleWithExtension}`);
79113
} catch (error) {
80114
new Notice("Failed to rename file");

0 commit comments

Comments
 (0)