feat: add minimum character count setting

This commit is contained in:
Kodai Nakamura 2025-02-05 19:49:41 +09:00
parent 3e4cfc921c
commit eca0d7da33
4 changed files with 55 additions and 1 deletions

View file

@ -8,11 +8,14 @@ Automatic Linker Plugin automatically converts plain text file references into O
The plugin scans your file for text that matches file names in your vault and converts them into wiki links by wrapping them in `[[ ]]`.
- **Format on Save:**
Optionally, the plugin can automatically format (i.e. convert links) when you save your file.
Optionally, the plugin can automatically format (i.e. convert links) when you save a file.
- **Configurable Base Directories:**
Specify directories (e.g. `pages`) that are treated as base. For files in these directories, the directory prefix can be omitted when linking.
- **Minimum Character Count:**
If the file content is shorter than the specified minimum character count, link conversion is skipped. This prevents accidental formatting of very short texts.
- **Respects Existing Links:**
Already formatted links (i.e. those wrapped in `[[ ]]`) are preserved and not reformatted.
@ -36,3 +39,6 @@ The plugin settings are available under the **Automatic Linker Plugin** settings
- **Base Directories:**
Enter one or more directory names (one per line) that should be treated as base. For example, if you enter `pages`, then file links like `pages/tags` can be referenced simply as `tags`.
- **Minimum Character Count:**
Set the minimum number of characters required for the file content to be processed. If the file content is shorter than this value, link conversion will be skipped.

View file

@ -74,6 +74,7 @@ export default class AutomaticLinkerPlugin extends Plugin {
fileContent,
trie: this.trie ?? buildCandidateTrie([]).trie,
candidateMap: this.candidateMap ?? new Map(),
minCharCount: this.settings.minCharCount,
getFrontMatterInfo,
});

View file

@ -7,19 +7,28 @@ import { buildCandidateTrie, TrieNode } from "./trie";
* @param trie - The pre-built Trie for candidate lookup.
* @param candidateMap - Mapping from candidate string to its canonical replacement.
* @param getFrontMatterInfo - Function to get the front matter info.
* @param minCharCount - Minimum character count required to perform replacement.
* @returns The file content with replaced links.
*/
export const replaceLinks = async ({
fileContent,
trie,
candidateMap,
minCharCount = 0,
getFrontMatterInfo,
}: {
fileContent: string;
trie: TrieNode;
candidateMap: Map<string, string>;
minCharCount?: number;
getFrontMatterInfo: (fileContent: string) => { contentStart: number };
}): Promise<string> => {
// If the file content is shorter than the minimum character count,
// return the content unchanged.
if (fileContent.length <= minCharCount) {
return fileContent;
}
// Helper: determine if a character is a word boundary.
const isWordBoundary = (char: string | undefined): boolean => {
if (char === undefined) return true;
@ -140,6 +149,7 @@ if (import.meta.vitest) {
trie,
candidateMap,
getFrontMatterInfo,
minCharCount: 0,
}),
).toBe("[[hello]]");
});
@ -670,5 +680,19 @@ if (import.meta.vitest) {
}),
).toBe("```typescript\nexample\n```");
});
it("skips replacement when content is too short", async () => {
const fileNames = getSortedFileNames(["hello"]);
const { candidateMap, trie } = buildCandidateTrie(fileNames);
// When minCharCount is higher than the fileContent length, no replacement should occur.
expect(
await replaceLinks({
fileContent: "hello",
trie,
candidateMap,
getFrontMatterInfo,
minCharCount: 10,
}),
).toBe("hello");
});
});
}

View file

@ -5,12 +5,14 @@ export type AutomaticLinkerSettings = {
formatOnSave: boolean;
baseDirs: string[];
showNotice: boolean;
minCharCount: number; // Minimum character count setting
};
export const DEFAULT_SETTINGS: AutomaticLinkerSettings = {
formatOnSave: false,
baseDirs: ["pages"],
showNotice: false,
minCharCount: 0, // Default value: 0 (always replace links)
};
export class AutomaticLinkerPluginSettingsTab extends PluginSettingTab {
@ -39,6 +41,7 @@ export class AutomaticLinkerPluginSettingsTab extends PluginSettingTab {
});
});
// Setting for base directories.
new Setting(containerEl)
.setName("Base Directories")
.setDesc(
@ -56,6 +59,7 @@ export class AutomaticLinkerPluginSettingsTab extends PluginSettingTab {
});
});
// Toggle for showing the load notice.
new Setting(containerEl)
.setName("Show Load Notice")
.setDesc("Display a notice when markdown files are loaded.")
@ -67,5 +71,24 @@ export class AutomaticLinkerPluginSettingsTab extends PluginSettingTab {
await this.plugin.saveData(this.plugin.settings);
});
});
// Setting for minimum character count.
// If the text is below this number of characters, links will not be replaced.
new Setting(containerEl)
.setName("Minimum Character Count")
.setDesc(
"If the content is below this character count, the links will not be replaced.",
)
.addText((text) => {
text.setPlaceholder("e.g. 4")
.setValue(this.plugin.settings.minCharCount.toString())
.onChange(async (value) => {
const parsedValue = parseInt(value);
if (!isNaN(parsedValue)) {
this.plugin.settings.minCharCount = parsedValue;
await this.plugin.saveData(this.plugin.settings);
}
});
});
}
}