mirror of
https://github.com/mara-li/obsidian-my-thesaurus.git
synced 2026-07-22 05:38:22 +00:00
feat: add commands to parse one file
This commit is contained in:
parent
13fd74421d
commit
d49b7b0a97
8 changed files with 163 additions and 22 deletions
|
|
@ -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:"
|
||||
}
|
||||
}
|
||||
|
|
@ -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 :"
|
||||
}
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
102
src/main.ts
102
src/main.ts
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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
4
src/utils/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { getThesaurus } from "./parse_csv";
|
||||
import { getTags } from "./parse_file";
|
||||
|
||||
export { getThesaurus, getTags };
|
||||
|
|
@ -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
14
src/utils/parse_file.ts
Normal 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;
|
||||
}
|
||||
Loading…
Reference in a new issue