From f096f40bf28810ab7d1f520ae975a98b5ffb4f3e Mon Sep 17 00:00:00 2001 From: Mara Date: Sat, 1 Jun 2024 12:19:43 +0200 Subject: [PATCH] refactor: usage of logs & call --- src/GitHub/branch.ts | 32 ++-- src/GitHub/delete.ts | 30 +-- src/GitHub/files.ts | 31 ++- src/GitHub/upload.ts | 41 ++-- src/commands/purge.ts | 3 +- src/commands/share/all_notes.ts | 29 +-- src/commands/share/unique_note.ts | 22 +-- src/conversion/compiler/dataview.ts | 21 +- src/conversion/compiler/embeds.ts | 2 +- src/conversion/file_path.ts | 3 +- src/conversion/find_and_replace_text.ts | 15 +- src/conversion/index.ts | 25 ++- src/conversion/links.ts | 22 ++- src/interfaces/settings.ts | 5 + src/main.ts | 49 ++--- src/settings.ts | 8 +- src/settings/migrate.ts | 24 ++- src/settings/modals/import_export.ts | 30 +-- src/settings/modals/manage_repo.ts | 2 +- src/settings/modals/token_path.ts | 7 +- src/utils/data_validation_test.ts | 15 +- src/utils/index.ts | 243 +----------------------- src/utils/logs.ts | 204 ++++++++++++++++++++ src/utils/status_bar.ts | 11 +- 24 files changed, 412 insertions(+), 462 deletions(-) create mode 100644 src/utils/logs.ts diff --git a/src/GitHub/branch.ts b/src/GitHub/branch.ts index c5f6b44c..3a7cf4ff 100644 --- a/src/GitHub/branch.ts +++ b/src/GitHub/branch.ts @@ -4,11 +4,13 @@ import i18next from "i18next"; import { Notice } from "obsidian"; import { FilesManagement } from "src/GitHub/files"; import type Enveloppe from "src/main"; -import { logs, notif } from "src/utils"; +import type { Logs } from "../utils/logs"; export class GithubBranch extends FilesManagement { + console: Logs; constructor(octokit: Octokit, plugin: Enveloppe) { super(octokit, plugin); + this.console = plugin.console; } /** @@ -48,8 +50,8 @@ export class GithubBranch extends FilesManagement { ref: `refs/heads/${this.branchName}`, sha: shaMainBranch, }); - notif( - { settings: this.settings }, + this.console.notif( + {}, i18next.t("publish.branch.success", { branchStatus: branch.status, repo: prop }) ); return branch.status === 201; @@ -66,8 +68,8 @@ export class GithubBranch extends FilesManagement { const mainBranch = allBranch.data.find( (branch: { name: string }) => branch.name === this.branchName ); - notif( - { settings: this.settings }, + this.console.notif( + {}, i18next.t("publish.branch.alreadyExists", { branchName: this.branchName, repo: prop, @@ -75,7 +77,7 @@ export class GithubBranch extends FilesManagement { ); return !!mainBranch; } catch (e) { - notif({ settings: this.settings, e: true }, e); + this.console.notif({ e: true }, e); return false; } } @@ -100,7 +102,7 @@ export class GithubBranch extends FilesManagement { }); return pr.data.number; } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); //trying to get the last open PR number try { const pr = await this.octokit.request("GET /repos/{owner}/{repo}/pulls", { @@ -111,8 +113,8 @@ export class GithubBranch extends FilesManagement { return pr.data[0]?.number || 0; } catch (e) { // there is no open PR and impossible to create a new one - notif( - { settings: this.settings, e: true }, + this.console.notif( + { e: true }, i18next.t("publish.branch.error", { error: e, repo: prop }) ); return 0; @@ -138,7 +140,7 @@ export class GithubBranch extends FilesManagement { ); return branch.status === 200; } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); return false; } } @@ -171,7 +173,7 @@ export class GithubBranch extends FilesManagement { ); return branch.status === 200; } catch (e) { - notif({ settings: this.settings, e: true }, e); + this.console.notif({ e: true }, e); new Notice(i18next.t("error.mergeconflic")); return false; } @@ -215,7 +217,7 @@ export class GithubBranch extends FilesManagement { } return true; } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); new Notice(i18next.t("error.errorConfig", { repo: prop })); return false; } @@ -252,8 +254,8 @@ export class GithubBranch extends FilesManagement { }); //@ts-ignore if (repoExist.status === 200) { - notif( - { settings: this.settings }, + this.console.notif( + {}, i18next.t("commands.checkValidity.repoExistsTestBranch", { repo }) ); @@ -281,7 +283,7 @@ export class GithubBranch extends FilesManagement { } } } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); new Notice(i18next.t("commands.checkValidity.error", { repo })); break; } diff --git a/src/GitHub/delete.ts b/src/GitHub/delete.ts index e007246e..abb53585 100644 --- a/src/GitHub/delete.ts +++ b/src/GitHub/delete.ts @@ -21,9 +21,10 @@ import { Vault, } from "obsidian"; import type { FilesManagement } from "src/GitHub/files"; -import { logs, notif, trimObject } from "src/utils"; +import { trimObject } from "src/utils"; import { isAttachment, verifyRateLimitAPI } from "src/utils/data_validation_test"; import { frontmatterSettingsRepository } from "src/utils/parse_frontmatter"; +import type Enveloppe from "../main"; /** * Delete file from github, based on a list of file in the original vault @@ -71,21 +72,22 @@ async function deleteFromGithubOneRepo( repoProperties: MonoRepoProperties ): Promise { const repo = repoProperties.frontmatter; + const pconsole = filesManagement.console; if (repo.dryRun.autoclean) return cleanDryRun(silent, filesManagement, repoProperties); if (!repo.autoclean) return { success: false, deleted: [], undeleted: [] }; const getAllFile = await filesManagement.getAllFileFromRepo(branchName, repo); const settings = filesManagement.settings; - const octokit = filesManagement.octokit; + const { octokit, plugin } = filesManagement; const filesInRepo = await filterGithubFile(getAllFile, settings, repo); if ( (settings.github.rateLimit === 0 || filesInRepo.length > settings.github.rateLimit) && - (await verifyRateLimitAPI(octokit, settings, false, filesInRepo.length)) === 0 + (await verifyRateLimitAPI(octokit, plugin, false, filesInRepo.length)) === 0 ) { console.warn("Rate limited exceeded, please try again later"); return { success: false, deleted: [], undeleted: [] }; } if (filesInRepo.length === 0) { - logs({ settings }, `No file to delete in ${repo.owner}/${repo.repo}`); + pconsole.logs({}, `No file to delete in ${repo.owner}/${repo.repo}`); return { success: false, deleted: [], undeleted: [] }; } const allSharedFiles = filesManagement.getAllFileWithPath( @@ -119,12 +121,12 @@ async function deleteFromGithubOneRepo( const isNeedToBeDeleted = isInObsidian ? isMarkdownForAnotherRepo : true; if (isNeedToBeDeleted) { const checkingIndex = file.file.contains(settings.upload.folderNote.rename) - ? await checkIndexFiles(octokit, settings, file.file, repo) + ? await checkIndexFiles(octokit, plugin, file.file, repo) : false; try { if (!checkingIndex) { - notif( - { settings }, + pconsole.notif( + {}, `trying to delete file : ${file.file} from ${repo.owner}/${repo.repo}` ); const reponse = await octokit.request( @@ -147,7 +149,7 @@ async function deleteFromGithubOneRepo( } } } catch (e) { - if (!(e instanceof DOMException)) logs({ settings, e: true }, e); + if (!(e instanceof DOMException)) pconsole.logs({ e: true }, e); } } } @@ -253,7 +255,7 @@ function parseYamlFrontmatter(contents: string): unknown { async function checkIndexFiles( octokit: Octokit, - settings: EnveloppeSettings, + plugin: Enveloppe, path: string, prop: Properties ): Promise { @@ -284,7 +286,7 @@ async function checkIndexFiles( } } catch (e) { if (!(e instanceof DOMException)) { - notif({ settings, e: true }, e); + plugin.console.notif({ e: true }, e); return false; } } @@ -296,8 +298,8 @@ function cleanDryRun( filesManagement: FilesManagement, repoProperties: MonoRepoProperties ): Deleted { - const { vault, settings } = filesManagement; - const app = filesManagement.plugin.app; + const { vault, settings, console, plugin } = filesManagement; + const app = plugin.app; const repo = repoProperties.frontmatter; const dryRunFolderPath = normalizePath( repo.dryRun.folderName @@ -358,8 +360,8 @@ function cleanDryRun( ? indexFileDryRun(file as TFile, app.metadataCache) : false; if (!indexFile) { - notif( - { settings }, + console.notif( + {}, `[DRYRUN] trying to delete file : ${file.path} from ${dryRunFolderPath}` ); vault.trash(file, false); diff --git a/src/GitHub/files.ts b/src/GitHub/files.ts index d2687809..e7ceb422 100644 --- a/src/GitHub/files.ts +++ b/src/GitHub/files.ts @@ -12,22 +12,23 @@ import { getAPI, type Link } from "obsidian-dataview"; import { getImagePath, getReceiptFolder } from "src/conversion/file_path"; import Publisher from "src/GitHub/upload"; import type Enveloppe from "src/main"; -import { logs } from "src/utils"; import { isAttachment, isShared } from "src/utils/data_validation_test"; import { frontmatterFromFile, getFrontmatterSettings, getProperties, } from "src/utils/parse_frontmatter"; +import type { Logs } from "../utils/logs"; export class FilesManagement extends Publisher { /** * @param {Octokit} octokit The octokit instance * @param {EnveloppeSettings} plugin The plugin */ - + console: Logs; constructor(octokit: Octokit, plugin: Enveloppe) { super(octokit, plugin); + this.console = plugin.console; } /** @@ -45,7 +46,7 @@ export class FilesManagement extends Publisher { sharedFile.push(file); } } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); } } return sharedFile; @@ -73,7 +74,7 @@ export class FilesManagement extends Publisher { files.push(file as TFile); } } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); } } } @@ -220,7 +221,7 @@ export class FilesManagement extends Publisher { linkedFiles.push(thisLinkedFile); } } catch (e) { - logs({ settings: this.settings }, e); + this.console.logs({}, e); } } } @@ -281,11 +282,7 @@ export class FilesManagement extends Publisher { embedList.push(thisEmbed); } } catch (e) { - logs( - { settings: this.settings, e: true }, - `Error with this links : ${embedCache.link}`, - e - ); + this.console.logs({ e: true }, `Error with this links : ${embedCache.link}`, e); } } return [...new Set(embedList)]; @@ -347,11 +344,7 @@ export class FilesManagement extends Publisher { fromWhat ) as TFile; } catch (e) { - logs( - { settings: this.settings, e: true }, - `Error with this file : ${embed.displayText}`, - e - ); + this.console.logs({ e: true }, `Error with this file : ${embed.displayText}`, e); } return undefined; } @@ -415,7 +408,7 @@ export class FilesManagement extends Publisher { } } } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); } return filesInRepo; } @@ -578,7 +571,6 @@ export class FilesManagement extends Publisher { * Get all edited file since the last sync, compared to the github repo * @param {ConvertedLink[]} allFileWithPath - all shared file with their path * @param {GithubRepo[]} githubSharedFiles - all file in the github repo - * @param {Vault} vault - vault * @param {TFile[]} newFiles - new file to add to the repo * @return {Promise} newFiles - File to add in the repo */ @@ -600,12 +592,11 @@ export class FilesManagement extends Publisher { fileInVault instanceof TFile && fileInVault?.extension === "md" && !fileInVault?.name.endsWith(".excalidraw.md"); - console.log(fileInVault, isMarkdown, repoEditedTime, githubSharedFile); if (fileInVault && isMarkdown) { const vaultEditedTime = new Date(fileInVault.stat.mtime); if (repoEditedTime && vaultEditedTime > repoEditedTime) { - logs( - { settings: this.settings }, + this.console.logs( + {}, `edited file : ${fileInVault.path} / ${vaultEditedTime} vs ${repoEditedTime}` ); newFiles.push(fileInVault); diff --git a/src/GitHub/upload.ts b/src/GitHub/upload.ts index 3a763b1e..d8b1a59b 100644 --- a/src/GitHub/upload.ts +++ b/src/GitHub/upload.ts @@ -29,7 +29,6 @@ import { getImagePath, getReceiptFolder } from "src/conversion/file_path"; import { deleteFromGithub } from "src/GitHub/delete"; import { FilesManagement } from "src/GitHub/files"; import type Enveloppe from "src/main"; -import { logs, noticeMobile, notif, notifError } from "src/utils"; import { checkEmptyConfiguration, checkIfRepoIsInAnother, @@ -45,6 +44,7 @@ import { } from "src/utils/parse_frontmatter"; import { ShareStatusBar } from "src/utils/status_bar"; import merge from "ts-deepmerge"; +import type { Logs } from "../utils/logs"; /** Class to manage the branch * @extends FilesManagement @@ -57,6 +57,7 @@ export default class Publisher { metadataCache: MetadataCache; settings: EnveloppeSettings; branchName: string; + console: Logs; /** * Class to manage the branch @@ -71,6 +72,7 @@ export default class Publisher { this.octokit = octokit; this.plugin = plugin; this.branchName = plugin.branchName; + this.console = plugin.console; } /** @@ -90,7 +92,12 @@ export default class Publisher { const fileError: string[] = []; if (linkedFiles.length > 0) { const statusBarItems = this.plugin.addStatusBarItem(); - const statusBar = new ShareStatusBar(statusBarItems, linkedFiles.length, true); + const statusBar = new ShareStatusBar( + statusBarItems, + linkedFiles.length, + true, + this.console + ); const prop = properties.frontmatter.prop; const repoProperties: MonoRepoProperties = { frontmatter: properties.frontmatter.prop, @@ -129,13 +136,13 @@ export default class Publisher { } catch (e) { new Notice(i18next.t("error.unablePublishNote", { file: file.name })); fileError.push(file.name); - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); } } statusBar.finish(8000); } catch (e) { - logs({ settings: this.settings, e: true }, e); - notifError(prop); + this.console.logs({ e: true }, e); + this.console.notifError(prop); statusBar.error(prop); } } @@ -182,7 +189,7 @@ export default class Publisher { return false; } try { - logs({ settings: this.settings }, `Publishing file: ${file.path}`); + this.console.logs({}, `Publishing file: ${file.path}`); fileHistory.push(file); const frontmatterSettingsFromFile = getFrontmatterSettings( frontmatter, @@ -227,7 +234,7 @@ export default class Publisher { multiRepMsg += `[${repo.owner}/${repo.repo}/${repo.branch}] `; } const msg = `Publishing ${file.name} to ${multiRepMsg}`; - logs({ settings: this.settings }, msg); + this.console.logs({}, msg); const fileDeleted: Deleted[] = []; const updated: UploadedFiles[][] = []; const fileError: string[] = []; @@ -260,7 +267,7 @@ export default class Publisher { } return { deleted: fileDeleted[0], uploaded: updated[0], error: fileError }; } catch (e) { - logs({ settings: this.settings, e: true }, e); + this.console.logs({ e: true }, e); return false; } } @@ -299,11 +306,15 @@ export default class Publisher { }); embedFiles = await this.cleanLinkedImageIfAlreadyInRepo(embedFiles, properties); const repo = properties.frontmatter.prop; - notif( - { settings: this.settings }, + this.console.notif( + {}, `Upload ${file.name}:${path} on ${repo.owner}/${repo.repo}:${this.branchName}` ); - const notifMob = noticeMobile("wait", LOADING_ICON, i18next.t("statusBar.loading")); + const notifMob = this.console.noticeMobile( + "wait", + LOADING_ICON, + i18next.t("statusBar.loading") + ); let deleted: Deleted = { success: false, deleted: [], @@ -406,7 +417,7 @@ export default class Publisher { result.isUpdated = true; } } catch { - logs({ settings: this.settings }, i18next.t("error.normal")); + this.console.logs({}, i18next.t("error.normal")); } payload.message = msg; @@ -512,7 +523,7 @@ export default class Publisher { const contentBase64 = Base64.encode(text).toString(); return await this.upload(contentBase64, path, title, prop); } catch (e) { - notif({ settings: this.settings, e: true }, e); + this.console.notif({ e: true }, e); return undefined; } } @@ -655,8 +666,8 @@ export default class Publisher { ) { newLinkedFiles.push(file); } else - logs( - { settings: this.settings }, + this.console.logs( + {}, i18next.t("error.alreadyExists", { file: file.name }) ); } diff --git a/src/commands/purge.ts b/src/commands/purge.ts index 55d3d6fd..70fb8ce9 100644 --- a/src/commands/purge.ts +++ b/src/commands/purge.ts @@ -5,7 +5,6 @@ import type { GithubBranch } from "src/GitHub/branch"; import { deleteFromGithub } from "src/GitHub/delete"; import type Enveloppe from "src/main"; import { ListChangedFiles } from "src/settings/modals/list_changed"; -import { notif } from "src/utils"; import { checkRepositoryValidityWithProperties } from "src/utils/data_validation_test"; import { frontmatterSettingsRepository, @@ -76,7 +75,7 @@ async function purge( if (PublisherManager.settings.plugin.displayModalRepoEditing) new ListChangedFiles(PublisherManager.plugin.app, deleted).open(); } catch (e) { - notif({ settings: PublisherManager.settings, e: true }, e); + PublisherManager.plugin.console.notif({ e: true }, e); } } diff --git a/src/commands/share/all_notes.ts b/src/commands/share/all_notes.ts index 9889c31c..8fc022bb 100644 --- a/src/commands/share/all_notes.ts +++ b/src/commands/share/all_notes.ts @@ -12,13 +12,7 @@ import type { GithubBranch } from "src/GitHub/branch"; import { deleteFromGithub } from "src/GitHub/delete"; import type Enveloppe from "src/main"; import { ListChangedFiles } from "src/settings/modals/list_changed"; -import { - createListEdited, - getSettingsOfMetadataExtractor, - logs, - notifError, - publisherNotification, -} from "src/utils"; +import { createListEdited, getSettingsOfMetadataExtractor } from "src/utils"; import { checkRepositoryValidityWithProperties } from "src/utils/data_validation_test"; import { frontmatterSettingsRepository, @@ -102,7 +96,13 @@ export async function shareAllMarkedNotes( createGithubBranch: boolean = true, sourceFrontmatter: FrontMatterCache | undefined | null = null ) { - const statusBar = new ShareStatusBar(statusBarItems, sharedFiles.length); + const statusBar = new ShareStatusBar( + statusBarItems, + sharedFiles.length, + undefined, + PublisherManager.console + ); + const plugin = PublisherManager.plugin; const prop = monoRepo.frontmatter; try { const fileError: string[] = []; @@ -134,7 +134,7 @@ export async function shareAllMarkedNotes( } catch (e) { fileError.push(sharedFile.name); new Notice(i18next.t("error.unablePublishNote", { file: sharedFile.name })); - logs({ settings: PublisherManager.settings, e: true }, e); + plugin.console.logs({ e: true }, e); } } statusBar.finish(8000); @@ -157,17 +157,22 @@ export async function shareAllMarkedNotes( } const update = await PublisherManager.updateRepository(prop); if (update) { - await publisherNotification(PublisherManager, noticeValue, settings, prop); + await plugin.console.publisherNotification( + PublisherManager, + noticeValue, + settings, + prop + ); if (settings.plugin.displayModalRepoEditing) { const listEdited = createListEdited(listStateUploaded, deleted, fileError); new ListChangedFiles(PublisherManager.plugin.app, listEdited).open(); } } else { - notifError(prop); + plugin.console.notifError(prop); } } } catch (error) { - logs({ settings: PublisherManager.settings, e: true }, error); + plugin.console.logs({ e: true }, error); const errorFrag = document.createDocumentFragment(); errorFrag.createSpan({ cls: ["error", "obsidian-publisher", "icons", "notification"], diff --git a/src/commands/share/unique_note.ts b/src/commands/share/unique_note.ts index 0dab3779..f715d173 100644 --- a/src/commands/share/unique_note.ts +++ b/src/commands/share/unique_note.ts @@ -10,14 +10,7 @@ import { import type { GithubBranch } from "src/GitHub/branch"; import type Enveloppe from "src/main"; import { ListChangedFiles } from "src/settings/modals/list_changed"; -import { - createLink, - createListEdited, - getSettingsOfMetadataExtractor, - logs, - notifError, - publisherNotification, -} from "src/utils"; +import { createLink, createListEdited, getSettingsOfMetadataExtractor } from "src/utils"; import { checkRepositoryValidityWithProperties, isShared, @@ -122,7 +115,12 @@ export async function shareOneNote( settings.github.dryRun.enable ); if (update) { - await publisherNotification(PublisherManager, title, settings, prop); + await plugin.console.publisherNotification( + PublisherManager, + title, + settings, + prop + ); await createLink(file, multiRepo, plugin); if (settings.plugin.displayModalRepoEditing) { const listEdited = createListEdited( @@ -133,13 +131,13 @@ export async function shareOneNote( new ListChangedFiles(app, listEdited).open(); } } else { - notifError(prop); + plugin.console.notifError(prop); } } } catch (error) { if (!(error instanceof DOMException)) { - logs({ settings, e: true }, error); - notifError(getProperties(plugin, repository, frontmatter, true)); + plugin.console.logs({ e: true }, error); + plugin.console.notifError(getProperties(plugin, repository, frontmatter, true)); } } } diff --git a/src/conversion/compiler/dataview.ts b/src/conversion/compiler/dataview.ts index e25ac2d5..d9ccbae0 100644 --- a/src/conversion/compiler/dataview.ts +++ b/src/conversion/compiler/dataview.ts @@ -23,7 +23,6 @@ import { escapeRegex, } from "src/conversion/links"; import type Enveloppe from "src/main"; -import { logs, notif } from "src/utils"; class DataviewCompiler { settings: EnveloppeSettings; @@ -189,7 +188,7 @@ export async function convertDataviewQueries( const { dataviewJsMatches, inlineMatches, inlineJsMatches } = compiler.matches(); if (!matches && !inlineMatches && !dataviewJsMatches && !inlineJsMatches) { - logs({ settings }, "No dataview queries found"); + plugin.console.logs({}, "No dataview queries found"); return replacedText; } const error = i18next.t("error.dataview"); @@ -203,8 +202,8 @@ export async function convertDataviewQueries( const markdown = await compiler.dataviewDQL(queryBlock[1]); replacedText = replacedText.replace(block, markdown); } catch (e) { - logs({ settings, e: true }, e); - notif({ settings }, error); + plugin.console.logs({ e: true }, e); + plugin.console.notif({}, error); return queryBlock[0]; } } @@ -215,8 +214,8 @@ export async function convertDataviewQueries( const markdown = await compiler.dataviewJS(queryBlock[1]); replacedText = replacedText.replace(block, markdown); } catch (e) { - logs({ settings, e: true }, e); - notif({ settings }, error); + plugin.console.logs({ e: true }, e); + plugin.console.notif({}, error); return queryBlock[0]; } } @@ -229,8 +228,8 @@ export async function convertDataviewQueries( const markdown = await compiler.inlineDQLDataview(query); replacedText = replacedText.replace(code, markdown); } catch (e) { - logs({ settings, e: true }, e); - notif({ settings }, error); + plugin.console.logs({ e: true }, e); + plugin.console.notif({}, error); return inlineQuery[0]; } } @@ -241,8 +240,8 @@ export async function convertDataviewQueries( const markdown = await compiler.inlineDataviewJS(inlineJsQuery[1].trim()); replacedText = replacedText.replace(code, markdown); } catch (e) { - logs({ settings, e: true }, e); - notif({ settings }, error); + plugin.console.logs({ e: true }, e); + plugin.console.notif({}, error); return inlineJsQuery[0]; } } @@ -284,7 +283,7 @@ async function convertDataviewLinks( md, properties.frontmatter.general, dataviewPath, - properties.plugin.settings, + properties.plugin, frontmatter ); } diff --git a/src/conversion/compiler/embeds.ts b/src/conversion/compiler/embeds.ts index 11e6d085..ea28567a 100644 --- a/src/conversion/compiler/embeds.ts +++ b/src/conversion/compiler/embeds.ts @@ -348,7 +348,7 @@ export async function convertInlineDataview( } } if (valueToAdd.length > 0) { - return addToYaml(text, valueToAdd.filter(Boolean), plugin, { + return addToYaml(text, valueToAdd.filter(Boolean), { properties: null, file: sourceFile, }); diff --git a/src/conversion/file_path.ts b/src/conversion/file_path.ts index 4d5efb7c..5e4671a2 100644 --- a/src/conversion/file_path.ts +++ b/src/conversion/file_path.ts @@ -17,7 +17,6 @@ import { } from "obsidian"; import { createRegexFromText } from "src/conversion/find_and_replace_text"; import type Enveloppe from "src/main"; -import { logs } from "src/utils"; import { checkIfRepoIsInAnother, isInternalShared, @@ -97,7 +96,7 @@ export async function createRelativePath( targetRepo ); const shared = isInternalShared(frontmatterTarget, properties, targetFile.linked); - logs({ settings }, `Shared: ${shared} for ${targetFile.linked.path}`); + properties.plugin.console.logs({}, `Shared: ${shared} for ${targetFile.linked.path}`); if ( targetFile.linked.extension === "md" && !targetFile.linked.name.includes("excalidraw") && diff --git a/src/conversion/find_and_replace_text.ts b/src/conversion/find_and_replace_text.ts index 989adbfd..54cbc2ed 100644 --- a/src/conversion/find_and_replace_text.ts +++ b/src/conversion/find_and_replace_text.ts @@ -1,6 +1,6 @@ -import { FIND_REGEX, type EnveloppeSettings } from "@interfaces"; +import { FIND_REGEX } from "@interfaces"; import { escapeRegex } from "src/conversion/links"; -import { logs } from "src/utils"; +import type Enveloppe from "../main"; /** * Convert a string to a regex object when the string is in the form of a regex (enclosed by /) @@ -28,9 +28,10 @@ export function createRegexFromText(toReplace: string, withflag?: string): RegEx */ export default function findAndReplaceText( text: string, - settings: EnveloppeSettings, + plugin: Enveloppe, after?: boolean ): string { + const settings = plugin.settings; if (!settings.conversion.censorText) { return text; } @@ -45,11 +46,11 @@ export default function findAndReplaceText( const regex = createRegexFromText(toReplace, censor.flags); text = censor.inCodeBlocks ? text.replace(regex, replaceWith) - : replaceText(text, regex, replaceWith, settings); + : replaceText(text, regex, replaceWith, plugin); } else { text = censor.inCodeBlocks ? text.replace(toReplace, replaceWith) - : replaceText(text, toReplace, replaceWith, settings); + : replaceText(text, toReplace, replaceWith, plugin); } } } @@ -70,7 +71,7 @@ export function replaceText( fileContent: string, pattern: string | RegExp, replaceWith: string, - settings: EnveloppeSettings, + plugin: Enveloppe, links?: boolean ): string { let regexWithString: string; @@ -97,7 +98,7 @@ export function replaceText( const replaceWithParsed = JSON.parse(`"${replaceWith}"`); return match.replace(pattern, replaceWithParsed); } catch (e) { - logs({ settings, e: true }, e); + plugin.console.logs({ e: true }, e); return match.replace(pattern, replaceWith); } } diff --git a/src/conversion/index.ts b/src/conversion/index.ts index a54613eb..903c2719 100644 --- a/src/conversion/index.ts +++ b/src/conversion/index.ts @@ -19,7 +19,6 @@ import { convertDataviewQueries } from "src/conversion/compiler/dataview"; import { bakeEmbeds, convertInlineDataview } from "src/conversion/compiler/embeds"; import { convertToInternalGithub, convertWikilinks } from "src/conversion/links"; import type Enveloppe from "src/main"; -import { notif } from "src/utils"; import { isFolderNote } from "src/utils/data_validation_test"; import findAndReplaceText from "./find_and_replace_text"; @@ -37,7 +36,7 @@ import findAndReplaceText from "./find_and_replace_text"; export function addHardLineBreak( text: string, - settings: EnveloppeSettings, + plugin: Enveloppe, frontmatter: PropertiesConversion ): string { try { @@ -47,12 +46,12 @@ export function addHardLineBreak( } return text; } catch (e) { - notif({ settings, e: true }, e); + plugin.console.notif({ e: true }, e); return text; } } -function tagsToYaml(toAdd: string[], settings: EnveloppeSettings, yaml: any) { +function tagsToYaml(toAdd: string[], plugin: Enveloppe, yaml: any) { if (yaml.tag) { try { toAdd = [ @@ -63,7 +62,7 @@ function tagsToYaml(toAdd: string[], settings: EnveloppeSettings, yaml: any) { ]; delete yaml.tag; } catch (e) { - notif({ settings, e: true }, e); + plugin.console.notif({ e: true }, e); } } if (yaml.tags) { @@ -75,7 +74,7 @@ function tagsToYaml(toAdd: string[], settings: EnveloppeSettings, yaml: any) { ]), ]; } catch (e) { - notif({ settings, e: true }, e); + plugin.console.notif({ e: true }, e); } } else { yaml.tags = toAdd; @@ -95,7 +94,6 @@ function tagsToYaml(toAdd: string[], settings: EnveloppeSettings, yaml: any) { export function addToYaml( text: string, toAdd: string[], - plugin: Enveloppe, folderNoteParaMeters: { properties: MultiProperties | null; file: TFile } ): string { const properties = folderNoteParaMeters?.properties; @@ -106,11 +104,10 @@ export function addToYaml( !properties.plugin.settings.upload.folderNote.addTitle) ) return text; - const { settings } = plugin; let yamlObject = parseYaml(exists ? frontmatter : "{}"); try { if (yamlObject && toAdd.length > 0) { - yamlObject = tagsToYaml(toAdd, settings, yamlObject); + yamlObject = tagsToYaml(toAdd, properties.plugin, yamlObject); } if (folderNoteParaMeters?.properties) { yamlObject = titleToYaml( @@ -183,7 +180,7 @@ export async function processYaml( const metadataCache = app.metadataCache; const toAdd = inlineTags(settings, file, metadataCache, frontmatter); const folderNoteParaMeters = { properties: multiProperties, file }; - return addToYaml(text, toAdd, plugin, folderNoteParaMeters); + return addToYaml(text, toAdd, folderNoteParaMeters); } /** @@ -200,19 +197,19 @@ export async function mainConverting( const { plugin } = properties; if (properties.frontmatter.general.removeEmbed === "bake") text = await bakeEmbeds(file, new Set(), properties, null, linkedFiles); - text = findAndReplaceText(text, plugin.settings, false); + text = findAndReplaceText(text, plugin, false); text = await processYaml(file, frontmatter, text, properties); text = await convertToInternalGithub(text, linkedFiles, file, frontmatter, properties); text = convertWikilinks( text, properties.frontmatter.general, linkedFiles, - plugin.settings, + plugin, frontmatter ); text = await convertDataviewQueries(text, file.path, frontmatter, file, properties); text = await convertInlineDataview(text, plugin, file); - text = addHardLineBreak(text, plugin.settings, properties.frontmatter.general); + text = addHardLineBreak(text, plugin, properties.frontmatter.general); - return findAndReplaceText(text, plugin.settings, true); + return findAndReplaceText(text, plugin, true); } diff --git a/src/conversion/links.ts b/src/conversion/links.ts index 989bce4d..f65ad0c4 100644 --- a/src/conversion/links.ts +++ b/src/conversion/links.ts @@ -13,6 +13,7 @@ import { } from "src/conversion/file_path"; import { replaceText } from "src/conversion/find_and_replace_text"; import { isAttachment, noTextConversion } from "src/utils/data_validation_test"; +import type Enveloppe from "../main"; type IsEmbed = { cond: boolean; @@ -33,11 +34,11 @@ export function convertWikilinks( fileContent: string, conditionConvert: PropertiesConversion, linkedFiles: LinkedNotes[], - settings: EnveloppeSettings, + plugin: Enveloppe, sourceFrontmatter: FrontMatterCache | undefined | null ): string { if (noTextConversion(conditionConvert)) return fileContent; - + const settings = plugin.settings; const wikiRegex = /!?\[\[.*?\]\]/g; const wikiMatches = fileContent.match(wikiRegex); if (wikiMatches) { @@ -65,7 +66,7 @@ export function convertWikilinks( linkedFile, conditionConvert, isEmbed, - settings, + plugin, isNotAttachment, fileContent, wikiMatch, @@ -81,7 +82,7 @@ export function convertWikilinks( wikiMatch, path, conditionConvert, - settings, + plugin, fileContent ); } @@ -140,7 +141,7 @@ function isLinkedFile( linkedFile: LinkedNotes, conditionConvert: PropertiesConversion, isEmbed: IsEmbed, - settings: EnveloppeSettings, + plugin: Enveloppe, isNotAttachment: boolean, fileContent: string, wikiMatch: string, @@ -148,7 +149,7 @@ function isLinkedFile( ): string { let altText: string; let linkCreator = wikiMatch; - + const settings = plugin.settings; if (linkedFile.linked.extension === "md") { altText = linkedFile.altText ? linkedFile.altText : linkedFile.linked.basename; altText = altText.replace("#", " > ").replace(/ > \^\w*/, ""); @@ -187,7 +188,7 @@ function isLinkedFile( linkCreator = altText; if ((!conditionConvert.attachment && !isNotAttachment) || removeEmbed) linkCreator = ""; - return replaceText(fileContent, wikiMatch, linkCreator, settings, true); + return replaceText(fileContent, wikiMatch, linkCreator, plugin, true); } /** * Will strictly convert the the links without a found linked notes (usefull when links are already edited using the markdown conversion or regex) @@ -206,7 +207,7 @@ function strictStringConversion( wikiMatch: string, fileName: string, conditionConvert: PropertiesConversion, - settings: EnveloppeSettings, + plugin: Enveloppe, fileContent: string ): string { const altMatch = wikiMatch.match(/(\|).*(]])/); @@ -226,6 +227,7 @@ function strictStringConversion( isEmbed.char = `${conditionConvert.charEmbedLinks} `; linkCreator = linkCreator.replace("!", isEmbed.char); } + const settings = plugin.settings; linkCreator = conditionConvert.convertWiki ? createMarkdownLinks(fileName, isEmbed.char, altLink, settings) : addAltForWikilinks(altMatch as RegExpMatchArray, linkCreator); @@ -235,7 +237,7 @@ function strictStringConversion( if ((!conditionConvert.attachment && !isNotAttachment) || removeEmbed) { linkCreator = ""; } - return replaceText(fileContent, wikiMatch, linkCreator, settings, true); + return replaceText(fileContent, wikiMatch, linkCreator, plugin, true); } /** @@ -392,7 +394,7 @@ export async function convertToInternalGithub( newLink = `[${altText}](${encodeURI(pathInGithub)})`; //encode to URI for compatibility with github } newLink = addAltText(newLink, linkedFile); - fileContent = replaceText(fileContent, link, newLink, settings, true); + fileContent = replaceText(fileContent, link, newLink, properties.plugin, true); } } } diff --git a/src/interfaces/settings.ts b/src/interfaces/settings.ts index 9fa3c286..f2b19ff0 100644 --- a/src/interfaces/settings.ts +++ b/src/interfaces/settings.ts @@ -296,6 +296,11 @@ export interface PluginBehavior { * @example `Set: [[frontmatter]]` */ setFrontmatterKey: string; + /** + * Save the folder of the plugin + * @default `.obsidian/plugins/%pluginID%` + */ + manifestDir?: string; } /** diff --git a/src/main.ts b/src/main.ts index 4356427b..7c6f1aaa 100644 --- a/src/main.ts +++ b/src/main.ts @@ -36,12 +36,13 @@ import { GithubBranch } from "src/GitHub/branch"; import { resources, translationLanguage } from "src/i18n/i18next"; import { EnveloppeSettingsTab } from "src/settings"; import { migrateSettings, type OldSettings } from "src/settings/migrate"; -import { createTokenPath, monkeyPatchConsole, notif } from "src/utils"; +import { createTokenPath } from "src/utils"; import { checkRepositoryValidity, verifyRateLimitAPI, } from "src/utils/data_validation_test"; import merge from "ts-deepmerge"; +import { Logs } from "./utils/logs"; /** * Main class of the plugin @@ -52,7 +53,7 @@ export default class Enveloppe extends Plugin { settings!: EnveloppeSettings; branchName: string = ""; repositoryFrontmatter: SetRepositoryFrontmatter = {}; - originalConsole: any; + console: Logs = new Logs(this); /** * Get the title field of a file @@ -178,7 +179,7 @@ export default class Enveloppe extends Plugin { return defaultToken; } } catch (e) { - notif({ settings: this.settings, e: true }, e); + this.console.notif({ e: true }, e); return ""; } return ""; @@ -215,19 +216,15 @@ export default class Enveloppe extends Plugin { returnEmptyString: false, }); - console.info( + await this.loadSettings(); + this.console = new Logs(this); + this.console.logs( + {}, dedent(`[Obsidian Enveloppe] v.${this.manifest.version} (lang: ${translationLanguage}) loaded. * You can hide HTTP logs in the console with checking the "Hide network" in the console settings. * See here: https://developer.chrome.com/docs/devtools/console/reference#network`) ); - await this.loadSettings(); - this.originalConsole = { - debug: console.debug, - error: console.error, - info: console.info, - log: console.log, - warn: console.warn, - }; + if ( !this.settings.plugin.dev && (await this.app.vault.adapter.exists( @@ -258,7 +255,7 @@ export default class Enveloppe extends Plugin { ); this.settings.github.rateLimit = await verifyRateLimitAPI( octokit.octokit, - this.settings, + this, false ); await this.saveSettings(); @@ -276,10 +273,7 @@ export default class Enveloppe extends Plugin { null, false ); - repository.rateLimit = await verifyRateLimitAPI( - repoOctokit.octokit, - this.settings - ); + repository.rateLimit = await verifyRateLimitAPI(repoOctokit.octokit, this); } if (repository.set) { @@ -317,10 +311,7 @@ export default class Enveloppe extends Plugin { name: i18next.t("commands.checkValidity.rateLimit.command"), callback: async () => { const octokit = await this.reloadOctokit(); - this.settings.github.rateLimit = await verifyRateLimitAPI( - octokit.octokit, - this.settings - ); + this.settings.github.rateLimit = await verifyRateLimitAPI(octokit.octokit, this); await this.saveSettings(); }, }); @@ -344,7 +335,6 @@ export default class Enveloppe extends Plugin { this.addCommand(refreshOpenedSet(this)); this.addCommand(refreshAllSets(this)); this.app.vault.adapter.removeFile(normalizePath(`${this.manifest.dir}/logs.txt`)); - monkeyPatchConsole(this); } /** @@ -352,21 +342,6 @@ export default class Enveloppe extends Plugin { */ onunload() { console.info("[Obsidian Enveloppe] Unloaded"); - this.returnNormalConsoleState(); - } - - async returnNormalConsoleState() { - try { - await this.app.vault.adapter.remove(normalizePath(`${this.manifest.dir}/logs.txt`)); - } catch (_e) { - //pass - } - - console.log = this.originalConsole.log; - console.info = this.originalConsole.info; - console.warn = this.originalConsole.warn; - console.error = this.originalConsole.error; - console.debug = this.originalConsole.debug; } /** diff --git a/src/settings.ts b/src/settings.ts index c1436fc0..9843f798 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -46,7 +46,6 @@ import { checkRepositoryValidity, verifyRateLimitAPI, } from "src/utils/data_validation_test"; -import { monkeyPatchConsole } from "./utils"; export class EnveloppeSettingsTab extends PluginSettingTab { plugin: EnveloppePlugin; @@ -355,7 +354,7 @@ export class EnveloppeSettingsTab extends PluginSettingTab { ); this.settings.github.rateLimit = await verifyRateLimitAPI( octokit.octokit, - this.settings + this.plugin ); await this.plugin.saveSettings(); }) @@ -1380,8 +1379,7 @@ export class EnveloppeSettingsTab extends PluginSettingTab { .addToggle((toggle) => toggle.setValue(pluginSettings.dev ?? false).onChange(async (value) => { pluginSettings.dev = value; - if (!value) await this.plugin.returnNormalConsoleState(); - else monkeyPatchConsole(this.plugin); + await this.plugin.saveSettings(); }) ); @@ -1424,7 +1422,7 @@ export class EnveloppeSettingsTab extends PluginSettingTab { try { return JSON.parse(JSON.stringify(object)); } catch (_e) { - console.log("error with stringify for", object); + this.plugin.console.logs({ e: true }, "error with stringify for", object); } } } diff --git a/src/settings/migrate.ts b/src/settings/migrate.ts index b63aa694..f482dc13 100644 --- a/src/settings/migrate.ts +++ b/src/settings/migrate.ts @@ -8,7 +8,7 @@ import { import i18next from "i18next"; import { normalizePath } from "obsidian"; import type Enveloppe from "src/main"; -import { createTokenPath, logs } from "src/utils"; +import { createTokenPath } from "src/utils"; export interface OldSettings { githubRepo: string; @@ -82,7 +82,8 @@ async function migrateReplaceTitle(plugin: Enveloppe) { if (plugin.settings.upload.replaceTitle instanceof Array) { return; } - logs({ settings: plugin.settings }, i18next.t("informations.migrating.fileReplace")); + + plugin.console.logs({}, i18next.t("informations.migrating.fileReplace")); plugin.settings.upload.replaceTitle = [plugin.settings.upload.replaceTitle]; await plugin.saveSettings(); } @@ -96,7 +97,7 @@ async function migrateSubFolder(plugin: Enveloppe) { (e) => e.regex === `/${plugin.settings.upload.subFolder}` ) ) { - logs({ settings: plugin.settings }, i18next.t("informations.migrating.subFolder")); + plugin.console.logs({}, i18next.t("informations.migrating.subFolder")); //@ts-ignore if (plugin.settings.upload.subFolder.length > 0) { plugin.settings.upload.replacePath.push({ @@ -125,7 +126,7 @@ async function migrateCensor(plugin: Enveloppe) { } async function migrateWorFlow(plugin: Enveloppe) { - logs({ settings: plugin.settings }, "Migrating workflow"); + plugin.console.logs({}, "Migrating workflow"); //@ts-ignore if (!plugin.settings.github.worflow) { return; @@ -144,14 +145,11 @@ async function migrateWorFlow(plugin: Enveloppe) { } export async function migrateToken(plugin: Enveloppe, token?: string, repo?: string) { - logs({ settings: plugin.settings }, "migrating token"); + plugin.console.logs({}, "migrating token"); const tokenPath = createTokenPath(plugin, plugin.settings.github.tokenPath); //@ts-ignore if (plugin.settings.github.token && !token) { - logs( - { settings: plugin.settings }, - `Moving the GitHub Token in the file : ${tokenPath}` - ); + plugin.console.logs({}, `Moving the GitHub Token in the file : ${tokenPath}`); //@ts-ignore token = plugin.settings.github.token; //@ts-ignore @@ -161,8 +159,8 @@ export async function migrateToken(plugin: Enveloppe, token?: string, repo?: str if (token === undefined) { return; } - logs( - { settings: plugin.settings }, + plugin.console.logs( + {}, `Moving the GitHub Token in the file : ${tokenPath} for ${ repo ?? "default" } repository` @@ -217,7 +215,7 @@ export async function migrateToken(plugin: Enveloppe, token?: string, repo?: str } async function migrateOtherRepository(plugin: Enveloppe) { - logs({ settings: plugin.settings }, "Configuring other repositories"); + plugin.console.logs({}, "Configuring other repositories"); const otherRepo = plugin.settings.github?.otherRepo ?? []; for (const repo of otherRepo) { const workflow = { @@ -267,7 +265,7 @@ async function migrateOldSettings(plugin: Enveloppe, old: OldSettings) { if (!Object.keys(old).includes("editorMenu")) { return; } - logs({ settings: plugin.settings }, i18next.t("informations.migrating.oldSettings")); + plugin.console.logs({}, i18next.t("informations.migrating.oldSettings")); plugin.settings = { github: { user: old.githubName diff --git a/src/settings/modals/import_export.ts b/src/settings/modals/import_export.ts index ae89cefb..c15b57b2 100644 --- a/src/settings/modals/import_export.ts +++ b/src/settings/modals/import_export.ts @@ -14,7 +14,7 @@ import { import type Enveloppe from "src/main"; import type { EnveloppeSettingsTab } from "src/settings"; import { migrateSettings, type OldSettings } from "src/settings/migrate"; -import { logs, notif } from "src/utils"; +import type { Logs } from "../../utils/logs"; export type SettingValue = number | string | boolean | unknown; @@ -32,6 +32,7 @@ export class ImportModal extends Modal { settingsPage: HTMLElement; settingsTab: EnveloppeSettingsTab; settings: EnveloppeSettings; + console: Logs; constructor( app: App, plugin: Enveloppe, @@ -43,10 +44,11 @@ export class ImportModal extends Modal { this.settingsPage = settingsPage; this.settingsTab = settingsTab; this.settings = plugin.settings; + this.console = plugin.console; } async censorRepositoryData(original: EnveloppeSettings) { - logs({ settings: original }, "original settings:", original); + this.console.logs({}, "original settings:", original); this.settings.plugin.dev = original.plugin.dev; this.settings.plugin.migrated = original.plugin.migrated; this.settings.plugin.displayModalRepoEditing = @@ -83,15 +85,9 @@ export class ImportModal extends Modal { //need to convert old settings to new settings const oldSettings = importedSettings as unknown as OldSettings; await migrateSettings(oldSettings, this.plugin, true); - logs( - { settings: this.plugin.settings }, - i18next.t("informations.migrating.oldSettings") - ); + this.console.logs({}, i18next.t("informations.migrating.oldSettings")); } else { - logs( - { settings: this.plugin.settings }, - i18next.t("informations.migrating.normalFormat") - ); + this.console.logs({}, i18next.t("informations.migrating.normalFormat")); importedSettings = importedSettings as unknown as EnveloppeSettings; //create a copy of actual settings const actualSettings = clone(this.plugin.settings); @@ -205,10 +201,12 @@ export class ImportModal extends Modal { export class ExportModal extends Modal { plugin: Enveloppe; + console: Logs; constructor(app: App, plugin: Enveloppe) { super(app); this.plugin = plugin; + this.console = plugin.console; } censorGithubSettingsData(censuredSettings: EnveloppeSettings) { @@ -310,7 +308,7 @@ export class ExportModal extends Modal { `${this.app.vault.configDir}/plugins/obsidian-mkdocs-publisher/._tempSettings.json` ); } catch (e) { - logs({ settings: this.plugin.settings }, "Error while deleting temporary file", e); + this.console.logs({}, "Error while deleting temporary file", e); } const { contentEl } = this; contentEl.empty(); @@ -323,6 +321,7 @@ export class ImportLoadPreset extends FuzzySuggestModal { presetList: Preset[]; page: EnveloppeSettingsTab; settings: EnveloppeSettings; + console: Logs; constructor( app: App, @@ -337,6 +336,7 @@ export class ImportLoadPreset extends FuzzySuggestModal { this.octokit = octokit; this.page = page; this.settings = plugin.settings; + this.console = plugin.console; } getItems(): Preset[] { @@ -350,7 +350,7 @@ export class ImportLoadPreset extends FuzzySuggestModal { // eslint-disable-next-line @typescript-eslint/no-unused-vars onChooseItem(item: Preset, _evt: MouseEvent | KeyboardEvent): void { const presetSettings = item.settings; - logs({ settings: presetSettings }, "onChooseItem"); + this.console.logs({}, "onChooseItem"); try { const original = clone(this.plugin.settings); if (!(presetSettings.upload.replaceTitle instanceof Array)) { @@ -379,7 +379,7 @@ export class ImportLoadPreset extends FuzzySuggestModal { this.page.renderSettingsPage("github-configuration"); } catch (e) { new Notice(i18next.t("modals.import.error.span") + e); - notif({ settings: this.settings }, "onChooseItem", e); + this.console.notif({}, "onChooseItem", e); } } } @@ -404,7 +404,7 @@ export async function loadAllPresets( if (!Array.isArray(githubPreset.data)) { return presetList; } - logs({ settings: plugin.settings }, "LoadAllPreset", githubPreset); + plugin.console.logs({}, "LoadAllPreset", githubPreset); for (const preset of githubPreset.data) { if (preset.name.endsWith(".json")) { const presetName = preset.name.replace(".json", ""); @@ -416,7 +416,7 @@ export async function loadAllPresets( } return presetList; } catch (e) { - notif({ settings: plugin.settings, e: true }, "Couldn't load preset. Error:", e); + plugin.console.notif({ e: true }, "Couldn't load preset. Error:", e); return []; } } diff --git a/src/settings/modals/manage_repo.ts b/src/settings/modals/manage_repo.ts index 4e162d84..c25094df 100644 --- a/src/settings/modals/manage_repo.ts +++ b/src/settings/modals/manage_repo.ts @@ -433,7 +433,7 @@ class ModalEditingRepository extends Modal { ); this.plugin.settings.github.rateLimit = await verifyRateLimitAPI( octokit.octokit, - this.plugin.settings + this.plugin ); }) ); diff --git a/src/settings/modals/token_path.ts b/src/settings/modals/token_path.ts index c5b62a13..a2957d03 100644 --- a/src/settings/modals/token_path.ts +++ b/src/settings/modals/token_path.ts @@ -3,18 +3,21 @@ import i18next from "i18next"; import { type App, Modal, Notice, Setting } from "obsidian"; import type Enveloppe from "src/main"; import { migrateToken } from "src/settings/migrate"; -import { createTokenPath, logs } from "src/utils"; +import { createTokenPath } from "src/utils"; +import type { Logs } from "../../utils/logs"; export class TokenEditPath extends Modal { plugin: Enveloppe; token: string; tokenPath: string; + console: Logs; constructor(app: App, plugin: Enveloppe, token: string) { super(app); this.plugin = plugin; this.token = token; this.tokenPath = ""; + this.console = plugin.console; } onOpen() { @@ -94,7 +97,7 @@ export class TokenEditPath extends Modal { input.controlEl.querySelector("input")!.style.border = "1px solid red"; new Notice(i18next.t("error.reading-token-file")); this.tokenPath = "error"; - logs({ settings: this.plugin.settings, e: true }, e); + this.console.logs({ e: true }, e); } }); }); diff --git a/src/utils/data_validation_test.ts b/src/utils/data_validation_test.ts index 0dcb7e52..679f0ca1 100644 --- a/src/utils/data_validation_test.ts +++ b/src/utils/data_validation_test.ts @@ -19,7 +19,6 @@ import { } from "obsidian"; import type { GithubBranch } from "src/GitHub/branch"; import type Enveloppe from "src/main"; -import { notif } from "src/utils"; import { frontmatterFromFile, getLinkedFrontmatter, @@ -386,7 +385,6 @@ export async function checkRepositoryValidity( file: TFile | null, silent: boolean = false ): Promise { - const settings = PublisherManager.settings; try { const frontmatter = frontmatterFromFile(file, PublisherManager.plugin, repository); const prop = getProperties(PublisherManager.plugin, repository, frontmatter); @@ -400,7 +398,7 @@ export async function checkRepositoryValidity( return true; } } catch (e) { - notif({ settings, e: true }, e); + PublisherManager.console.notif({}, e); return false; } return false; @@ -431,7 +429,7 @@ export async function checkRepositoryValidityWithProperties( return ( (await verifyRateLimitAPI( PublisherManager.octokit, - settings, + PublisherManager.plugin, false, numberOfFile )) > 0 @@ -440,7 +438,7 @@ export async function checkRepositoryValidityWithProperties( return true; } } catch (e) { - notif({ settings, e: true }, e); + PublisherManager.console.notif({ e: true }, e); return false; } return false; @@ -498,10 +496,11 @@ export function defaultRepo(settings: EnveloppeSettings): Repository { */ export async function verifyRateLimitAPI( octokit: Octokit, - settings: EnveloppeSettings, + plugin: Enveloppe, commands = false, numberOfFile = 1 ): Promise { + const settings = plugin.settings; try { const rateLimit = await octokit.request("GET /rate_limit"); const remaining = rateLimit.data.resources.core.remaining; @@ -524,7 +523,7 @@ export async function verifyRateLimitAPI( if (commands) { new Notice(message); } else { - notif({ settings }, message); + plugin.console.notif({}, message); } return remaining; @@ -537,7 +536,7 @@ export async function verifyRateLimitAPI( (error as any).name === "HttpError" ) return 5000; - notif({ settings, e: true }, error); + plugin.console.notif({ e: true }, error); return 0; } } diff --git a/src/utils/index.ts b/src/utils/index.ts index 37343778..1073113a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -5,162 +5,16 @@ import { type ListEditedFiles, type MetadataExtractor, type MultiRepoProperties, - type Properties, TOKEN_PATH, type UploadedFiles, } from "@interfaces"; -import { ERROR_ICONS, HOURGLASS_ICON, SUCCESS_ICON } from "@interfaces/icons"; -import i18next from "i18next"; -import { type App, normalizePath, Notice, Platform, TFile } from "obsidian"; +import { type App, normalizePath, Platform, type TFile } from "obsidian"; import slugify from "slugify"; import { getReceiptFolder } from "src/conversion/file_path"; import { createRegexFromText } from "src/conversion/find_and_replace_text"; -import type Publisher from "src/GitHub/upload"; import type Enveloppe from "src/main"; import { frontmatterFromFile } from "src/utils/parse_frontmatter"; -type LogsParameters = { - settings: Partial; - e?: boolean; - logs?: boolean; -}; - -/** - * Create a notice message for the log - */ -export function notif(args: LogsParameters, ...messages: unknown[]) { - const { settings, e } = args; - if (settings.plugin?.noticeError) { - new Notice(messages.join(" ")); - return; - } - let stack: string = callFunction(); - if (stack.contains("logs")) { - stack = callFunction(true); - } - const date = new Date().toISOString().slice(11, 23); - const prefix = args.logs - ? `DEV LOGS [${date}] ${stack}:\n` - : `[Enveloppe](${stack}):\n`; - if (e) console.error(prefix, ...messages); - else console.log(prefix, ...messages); -} - -/** - * Notify the user with a message in the console and a message in the notification - * Only for mobile - * @param cls {"error"|"load"|"success"|"wait"} To adjust css style in function of the type of message - * @param icon {string} The icon to display - * @param message {string} The message to display - * @returns {Notice | undefined} - */ -export function noticeMobile( - cls: "error" | "load" | "success" | "wait", - icon: string, - message: string -): Notice | undefined { - if (!Platform.isMobile) { - return; - } - const noticeFrag = document.createDocumentFragment(); - noticeFrag.createEl("span", { - text: message, - cls: ["obsidian-publisher", cls, "icons"], - }).innerHTML = icon; - noticeFrag.createEl("span", { - cls: ["obsidian-publisher", cls, "notification"], - }).innerHTML = message; - return new Notice(noticeFrag, 0); -} - -/** - * Detect the function that call the function - * @param type {boolean} if true, return the function that call the function that call the function - * @returns {string} - */ -function callFunction(type?: boolean): string { - const index = type ? 4 : 3; - let callFunction = new Error().stack?.split("\n")[index].trim(); - callFunction = callFunction?.substring( - callFunction.indexOf("at ") + 3, - callFunction.lastIndexOf(" (") - ); - callFunction = callFunction?.replace("Object.callback", ""); - callFunction = callFunction ? callFunction : "main"; - callFunction = callFunction === "eval" ? "main" : callFunction; - return callFunction; -} - -/** - * Add a new option in settings "dev" - * Will make appear ALL the logs in the console - * Not just the logs for normal process - * For advanced users only - * @param args {LogsParameters} the settings and the error type - * @param messages {unknown[]} the message to display - */ -export function logs(args: LogsParameters, ...messages: unknown[]) { - const settings = args.settings as EnveloppeSettings; - args.logs = true; - if (args.e) { - notif(args, ...messages); - return; - } - if (settings.plugin?.dev) { - notif(args, ...messages); - } -} - -/** - * Monkey patch the console to log all the messages in a file in the plugin folder - * @param plugin {Enveloppe} the plugin instance - * @returns {void} - */ -export function monkeyPatchConsole(plugin: Enveloppe): void { - if (!plugin.settings.plugin.dev) return; - - const logFile = `${plugin.manifest.dir}/logs.txt`; - const logs: string[] = []; - //detect if console.debug, console.error, console.info, console.log or console.warn is called - - const logMessages = - (prefix: string) => - (...messages: unknown[]) => { - const stack = new Error().stack?.split("\n")?.[3]?.trim(); - if (stack?.includes("obsidian-mkdocs-publisher")) { - logs.push(`\n[${prefix}]`); - for (const message of messages) { - logs.push(String(message)); - } - plugin.app.vault.adapter.write(logFile, logs.join(" ")); - } - //also display the message in the console - switch (prefix) { - case "error": - plugin.originalConsole.error(...messages); - break; - case "info": - plugin.originalConsole.info(...messages); - break; - case "log": - plugin.originalConsole.log(...messages); - break; - case "warn": - plugin.originalConsole.warn(...messages); - break; - case "debug": - plugin.originalConsole.debug(...messages); - break; - } - }; - console.debug = logMessages("debug"); - console.error = logMessages("error"); - console.info = logMessages("info"); - console.log = logMessages("log"); - console.warn = logMessages("warn"); - notif({ settings: plugin.settings }, "Console monkey patched"); -} - /** * Create the differents list of the modals opened after the upload * @param {UploadedFiles[]} listUploaded @@ -349,101 +203,6 @@ export async function createLink( return; } -/** - * Create a notice message for the sharing ; the message can be delayed if a workflow is used. - * Loop through the list of repo and create a message for each one. - * @param {Publisher} PublisherManager - * @param {TFile | string} file - * @param {EnveloppeSettings} settings - * @param {Properties | Properties[]} prop - */ - -export async function publisherNotification( - PublisherManager: Publisher, - file: TFile | string | undefined, - settings: EnveloppeSettings, - prop: Properties | Properties[] -) { - prop = Array.isArray(prop) ? prop : [prop]; - for (const repository of prop) { - await publisherNotificationOneRepo(PublisherManager, file, settings, repository); - } -} - -/** - * Notify the user with a message in the console and a message in the notification - * @param properties - */ -export function notifError(properties: Properties | Properties[]) { - const repo = Array.isArray(properties) ? properties : [properties]; - for (const repository of repo) { - const notif = document.createDocumentFragment(); - notif.createSpan({ - cls: ["error", "obsidian-publisher", "icons", "notification"], - }).innerHTML = ERROR_ICONS; - notif.createSpan({ cls: ["error", "obsidian-publisher", "notification"] }).innerHTML = - i18next.t("error.errorPublish", { repo: repository }); - new Notice(notif); - } -} - -/** - * Create a notice message for the sharing ; the message can be delayed if a workflow is used. - * @param {Publisher} PublisherManager - * @param {TFile | string} file - * @param {EnveloppeSettings} settings - * @param {Properties} prop - * @return {Promise} - */ - -async function publisherNotificationOneRepo( - PublisherManager: Publisher, - file: TFile | string | undefined, - settings: EnveloppeSettings, - prop: Properties -): Promise { - const noticeValue = file instanceof TFile ? `"${file.basename}"` : file; - const docSuccess = document.createDocumentFragment(); - const successMsg = - file instanceof String - ? i18next.t("informations.successfulPublish", { nbNotes: noticeValue, repo: prop }) - : i18next.t("informations.successPublishOneNote", { - file: noticeValue, - repo: prop, - }); - docSuccess.createEl("span", { - text: successMsg, - cls: ["obsidian-publisher", "success", "icons"], - }).innerHTML = SUCCESS_ICON; - docSuccess.createEl("span", { - cls: ["obsidian-publisher", "success", "notification"], - }).innerHTML = successMsg; - if (settings.github.workflow.name.length === 0) { - new Notice(docSuccess, 0); - return; - } - const workflowSuccess = document.createDocumentFragment(); - workflowSuccess.createEl("span", { - text: i18next.t("informations.successfulPublish", { - nbNotes: noticeValue, - repo: prop, - }), - cls: ["obsidian-publisher", "wait", "icons"], - }).innerHTML = HOURGLASS_ICON; - const msg = `${i18next.t("informations.sendMessage", { - nbNotes: noticeValue, - repo: prop, - })}.
${i18next.t("informations.waitingWorkflow")}`; - workflowSuccess.createEl("span", { - cls: ["obsidian-publisher", "wait", "notification"], - }).innerHTML = msg; - new Notice(workflowSuccess); - const successWorkflow = await PublisherManager.workflowGestion(prop); - if (successWorkflow) { - new Notice(docSuccess, 0); - } -} - /** * Trim the object to remove the empty value */ diff --git a/src/utils/logs.ts b/src/utils/logs.ts new file mode 100644 index 00000000..8538b6e9 --- /dev/null +++ b/src/utils/logs.ts @@ -0,0 +1,204 @@ +import { Notice, Platform, TFile } from "obsidian"; +import type Enveloppe from "../main"; +import { + type EnveloppeSettings, + ERROR_ICONS, + HOURGLASS_ICON, + SUCCESS_ICON, + type Properties, +} from "@interfaces"; +import i18next from "i18next"; +import type Publisher from "../GitHub/upload"; + +type Arguments = { + logs?: boolean; + e?: boolean; +}; + +export class Logs { + plugin: Enveloppe; + + constructor(plugin: Enveloppe) { + this.plugin = plugin; + } + + /** + * Create a notice message for the log + */ + notif(args: Arguments, ...messages: unknown[]) { + const { logs, e } = args; + const settings = this.plugin.settings; + if (settings.plugin?.noticeError) { + new Notice(messages.join(" ")); + return; + } + let stack: string = this.callFunction(); + if (stack.contains("logs")) { + stack = this.callFunction(true); + } + const date = new Date().toISOString().slice(11, 23); + const prefix = logs ? `DEV LOGS [${date}] ${stack}:\n` : `[Enveloppe](${stack}):\n`; + if (e) console.error(prefix, ...messages); + else console.log(prefix, ...messages); + this.writeToLog(stack, e, ...messages); + } + + /** + * Notify the user with a message in the console and a message in the notification + * Only for mobile + * @param cls {"error"|"load"|"success"|"wait"} To adjust css style in function of the type of message + * @param icon {string} The icon to display + * @param message {string} The message to display + * @returns {Notice | undefined} + */ + noticeMobile( + cls: "error" | "load" | "success" | "wait", + icon: string, + message: string + ): Notice | undefined { + if (!Platform.isMobile) { + return; + } + const noticeFrag = document.createDocumentFragment(); + noticeFrag.createEl("span", { + text: message, + cls: ["obsidian-publisher", cls, "icons"], + }).innerHTML = icon; + noticeFrag.createEl("span", { + cls: ["obsidian-publisher", cls, "notification"], + }).innerHTML = message; + return new Notice(noticeFrag, 0); + } + + /** + * Detect the function that call the function + * @param type {boolean} if true, return the function that call the function that call the function + * @returns {string} + */ + callFunction(type?: boolean): string { + const index = type ? 4 : 3; + let callFunction = new Error().stack?.split("\n")[index].trim(); + callFunction = callFunction?.substring( + callFunction.indexOf("at ") + 3, + callFunction.lastIndexOf(" (") + ); + callFunction = callFunction?.replace("Object.callback", ""); + callFunction = callFunction ? callFunction : "main"; + callFunction = callFunction === "eval" ? "main" : callFunction; + return callFunction; + } + + /** + * Add a new option in settings "dev" + * Will make appear ALL the logs in the console + * Not just the logs for normal process + * For advanced users only + */ + logs(args: Arguments, ...messages: unknown[]) { + let { logs, e } = args; + const settings = this.plugin.settings; + logs = true; + if (e) { + this.notif({ logs, e }, ...messages); + return; + } + if (settings.plugin?.dev) { + this.notif({ logs }, ...messages); + } + } + + async writeToLog(stack: string, e?: boolean, ...messages: unknown[]) { + const settings = this.plugin.settings; + if (!settings.plugin?.dev) return; + const logs: string[] = []; + logs.push(`\n[${e ? "error" : "logs"} - ${stack}]`); + for (const message of messages) { + logs.push(String(message)); + } + const logFile = `${this.plugin.manifest.dir}/logs.txt`; + + this.plugin.app.vault.adapter.append(logFile, logs.join(" ")); + } + + notifError(properties: Properties | Properties[]) { + const repo = Array.isArray(properties) ? properties : [properties]; + for (const repository of repo) { + const notif = document.createDocumentFragment(); + notif.createSpan({ + cls: ["error", "obsidian-publisher", "icons", "notification"], + }).innerHTML = ERROR_ICONS; + notif.createSpan({ + cls: ["error", "obsidian-publisher", "notification"], + }).innerHTML = i18next.t("error.errorPublish", { repo: repository }); + new Notice(notif); + } + } + + async publisherNotificationOneRepo( + PublisherManager: Publisher, + file: TFile | string | undefined, + settings: EnveloppeSettings, + prop: Properties + ): Promise { + const noticeValue = file instanceof TFile ? `"${file.basename}"` : file; + const docSuccess = document.createDocumentFragment(); + const successMsg = + file instanceof String + ? i18next.t("informations.successfulPublish", { + nbNotes: noticeValue, + repo: prop, + }) + : i18next.t("informations.successPublishOneNote", { + file: noticeValue, + repo: prop, + }); + docSuccess.createEl("span", { + text: successMsg, + cls: ["obsidian-publisher", "success", "icons"], + }).innerHTML = SUCCESS_ICON; + docSuccess.createEl("span", { + cls: ["obsidian-publisher", "success", "notification"], + }).innerHTML = successMsg; + if (settings.github.workflow.name.length === 0) { + new Notice(docSuccess, 0); + return; + } + const workflowSuccess = document.createDocumentFragment(); + workflowSuccess.createEl("span", { + text: i18next.t("informations.successfulPublish", { + nbNotes: noticeValue, + repo: prop, + }), + cls: ["obsidian-publisher", "wait", "icons"], + }).innerHTML = HOURGLASS_ICON; + const msg = `${i18next.t("informations.sendMessage", { + nbNotes: noticeValue, + repo: prop, + })}.
${i18next.t("informations.waitingWorkflow")}`; + workflowSuccess.createEl("span", { + cls: ["obsidian-publisher", "wait", "notification"], + }).innerHTML = msg; + new Notice(workflowSuccess); + const successWorkflow = await PublisherManager.workflowGestion(prop); + if (successWorkflow) { + new Notice(docSuccess, 0); + } + } + + async publisherNotification( + PublisherManager: Publisher, + file: TFile | string | undefined, + settings: EnveloppeSettings, + prop: Properties | Properties[] + ) { + prop = Array.isArray(prop) ? prop : [prop]; + for (const repository of prop) { + await this.publisherNotificationOneRepo( + PublisherManager, + file, + settings, + repository + ); + } + } +} diff --git a/src/utils/status_bar.ts b/src/utils/status_bar.ts index e2721a65..032b5a95 100644 --- a/src/utils/status_bar.ts +++ b/src/utils/status_bar.ts @@ -7,7 +7,7 @@ import { } from "@interfaces"; import i18next from "i18next"; import type { Notice } from "obsidian"; -import { noticeMobile } from "src/utils"; +import type { Logs } from "./logs"; // Credit : https://github.com/oleeskild/obsidian-digital-garden/ @oleeskild @@ -25,6 +25,7 @@ export class ShareStatusBar { status: HTMLElement; icon: HTMLElement; noticeMobile: Notice | undefined; + console: Logs; /** * @param {HTMLElement} statusBarItem @@ -35,12 +36,14 @@ export class ShareStatusBar { constructor( statusBarItem: HTMLElement, numberOfNotesToPublish: number, - attachment: boolean = false + attachment: boolean = false, + console: Logs ) { this.statusBarItem = statusBarItem; this.counter = 0; this.numberOfNotesToPublish = numberOfNotesToPublish; this.attachment = attachment; + this.console = console; const typeAttachment = this.attachment ? i18next.t("common.attachments") @@ -56,7 +59,7 @@ export class ShareStatusBar { this.icon.innerHTML = FOUND_ATTACHMENTS; this.status = this.statusBarItem.createEl("span", { text: `${msg}` }); this.status.addClass("found-attachments"); - this.noticeMobile = noticeMobile("wait", FOUND_ATTACHMENTS, msg); + this.noticeMobile = this.console.noticeMobile("wait", FOUND_ATTACHMENTS, msg); } /** @@ -83,7 +86,7 @@ export class ShareStatusBar { setTimeout(() => { this.noticeMobile?.hide(); }, 4000); - this.noticeMobile = noticeMobile("load", HOURGLASS_ICON, msg); + this.noticeMobile = this.console.noticeMobile("load", HOURGLASS_ICON, msg); } }