feat: add commands to parse one file

This commit is contained in:
Mara 2025-02-05 15:55:47 +01:00
parent 13fd74421d
commit d49b7b0a97
8 changed files with 163 additions and 22 deletions

View file

@ -1,11 +1,18 @@
{
"command": {
"active": "Add thesaurus tags to active file"
},
"error": {
"csv": {
"columns": "The columns doesn't correspond with the settings.",
"header": "You can have only two column in your thesaurus. You have: {{- len}} columns.",
"malformed": "Your CSV is malformed: {{- len}} columns found.",
"separator": "The specified separator is invalid. You seems to use \"{{- sep}}\" as separator."
}
},
"file": {
"empty": "The file {{- file}} is empty!"
},
"notFound": "The thesaurus is not found at the provided path ({{- path}})."
},
"settings": {
"columns": {
@ -19,11 +26,11 @@
},
"title": "Column title"
},
"excludedPath": {
"desc": "Exclude files in theses paths when using the global command. ",
"includedPaths": {
"desc": "Includes files from its paths when using the global command.",
"regex": "Regex are supported.",
"separate": "Separate paths with coma, semicolon, spaces or newlines.",
"title": "Excluded path"
"title": "Included paths"
},
"separator": {
"desc": "CSV column separator.",
@ -38,5 +45,9 @@
"title": "Thesaurus",
"verify": "Verify validity of the file"
}
},
"success": {
"none": "No tag to add!",
"title": "The tags has been added:"
}
}

View file

@ -1,11 +1,18 @@
{
"command": {
"active": "Ajouter les tags du thésaurus au fichier actif"
},
"error": {
"csv": {
"columns": "Les colonnes du CSV fourni ne correspondent pas avec les colonnes des paramètres.",
"header": "Vous ne pouvez avoir que deux colonnes dans votre thésaurus. Vous avez {{- len}} colonnes.",
"malformed": "Votre CSV est mal formé : {{- len}} colonnes trouvées.",
"separator": "Le séparateur spécifié n'est pas le bon. Vous semblez utiliser \"{{- sep}}\" comme séparateur."
}
},
"file": {
"empty": "Le fichier {{- file}} est vide !"
},
"notFound": "Le thésaurus est introuvable au chemin fourni ({{-path}})."
},
"settings": {
"columns": {
@ -19,11 +26,11 @@
},
"title": "Titre des colonnes"
},
"excludedPath": {
"desc": "Exclus les fichiers depuis ses chemins lors d'utilisation de la commande globale.",
"includedPaths": {
"desc": "Inclus les fichiers depuis ses chemins lors d'utilisation de la commande globale.",
"regex": "Les expressions régulières sont supportées.",
"separate": "Séparer les chemins par une virgule, point virgule, un espace ou un retour à la ligne.",
"title": "Fichier exclus"
"separate": "Séparer les chemins par une virgule, point virgule ou un retour à la ligne.",
"title": "Chemins inclus"
},
"separator": {
"desc": "Séparateur des colonnes du fichier CSV.",
@ -38,5 +45,9 @@
"title": "Thesaurus",
"verify": "Verifier la validité du fichier"
}
},
"success": {
"none": "Aucun tag à ajouter !",
"title": "Les tags suivants ont bien été ajoutés :"
}
}

View file

