diff --git a/README.md b/README.md index b8738fa..002e0ef 100644 --- a/README.md +++ b/README.md @@ -380,6 +380,28 @@ export type resultData = { } ``` +For `beforeSaveToFile` the data object is an object with the `filePath` and `content`. Here is the interface for `saveToFileData`: + +```typescript +export type saveToFileData = { + filePath: string; + content: string; +} +``` + +This is called when you call `saveToFile`, `saveToFileSync`. + +For `beforeRenderToFile` the data object is an object with the `filePath` and `content`. Here is the interface for `renderToFileData`: + +```typescript +export type renderToFileData = { + filePath: string; + content: string; +} +``` + +This is called when you call `renderToFile`, `renderToFileSync`. + # Code of Conduct and Contributing [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) guidelines. diff --git a/src/writr.ts b/src/writr.ts index ba1b283..7aa690c 100644 --- a/src/writr.ts +++ b/src/writr.ts @@ -56,7 +56,7 @@ export enum WritrHooks { beforeRender = 'beforeRender', afterRender = 'afterRender', beforeSaveToFile = 'beforeSaveToFile', - afterSaveToFile = 'afterSaveToFile', + beforeRenderToFile = 'beforeRenderToFile', beforeLoadFromFile = 'beforeLoadFromFile', afterLoadFromFile = 'afterLoadFromFile', } @@ -342,7 +342,12 @@ export class Writr extends Hookified { const directoryPath = dirname(filePath); const content = await this.render(options); await mkdir(directoryPath, {recursive: true}); - await writeFile(filePath, content, 'utf8'); + const data = { + filePath, + content, + }; + await this.hook(WritrHooks.beforeRenderToFile, data); + await writeFile(data.filePath, data.content); /* c8 ignore next 6 */ } catch (error) { this.emit('error', error); @@ -362,7 +367,14 @@ export class Writr extends Hookified { const directoryPath = dirname(filePath); const content = this.renderSync(options); fs.mkdirSync(directoryPath, {recursive: true}); - fs.writeFileSync(filePath, content, 'utf8'); + const data = { + filePath, + content, + }; + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.hook(WritrHooks.beforeRenderToFile, data); + + fs.writeFileSync(data.filePath, data.content); /* c8 ignore next 6 */ } catch (error) { this.emit('error', error); @@ -424,7 +436,13 @@ export class Writr extends Hookified { const {writeFile, mkdir} = fs.promises; const directoryPath = dirname(filePath); await mkdir(directoryPath, {recursive: true}); - await writeFile(filePath, this._content, 'utf8'); + const data = { + filePath, + content: this._content, + }; + await this.hook(WritrHooks.beforeSaveToFile, data); + + await writeFile(data.filePath, data.content); /* c8 ignore next 6 */ } catch (error) { this.emit('error', error); @@ -443,7 +461,14 @@ export class Writr extends Hookified { try { const directoryPath = dirname(filePath); fs.mkdirSync(directoryPath, {recursive: true}); - fs.writeFileSync(filePath, this._content, 'utf8'); + const data = { + filePath, + content: this._content, + }; + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.hook(WritrHooks.beforeSaveToFile, data); + + fs.writeFileSync(data.filePath, data.content); /* c8 ignore next 6 */ } catch (error) { this.emit('error', error); diff --git a/test/writr-hooks.test.ts b/test/writr-hooks.test.ts index c6588da..bdcc319 100644 --- a/test/writr-hooks.test.ts +++ b/test/writr-hooks.test.ts @@ -1,4 +1,5 @@ +import fs from 'node:fs'; import { test, describe, expect, } from 'vitest'; @@ -22,4 +23,64 @@ describe('Writr Render Hooks', async () => { const result = writr.renderSync(); expect(result).toBe('

Hello, Sync!

'); }); + + test('it should change the content before saving to file', async () => { + const filePath = './test-save-to-file.txt'; + const writr = new Writr('Hello, World!'); + writr.onHook(WritrHooks.beforeSaveToFile, data => { + data.content = 'Hello, File!'; + }); + await writr.saveToFile(filePath); + await writr.loadFromFile(filePath); + + expect(writr.content).toBe('Hello, File!'); + + // Cleanup + await fs.promises.rm(filePath); + }); + + test('it should change the content before saving to file sync', async () => { + const filePath = './test-save-to-file-sync.txt'; + const writr = new Writr('Hello, World!'); + writr.onHook(WritrHooks.beforeSaveToFile, data => { + data.content = 'Hello, File Sync!'; + }); + writr.saveToFileSync(filePath); + writr.loadFromFileSync(filePath); + + expect(writr.content).toBe('Hello, File Sync!'); + + // Cleanup + await fs.promises.rm(filePath); + }); + + test('it should change the content before render to file', async () => { + const filePath = './test-render-to-file.txt'; + const writr = new Writr('Hello, World!'); + writr.onHook(WritrHooks.beforeRenderToFile, data => { + data.content = 'Hello, File!'; + }); + await writr.renderToFile(filePath); + const fileContent = await fs.promises.readFile(filePath); + + expect(fileContent.toString()).toContain('Hello, File!'); + + // Cleanup + await fs.promises.rm(filePath); + }); + + test('it should change the content before render to file sync', async () => { + const filePath = './test-render-to-file-sync.txt'; + const writr = new Writr('Hello, World!'); + writr.onHook(WritrHooks.beforeRenderToFile, data => { + data.content = 'Hello, File Sync!'; + }); + writr.renderToFileSync(filePath); + const fileContent = await fs.promises.readFile(filePath); + + expect(fileContent.toString()).toContain('Hello, File Sync!'); + + // Cleanup + await fs.promises.rm(filePath); + }); });