diff --git a/apps/plugin/src/app/plugin.ts b/apps/plugin/src/app/plugin.ts index b8b5798..b180b84 100644 --- a/apps/plugin/src/app/plugin.ts +++ b/apps/plugin/src/app/plugin.ts @@ -52,6 +52,42 @@ export class DataviewSerializerPlugin extends Plugin { true ); + scheduleForcedUpdate = debounce( + this.processForceUpdateFiles.bind(this), + MINIMUM_MS_BETWEEN_EVENTS * 20, + true + ); + + /** + * Process updates for folders which are marked as forced updates. + * These files are updated on any modification, useful for scenarios + * where there's an index file that holds queries that could be impacted + * by file updates elsewhere. This can be run with an empty argument list, + * or with `true` passed as a value to the single optional parameter to + * update all files. The command palette command uses this behavior. + */ + async processForceUpdateFiles(allFiles?: boolean): Promise { + this.app.vault + .getMarkdownFiles() + .filter((file) => { + if (allFiles) { + // Ignore the configuration and update all queries when this parameter is true + return true; + } + let isUpdateable = false; + this.settings.foldersToForceUpdate.forEach((folder) => { + if (file.path.startsWith(folder)) { + isUpdateable = true; + } + }); + + return isUpdateable; + }) + .forEach(async (file) => { + await this.processFile(file); + }); + } + /** * Process all the identified recently updated files */ @@ -94,11 +130,7 @@ export class DataviewSerializerPlugin extends Plugin { name: 'Scan and serialize all Dataview queries', callback: async () => { log('Scanning and serializing all Dataview queries', 'debug'); - const allVaultFiles = this.app.vault.getMarkdownFiles(); - - for (const vaultFile of allVaultFiles) { - await this.processFile(vaultFile); - } + this.processForceUpdateFiles(true); }, }); } @@ -142,6 +174,19 @@ export class DataviewSerializerPlugin extends Plugin { log('The loaded settings miss the [ignoredFolders] property', 'debug'); needToSaveSettings = true; } + if ( + loadedSettings.foldersToForceUpdate !== undefined && + loadedSettings.foldersToForceUpdate !== null && + Array.isArray(loadedSettings.foldersToForceUpdate) + ) { + draft.foldersToForceUpdate = loadedSettings.foldersToForceUpdate; + } else { + log( + 'The loaded settings miss the [foldersToForceUpdate] property', + 'debug' + ); + needToSaveSettings = true; + } }); log(`Settings loaded`, 'debug', loadedSettings); @@ -172,6 +217,7 @@ export class DataviewSerializerPlugin extends Plugin { this.app.vault.on('create', (file) => { this.recentlyUpdatedFiles.add(file); this.scheduleUpdate(); + this.scheduleForcedUpdate(); }) ); @@ -179,6 +225,7 @@ export class DataviewSerializerPlugin extends Plugin { this.app.vault.on('rename', (file) => { this.recentlyUpdatedFiles.add(file); this.scheduleUpdate(); + this.scheduleForcedUpdate(); }) ); @@ -186,6 +233,7 @@ export class DataviewSerializerPlugin extends Plugin { this.app.vault.on('modify', (file) => { this.recentlyUpdatedFiles.add(file); this.scheduleUpdate(); + this.scheduleForcedUpdate(); }) ); }); @@ -207,14 +255,18 @@ export class DataviewSerializerPlugin extends Plugin { try { //log(`Processing file: ${file.path}`, 'debug'); - const text = await this.app.vault.cachedRead(file); - const foundQueries: string[] = findQueries(text); + // check cached text for queries + const cachedText = await this.app.vault.cachedRead(file); + const foundQueries: string[] = findQueries(cachedText); if (foundQueries.length === 0) { // No queries to serialize found in the file return; } + // get text from filesystem, per documentation, since we'll likely be changing it + const text = await this.app.vault.read(file); + // Process the modified file let updatedText = `${text}`; // To ensure we have access to replaceAll... @@ -270,6 +322,7 @@ export class DataviewSerializerPlugin extends Plugin { if (updatedText !== text) { //log('The file content has changed. Saving the modifications', 'info'); + await this.app.vault.modify(file, updatedText); } } catch (e: unknown) { diff --git a/apps/plugin/src/app/settingTab/index.ts b/apps/plugin/src/app/settingTab/index.ts index f832da2..0495a23 100644 --- a/apps/plugin/src/app/settingTab/index.ts +++ b/apps/plugin/src/app/settingTab/index.ts @@ -21,6 +21,7 @@ export class SettingsTab extends PluginSettingTab { this.renderFoldersToScan(); this.renderFoldersToIgnore(); + this.renderFoldersToForceUpdate(); this.renderFollowButton(containerEl); this.renderSupportHeader(containerEl); } @@ -84,6 +85,23 @@ export class SettingsTab extends PluginSettingTab { }); } + renderFoldersToForceUpdate(): void { + this.doSearchAndRemoveList({ + currentList: this.plugin.settings.foldersToForceUpdate, + setValue: async (newValue) => { + this.plugin.settings = produce( + this.plugin.settings, + (draft: Draft) => { + draft.foldersToForceUpdate = newValue; + } + ); + }, + name: 'Folders to force update on any modifications', + description: + 'Folders to update when any files are modified. Useful to update index files in your vault.', + }); + } + doSearchAndRemoveList({ currentList, setValue, diff --git a/apps/plugin/src/app/types/index.ts b/apps/plugin/src/app/types/index.ts index a7174b0..98b7e55 100644 --- a/apps/plugin/src/app/types/index.ts +++ b/apps/plugin/src/app/types/index.ts @@ -1,9 +1,11 @@ export interface PluginSettings { foldersToScan: string[]; ignoredFolders: string[]; + foldersToForceUpdate: string[]; } export const DEFAULT_SETTINGS: PluginSettings = { foldersToScan: [], ignoredFolders: [], + foldersToForceUpdate: [], };