feat: Add option to respect Obsidian's "Folder to create new notes in" setting

This commit is contained in:
Kodai Nakamura 2025-12-16 22:52:24 +09:00
parent dc292f1424
commit 6c7d6256c8
3 changed files with 44 additions and 26 deletions

View file

@ -61,9 +61,15 @@ export default class AutomaticLinkerPlugin extends Plugin {
* Falls back to default wikilink format if the file cannot be resolved.
*/
private createLinkGenerator(sourcePath: string): LinkGenerator {
return ({ linkPath, alias, isInTable }: LinkGeneratorParams): string => {
return ({
linkPath,
alias,
isInTable,
}: LinkGeneratorParams): string => {
// Try to get the TFile for the link path
const targetFile = this.app.vault.getAbstractFileByPath(linkPath + ".md");
const targetFile = this.app.vault.getAbstractFileByPath(
linkPath + ".md",
);
if (targetFile instanceof TFile) {
// File exists, use Obsidian's generateMarkdownLink API
@ -72,12 +78,15 @@ export default class AutomaticLinkerPlugin extends Plugin {
targetFile,
sourcePath,
"",
alias || ""
alias || "",
);
return link;
} catch (error) {
// Fall back to default format if API fails
console.warn("Failed to generate link using Obsidian API:", error);
console.warn(
"Failed to generate link using Obsidian API:",
error,
);
}
}
@ -145,6 +154,9 @@ export default class AutomaticLinkerPlugin extends Plugin {
const { contentStart } = getFrontMatterInfo(fileContent);
const frontmatter = fileContent.slice(0, contentStart);
const linkGenerator = this.createLinkGenerator(filePath);
const baseDir = this.settings.respectNewFileFolderPath
? this.app.vault.getConfig("newFileFolderPath")
: undefined;
const updatedBody = replaceLinks({
body: fileContent.slice(contentStart),
linkResolverContext: {
@ -154,7 +166,7 @@ export default class AutomaticLinkerPlugin extends Plugin {
},
settings: {
namespaceResolution: this.settings.namespaceResolution,
baseDir: this.settings.baseDir,
baseDir,
ignoreDateFormats: this.settings.ignoreDateFormats,
ignoreCase: this.settings.ignoreCase,
preventSelfLinking: this.settings.preventSelfLinking,
@ -258,6 +270,9 @@ export default class AutomaticLinkerPlugin extends Plugin {
}
const linkGenerator = this.createLinkGenerator(activeFile.path);
const baseDir = this.settings.respectNewFileFolderPath
? this.app.vault.getConfig("newFileFolderPath")
: undefined;
const updatedText = replaceLinks({
body: selectedText,
linkResolverContext: {
@ -267,7 +282,7 @@ export default class AutomaticLinkerPlugin extends Plugin {
},
settings: {
namespaceResolution: this.settings.namespaceResolution,
baseDir: this.settings.baseDir,
baseDir,
ignoreDateFormats: this.settings.ignoreDateFormats,
ignoreCase: this.settings.ignoreCase,
preventSelfLinking: this.settings.preventSelfLinking,
@ -337,9 +352,12 @@ export default class AutomaticLinkerPlugin extends Plugin {
}
// Build candidateMap and Trie using the helper function.
const baseDir = this.settings.respectNewFileFolderPath
? this.app.vault.getConfig("newFileFolderPath")
: undefined;
const { candidateMap, trie } = buildCandidateTrie(
allFiles,
this.settings.baseDir,
baseDir,
this.settings.ignoreCase ?? false,
);
this.candidateMap = candidateMap;
@ -487,7 +505,7 @@ export default class AutomaticLinkerPlugin extends Plugin {
// Optionally, override the default save command to run modifyLinks (throttled).
const saveCommandDefinition =
// @ts-expect-error
// @ts-ignore
this.app?.commands?.commands?.["editor:save-file"];
const saveCallback = saveCommandDefinition?.checkCallback;
if (typeof saveCallback === "function") {
@ -523,7 +541,7 @@ export default class AutomaticLinkerPlugin extends Plugin {
async onunload() {
// Restore original save command callback
const saveCommandDefinition =
// @ts-expect-error
// @ts-ignore
this.app?.commands?.commands?.["editor:save-file"];
if (saveCommandDefinition && this.originalSaveCallback) {
saveCommandDefinition.checkCallback = this.originalSaveCallback;

View file

@ -1,7 +1,7 @@
export type AutomaticLinkerSettings = {
formatOnSave: boolean;
baseDir: string;
showNotice: boolean;
respectNewFileFolderPath: boolean; // Respect Obsidian's "Folder to create new notes in" setting as base directory
considerAliases: boolean; // Consider aliases when linking
namespaceResolution: boolean; // Automatically resolve namespaces for shorthand links
ignoreDateFormats: boolean; // Ignore date formatted links (e.g. 2025-02-10)
@ -24,8 +24,8 @@ export type AutomaticLinkerSettings = {
export const DEFAULT_SETTINGS: AutomaticLinkerSettings = {
formatOnSave: false,
baseDir: "pages",
showNotice: false,
respectNewFileFolderPath: false, // Default: do not respect Obsidian's "Folder to create new notes in" setting
considerAliases: true, // Default: consider aliases
namespaceResolution: true, // Default: enable automatic namespace resolution
ignoreDateFormats: true, // Default: ignore date formats (e.g. 2025-02-10)

View file

@ -29,6 +29,21 @@ export class AutomaticLinkerPluginSettingsTab extends PluginSettingTab {
});
});
// Toggle for respecting Obsidian's "Folder to create new notes in" setting
new Setting(containerEl)
.setName("Respect 'Folder to create new notes in' setting")
.setDesc(
"When enabled, the plugin will use Obsidian's 'Folder to create new notes in' setting as the base directory for omitting folder prefixes in links.",
)
.addToggle((toggle) => {
toggle
.setValue(this.plugin.settings.respectNewFileFolderPath)
.onChange(async (value) => {
this.plugin.settings.respectNewFileFolderPath = value;
await this.plugin.saveData(this.plugin.settings);
});
});
// Toggle for running linter after formatting
new Setting(containerEl)
.setName("Run Obsidian Linter after formatting")
@ -77,21 +92,6 @@ export class AutomaticLinkerPluginSettingsTab extends PluginSettingTab {
});
});
// Setting for base directories.
new Setting(containerEl)
.setName("Base directory")
.setDesc(
"Enter the directory to be treated as the base directory. For example, 'pages' will allow links to be formatted without the 'pages/' prefix. If you want to achieve more complex behavior, consider using Obsidian Linter Plugin.",
)
.addText((text) => {
text.setPlaceholder("e.g. pages\n")
.setValue(this.plugin.settings.baseDir)
.onChange(async (value) => {
this.plugin.settings.baseDir = value;
await this.plugin.saveData(this.plugin.settings);
});
});
// Toggle for considering aliases.
new Setting(containerEl)
.setName("Consider aliases")