@ -2,7 +2,7 @@ import type { TFunction } from "i18next";
export interface MyThesaurusSettings {
thesaurusPath: string;
excludedPath: string[];
includedPaths: string[];
separator: Separator;
columns: ColumnName;
}
@ -19,7 +19,7 @@ export type Translation = TFunction<"translation", undefined>;
export const DEFAULT_SETTINGS: MyThesaurusSettings = {
thesaurusPath: "",
excludedPath: [],
includedPaths: [],
separator: ";",
columns: {
term: "term",

View file

@ -1,14 +1,85 @@
import i18next from "i18next";
import { Plugin } from "obsidian";
import { Notice, Plugin, TFile, sanitizeHTMLToDom } from "obsidian";
import { resources, translationLanguage } from "./i18n";
import { DEFAULT_SETTINGS, type MyThesaurusSettings } from "./interfaces";
import { DEFAULT_SETTINGS, type MyThesaurusSettings, type Thesaurus } from "./interfaces";
import { MyThesaurusSettingTab } from "./settings";
import "uniformize";
import { getTags, getThesaurus } from "./utils";
export default class MyThesaurus extends Plugin {
settings!: MyThesaurusSettings;
async addTagsToNote(tags: string[], file: TFile) {
const currentTags = this.app.metadataCache.getFileCache(file)?.tags || [];
const newTags = [...new Set([...currentTags, ...tags])];
if (newTags.length === 0) return;
await this.app.fileManager.processFrontMatter(file, (frontmatter) => {
frontmatter.tags = newTags;
});
}
notice(message: string | DocumentFragment, silent = false) {
if (!silent) {
new Notice(message);
}
}
async parseFile(file: TFile, silent = false, thesaurus: Thesaurus) {
const contents = await this.app.vault.read(file);
const results = [];
if (contents.length === 0) {
this.notice(i18next.t("error.file.empty", { file: file.name }), silent);
results.push({
file: file.name,
tags: [],
error: i18next.t("error.file.empty", { file: file.name }),
});
}
try {
const tags = getTags(contents, thesaurus);
if (tags.length > 0) {
await this.addTagsToNote(tags, file);
const successMsg = sanitizeHTMLToDom(
`<p>${i18next.t("success.title")}</p>${tags.map((tag) => `<li><code>${tag}</code></li>`).join("")}`
);
this.notice(successMsg, silent);
results.push({
file: file.name,
tags: tags,
});
} else {
this.notice(i18next.t("success.none"), silent);
results.push({
file: file.name,
tags: [],
});
}
} catch (error) {
this.notice((error as Error).message, silent);
results.push({
file: file.name,
tags: [],
error: (error as Error).message,
});
}
}
async readThesaurus() {
const thesaurusFile = this.app.vault.getAbstractFileByPath(
this.settings.thesaurusPath
);
if (
!thesaurusFile ||
!(thesaurusFile instanceof TFile) ||
thesaurusFile.extension !== "csv"
) {
throw new Error(i18next.t("error.notFound"));
}
return await this.app.vault.read(thesaurusFile);
}
async onload() {
console.log(`[${this.manifest.name}] Loaded`);
await this.loadSettings();
@ -21,6 +92,33 @@ export default class MyThesaurus extends Plugin {
returnEmptyString: false,
});
this.addSettingTab(new MyThesaurusSettingTab(this.app, this));
this.addCommand({
id: "parse-file",
name: i18next.t("command.active"),
checkCallback: (checking) => {
const file = this.app.workspace.getActiveFile();
if (file && file.extension == "md") {
if (!checking) {
this.readThesaurus()
.catch((error) => {
this.notice(error.message);
return "";
})
.then((thesaurusContent) => {
const thesaurus = getThesaurus(
thesaurusContent,
this.settings.separator,
i18next.t,
this.settings.columns
);
this.parseFile(file, false, thesaurus);
});
}
return true;
}
return false;
},
});
}
onunload() {

View file

@ -10,7 +10,7 @@ import {
import type { MyThesaurusSettings, Separator } from "./interfaces";
import type MyThesaurus from "./main";
import { FileSuggester } from "./searchFile";
import { verifCSV } from "./utils";
import { getThesaurus } from "./utils";
export class MyThesaurusSettingTab extends PluginSettingTab {
plugin: MyThesaurus;
@ -91,7 +91,7 @@ export class MyThesaurusSettingTab extends PluginSettingTab {
}
const content = await this.app.vault.read(file);
try {
verifCSV(
getThesaurus(
content,
this.settings.separator,
i18next.t,
@ -110,16 +110,19 @@ export class MyThesaurusSettingTab extends PluginSettingTab {
});
new Setting(containerEl)
.setName(i18next.t("settings.excludedPath.title"))
.setName(i18next.t("settings.includedPaths.title"))
.setHeading()
.setDesc(
sanitizeHTMLToDom(
`${i18next.t("settings.excludedPath.desc")}<br>${i18next.t("settings.excludedPath.separate")}<br>${i18next.t("settings.excludedPath.regex")}`
`${i18next.t("settings.includedPaths.desc")}<br>${i18next.t("settings.includedPaths.separate")}<br>${i18next.t("settings.includedPaths.regex")}`
)
)
.addTextArea((text) => {
text.setValue(this.settings.excludedPath.join("\n")).onChange(async (value) => {
this.settings.excludedPath = value.split(/[\n,; ]+/).map((path) => path.trim());
text.setValue(this.settings.includedPaths.join("\n")).onChange(async (value) => {
this.settings.includedPaths = value
.split(/[\n,;]+/)
.map((path) => path.trim())
.filter((path) => path.length > 0);
await this.plugin.saveSettings();
});
});

4
src/utils/index.ts Normal file
View file

@ -0,0 +1,4 @@
import { getThesaurus } from "./parse_csv";
import { getTags } from "./parse_file";
export { getThesaurus, getTags };

View file

@ -1,11 +1,11 @@
import type { ColumnName, Separator, Thesaurus, Translation } from "./interfaces";
import type { ColumnName, Separator, Thesaurus, Translation } from "../interfaces";
function verifySeparator(header: string, sep: Separator): boolean {
return header.includes(sep);
}
function searchSeparator(header: string): Separator {
return header.match(/[,;\t|]/)?.[0] as Separator;
return header.match(/[,;\t\|]/)?.[0] as Separator;
}
function getColumn(
@ -33,7 +33,7 @@ function getColumn(
return { indexKey, indexSynonyms };
}
export function verifCSV(
export function getThesaurus(
fileContent: string,
separator: Separator,
ln: Translation,

14
src/utils/parse_file.ts Normal file
View file

@ -0,0 +1,14 @@
import type { Thesaurus } from "../interfaces";
export function getTags(content: string, thesaurus: Thesaurus) {
const tagsToAdd: string[] = [];
for (const tags of Object.keys(thesaurus)) {
const synonyms = thesaurus[tags];
const regex = new RegExp(`\\b(${[...synonyms].join("|")})\\b`, "gi");
if (regex.test(content)) {
tagsToAdd.push(tags);
}
}
return tagsToAdd;
}