writr 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -22,7 +22,7 @@
22
22
  - [`.engine`](#engine)
23
23
  - [`.render(options?: RenderOptions): Promise<string>`](#renderoptions-renderoptions-promisestring)
24
24
  - [`.renderSync(options?: RenderOptions): string`](#rendersyncoptions-renderoptions-string)
25
- - [`.renderToFile(filePath: string, options?: RenderOptions): Promise<void>`](#rendertofilefilepath-string-options-renderoptions-promisevoid)
25
+ - [`.renderToFile(filePath: string, options?: RenderOptions)`](#rendertofilefilepath-string-options-renderoptions)
26
26
  - [`.renderToFileSync(filePath: string, options?: RenderOptions): void`](#rendertofilesyncfilepath-string-options-renderoptions-void)
27
27
  - [`.renderReact(options?: RenderOptions, reactOptions?: HTMLReactParserOptions): Promise<React.JSX.Element />`](#renderreactoptions-renderoptions-reactoptions-htmlreactparseroptions-promise-reactjsxelement-)
28
28
  - [`.renderReactSync( options?: RenderOptions, reactOptions?: HTMLReactParserOptions): React.JSX.Element`](#renderreactsync-options-renderoptions-reactoptions-htmlreactparseroptions-reactjsxelement)
@@ -30,6 +30,7 @@
30
30
  - [`.loadFromFileSync(filePath: string): void`](#loadfromfilesyncfilepath-string-void)
31
31
  - [`.saveToFile(filePath: string): Promise<void>`](#savetofilefilepath-string-promisevoid)
32
32
  - [`.saveToFileSync(filePath: string): void`](#savetofilesyncfilepath-string-void)
33
+ - [Hooks](#hooks)
33
34
  - [Code of Conduct and Contributing](#code-of-conduct-and-contributing)
34
35
  - [License](#license)
35
36
 
@@ -47,6 +48,7 @@
47
48
  * Github Flavor Markdown (remark-gfm).
48
49
  * Emoji Support (remark-emoji).
49
50
  * MDX Support (remark-mdx).
51
+ * Built in Hooks for adding code to render pipeline.
50
52
 
51
53
  # ESM and Node Version Support
52
54
 
@@ -252,7 +254,7 @@ const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
252
254
  const html = writr.renderSync(); // <h1>Hello World 🙂</h1><p>This is a test.</p>
253
255
  ```
254
256
 
255
- ## '.renderToFile(filePath: string, options?: RenderOptions): Promise<void>'
257
+ ## '.renderToFile(filePath: string, options?: RenderOptions)'
256
258
 
257
259
  Rendering markdown to a file. The options are based on RenderOptions.
258
260
 
@@ -347,9 +349,41 @@ writr.cache.store.lruSize = 100;
347
349
  writr.cache.store.ttl = '5m'; // setting it to 5 minutes
348
350
  ```
349
351
 
352
+ # Hooks
353
+
354
+ Hooks are a way to add additional parsing to the render pipeline. You can add hooks to the the Writr instance. Here is an example of adding a hook to the instance of Writr:
355
+
356
+ ```javascript
357
+ import { Writr, WritrHooks } from 'writr';
358
+ const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
359
+ writr.onHook(WritrHooks.beforeRender, data => {
360
+ data.body = 'Hello, Universe!';
361
+ });
362
+ const result = await writr.render();
363
+ console.log(result); // Hello, Universe!
364
+ ```
365
+
366
+ For `beforeRender` the data object is a `renderData` object. Here is the interface for `renderData`:
367
+
368
+ ```typescript
369
+ export type renderData {
370
+ body: string;
371
+ content: string;
372
+ options: RenderOptions;
373
+ }
374
+ ```
375
+
376
+ For `afterRender` the data object is a `resultData` object. Here is the interface for `resultData`:
377
+
378
+ ```typescript
379
+ export type resultData {
380
+ result: string;
381
+ }
382
+ ```
383
+
350
384
  # Code of Conduct and Contributing
351
385
  [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) guidelines.
352
386
 
353
387
  # License
354
388
 
355
- MIT © [Jared Wray](https://jaredwray.com)
389
+ [MIT](LICENSE) & © [Jared Wray](https://jaredwray.com)
package/dist/writr.d.ts CHANGED
@@ -49,6 +49,14 @@ type RenderOptions = {
49
49
  mdx?: boolean;
50
50
  caching?: boolean;
51
51
  };
52
+ declare enum WritrHooks {
53
+ beforeRender = "beforeRender",
54
+ afterRender = "afterRender",
55
+ beforeSaveToFile = "beforeSaveToFile",
56
+ afterSaveToFile = "afterSaveToFile",
57
+ beforeLoadFromFile = "beforeLoadFromFile",
58
+ afterLoadFromFile = "afterLoadFromFile"
59
+ }
52
60
  declare class Writr extends Hookified {
53
61
  engine: unified.Processor<mdast.Root, mdast.Root, hast.Root, hast.Root, string>;
54
62
  private readonly _options;
@@ -182,4 +190,4 @@ declare class Writr extends Hookified {
182
190
  private mergeRenderOptions;
183
191
  }
184
192
 
185
- export { type RenderOptions, Writr, type WritrOptions };
193
+ export { type RenderOptions, Writr, WritrHooks, type WritrOptions };
package/dist/writr.js CHANGED
@@ -54,6 +54,15 @@ var WritrCache = class {
54
54
  };
55
55
 
56
56
  // src/writr.ts
57
+ var WritrHooks = /* @__PURE__ */ ((WritrHooks2) => {
58
+ WritrHooks2["beforeRender"] = "beforeRender";
59
+ WritrHooks2["afterRender"] = "afterRender";
60
+ WritrHooks2["beforeSaveToFile"] = "beforeSaveToFile";
61
+ WritrHooks2["afterSaveToFile"] = "afterSaveToFile";
62
+ WritrHooks2["beforeLoadFromFile"] = "beforeLoadFromFile";
63
+ WritrHooks2["afterLoadFromFile"] = "afterLoadFromFile";
64
+ return WritrHooks2;
65
+ })(WritrHooks || {});
57
66
  var Writr = class extends Hookified {
58
67
  engine = unified().use(remarkParse).use(remarkGfm).use(remarkToc).use(remarkEmoji).use(remarkRehype).use(rehypeSlug).use(remarkMath).use(rehypeKatex).use(rehypeHighlight).use(remarkMDX).use(rehypeStringify);
59
68
  // Stringify HTML
@@ -201,24 +210,33 @@ ${yamlString}---
201
210
  */
202
211
  async render(options) {
203
212
  try {
204
- let result = "";
205
- if (this.isCacheEnabled(options)) {
206
- const cached = this._cache.get(this._content, options);
207
- if (cached) {
208
- return cached;
209
- }
210
- }
211
213
  let { engine } = this;
212
214
  if (options) {
213
215
  options = { ...this._options.renderOptions, ...options };
214
216
  engine = this.createProcessor(options);
215
217
  }
216
- const file = await engine.process(this.body);
217
- result = String(file);
218
- if (this.isCacheEnabled(options)) {
219
- this._cache.set(this._content, result, options);
218
+ const renderData = {
219
+ content: this._content,
220
+ body: this.body,
221
+ options
222
+ };
223
+ await this.hook("beforeRender" /* beforeRender */, renderData);
224
+ const resultData = {
225
+ result: ""
226
+ };
227
+ if (this.isCacheEnabled(renderData.options)) {
228
+ const cached = this._cache.get(renderData.content, renderData.options);
229
+ if (cached) {
230
+ return cached;
231
+ }
220
232
  }
221
- return result;
233
+ const file = await engine.process(renderData.body);
234
+ resultData.result = String(file);
235
+ if (this.isCacheEnabled(renderData.options)) {
236
+ this._cache.set(renderData.content, resultData.result, renderData.options);
237
+ }
238
+ await this.hook("afterRender" /* afterRender */, resultData);
239
+ return resultData.result;
222
240
  } catch (error) {
223
241
  throw new Error(`Failed to render markdown: ${error.message}`);
224
242
  }
@@ -230,24 +248,33 @@ ${yamlString}---
230
248
  */
231
249
  renderSync(options) {
232
250
  try {
233
- let result = "";
234
- if (this.isCacheEnabled(options)) {
235
- const cached = this._cache.get(this._content, options);
236
- if (cached) {
237
- return cached;
238
- }
239
- }
240
251
  let { engine } = this;
241
252
  if (options) {
242
253
  options = { ...this._options.renderOptions, ...options };
243
254
  engine = this.createProcessor(options);
244
255
  }
245
- const file = engine.processSync(this.body);
246
- result = String(file);
247
- if (this.isCacheEnabled(options)) {
248
- this._cache.set(this._content, result, options);
256
+ const renderData = {
257
+ content: this._content,
258
+ body: this.body,
259
+ options
260
+ };
261
+ this.hook("beforeRender" /* beforeRender */, renderData);
262
+ const resultData = {
263
+ result: ""
264
+ };
265
+ if (this.isCacheEnabled(renderData.options)) {
266
+ const cached = this._cache.get(renderData.content, renderData.options);
267
+ if (cached) {
268
+ return cached;
269
+ }
249
270
  }
250
- return result;
271
+ const file = engine.processSync(renderData.body);
272
+ resultData.result = String(file);
273
+ if (this.isCacheEnabled(renderData.options)) {
274
+ this._cache.set(renderData.content, resultData.result, renderData.options);
275
+ }
276
+ this.hook("afterRender" /* afterRender */, resultData);
277
+ return resultData.result;
251
278
  } catch (error) {
252
279
  throw new Error(`Failed to render markdown: ${error.message}`);
253
280
  }
@@ -433,5 +460,6 @@ ${yamlString}---
433
460
  }
434
461
  };
435
462
  export {
436
- Writr
463
+ Writr,
464
+ WritrHooks
437
465
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "writr",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "Markdown Rendering Simplified",
5
5
  "type": "module",
6
6
  "main": "./dist/writr.js",
@@ -53,11 +53,11 @@
53
53
  "website:serve": "rimraf ./site/README.md ./site/dist && npx docula serve -s ./site -o ./site/dist"
54
54
  },
55
55
  "dependencies": {
56
- "cacheable": "^1.8.5",
57
- "hookified": "^1.5.1",
58
- "html-react-parser": "^5.1.18",
56
+ "cacheable": "^1.8.7",
57
+ "hookified": "^1.6.0",
58
+ "html-react-parser": "^5.2.2",
59
59
  "js-yaml": "^4.1.0",
60
- "react": "^18.3.1",
60
+ "react": "^19.0.0",
61
61
  "rehype-highlight": "^7.0.1",
62
62
  "rehype-katex": "^7.0.1",
63
63
  "rehype-slug": "^6.0.0",
@@ -73,17 +73,17 @@
73
73
  },
74
74
  "devDependencies": {
75
75
  "@types/js-yaml": "^4.0.9",
76
- "@types/node": "^22.10.1",
77
- "@types/react": "^18.3.12",
78
- "@vitest/coverage-v8": "^2.1.6",
79
- "docula": "^0.9.5",
76
+ "@types/node": "^22.10.2",
77
+ "@types/react": "^19.0.2",
78
+ "@vitest/coverage-v8": "^2.1.8",
79
+ "docula": "^0.9.6",
80
80
  "rimraf": "^6.0.1",
81
81
  "ts-node": "^10.9.2",
82
82
  "tsup": "^8.3.5",
83
83
  "typescript": "^5.7.2",
84
- "vitest": "^2.1.6",
85
- "webpack": "^5.96.1",
86
- "xo": "^0.59.3"
84
+ "vitest": "^2.1.8",
85
+ "webpack": "^5.97.1",
86
+ "xo": "^0.60.0"
87
87
  },
88
88
  "xo": {
89
89
  "ignores": [