writr 4.0.0 → 4.1.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
@@ -32,13 +32,13 @@
32
32
 
33
33
  ## Getting Started
34
34
 
35
- ## 1. Install Writr
35
+ ## Install Writr
36
36
 
37
37
  ```bash
38
38
  > npm install writr
39
39
  ```
40
40
 
41
- ## 2. Render from Markdown
41
+ Then you can use it like this:
42
42
 
43
43
  ```javascript
44
44
  import { Writr } from 'writr';
@@ -58,6 +58,26 @@ const options = {
58
58
  const html = await writr.render(options); // <h1>Hello World ::-):</h1><p>This is a test.</p>
59
59
  ```
60
60
 
61
+ An example passing in the options also via the constructor:
62
+
63
+ ```javascript
64
+ import { Writr, WritrOptions } from 'writr';
65
+ const writrOptions = {
66
+ renderOptions: {
67
+ emoji: true,
68
+ toc: true,
69
+ slug: true,
70
+ highlight: true,
71
+ gfm: true,
72
+ math: true,
73
+ mdx: true,
74
+ caching: true,
75
+ }
76
+ };
77
+ const writr = new Writr(`# Hello World ::-):\n\n This is a test.`, writrOptions);
78
+ const html = await writr.render(options); // <h1>Hello World ::-):</h1><p>This is a test.</p>
79
+ ```
80
+
61
81
  ## API
62
82
 
63
83
  ### `new Writr(arg?: string | WritrOptions, options?: WritrOptions)`
package/dist/writr.cjs ADDED
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/writr.ts
31
+ var writr_exports = {};
32
+ __export(writr_exports, {
33
+ Writr: () => Writr
34
+ });
35
+ module.exports = __toCommonJS(writr_exports);
36
+ var import_node_fs = __toESM(require("fs"), 1);
37
+ var import_node_path = require("path");
38
+ var import_unified = require("unified");
39
+ var import_remark_parse = __toESM(require("remark-parse"), 1);
40
+ var import_remark_rehype = __toESM(require("remark-rehype"), 1);
41
+ var import_rehype_slug = __toESM(require("rehype-slug"), 1);
42
+ var import_rehype_highlight = __toESM(require("rehype-highlight"), 1);
43
+ var import_rehype_stringify = __toESM(require("rehype-stringify"), 1);
44
+ var import_remark_toc = __toESM(require("remark-toc"), 1);
45
+ var import_remark_math = __toESM(require("remark-math"), 1);
46
+ var import_rehype_katex = __toESM(require("rehype-katex"), 1);
47
+ var import_remark_gfm = __toESM(require("remark-gfm"), 1);
48
+ var import_remark_emoji = __toESM(require("remark-emoji"), 1);
49
+ var import_remark_mdx = __toESM(require("remark-mdx"), 1);
50
+ var import_html_react_parser = __toESM(require("html-react-parser"), 1);
51
+ var yaml = __toESM(require("js-yaml"), 1);
52
+
53
+ // src/writr-cache.ts
54
+ var import_node_crypto = require("crypto");
55
+ var import_cacheable = require("cacheable");
56
+ var WritrCache = class {
57
+ _markdownStore = new import_cacheable.Cacheable();
58
+ _markdownStoreSync = new import_cacheable.CacheableMemory();
59
+ _hashStore = new import_cacheable.CacheableMemory();
60
+ get markdownStore() {
61
+ return this._markdownStore;
62
+ }
63
+ get markdownStoreSync() {
64
+ return this._markdownStoreSync;
65
+ }
66
+ get hashStore() {
67
+ return this._hashStore;
68
+ }
69
+ async getMarkdown(markdown, options) {
70
+ const key = this.hash(markdown, options);
71
+ return this.get(key);
72
+ }
73
+ getMarkdownSync(markdown, options) {
74
+ const key = this.hash(markdown, options);
75
+ return this.getSync(key);
76
+ }
77
+ async setMarkdown(markdown, value, options) {
78
+ const key = this.hash(markdown, options);
79
+ return this.set(key, value);
80
+ }
81
+ setMarkdownSync(markdown, value, options) {
82
+ const key = this.hash(markdown, options);
83
+ this.setSync(key, value);
84
+ return true;
85
+ }
86
+ async get(key) {
87
+ return this._markdownStore.get(key);
88
+ }
89
+ getSync(key) {
90
+ return this._markdownStoreSync.get(key);
91
+ }
92
+ async set(key, value) {
93
+ return this._markdownStore.set(key, value);
94
+ }
95
+ setSync(key, value) {
96
+ this._markdownStoreSync.set(key, value);
97
+ return true;
98
+ }
99
+ async clear() {
100
+ await this._markdownStore.clear();
101
+ this._markdownStoreSync.clear();
102
+ this._hashStore.clear();
103
+ }
104
+ setStorageAdapter(adapter) {
105
+ this._markdownStore = new import_cacheable.Cacheable({ primary: adapter });
106
+ }
107
+ hash(markdown, options) {
108
+ const key = JSON.stringify({ markdown, options });
109
+ let result = this._hashStore.get(key);
110
+ if (result) {
111
+ return result;
112
+ }
113
+ result = (0, import_node_crypto.createHash)("sha256").update(key).digest("hex");
114
+ this._hashStore.set(key, result);
115
+ return result;
116
+ }
117
+ };
118
+
119
+ // src/writr.ts
120
+ var Writr = class {
121
+ engine = (0, import_unified.unified)().use(import_remark_parse.default).use(import_remark_gfm.default).use(import_remark_toc.default).use(import_remark_emoji.default).use(import_remark_rehype.default).use(import_rehype_slug.default).use(import_remark_math.default).use(import_rehype_katex.default).use(import_rehype_highlight.default).use(import_remark_mdx.default).use(import_rehype_stringify.default);
122
+ // Stringify HTML
123
+ _options = {
124
+ openai: void 0,
125
+ renderOptions: {
126
+ emoji: true,
127
+ toc: true,
128
+ slug: true,
129
+ highlight: true,
130
+ gfm: true,
131
+ math: true,
132
+ mdx: true,
133
+ caching: true
134
+ }
135
+ };
136
+ _content = "";
137
+ _cache = new WritrCache();
138
+ constructor(arguments1, arguments2) {
139
+ if (typeof arguments1 === "string") {
140
+ this._content = arguments1;
141
+ } else if (arguments1) {
142
+ this._options = { ...this._options, ...arguments1 };
143
+ if (this._options.renderOptions) {
144
+ this.engine = this.createProcessor(this._options.renderOptions);
145
+ }
146
+ }
147
+ if (arguments2) {
148
+ this._options = { ...this._options, ...arguments2 };
149
+ if (this._options.renderOptions) {
150
+ this.engine = this.createProcessor(this._options.renderOptions);
151
+ }
152
+ }
153
+ }
154
+ get options() {
155
+ return this._options;
156
+ }
157
+ get content() {
158
+ return this._content;
159
+ }
160
+ set content(value) {
161
+ this._content = value;
162
+ }
163
+ get cache() {
164
+ return this._cache;
165
+ }
166
+ get frontMatterRaw() {
167
+ const start = this._content.indexOf("---\n");
168
+ if (start === -1) {
169
+ return "";
170
+ }
171
+ const end = this._content.indexOf("\n---\n", start + 4);
172
+ if (end === -1) {
173
+ return "";
174
+ }
175
+ return this._content.slice(start, end + 5);
176
+ }
177
+ get body() {
178
+ const start = this._content.indexOf("---\n");
179
+ if (start === -1) {
180
+ return this._content;
181
+ }
182
+ const end = this._content.indexOf("\n---\n", start + 4);
183
+ if (end === -1) {
184
+ return this._content;
185
+ }
186
+ return this._content.slice(Math.max(0, end + 5)).trim();
187
+ }
188
+ get markdown() {
189
+ return this.body;
190
+ }
191
+ get frontMatter() {
192
+ const frontMatter = this.frontMatterRaw;
193
+ const match = /^---\s*([\s\S]*?)\s*---\s*/.exec(frontMatter);
194
+ if (match) {
195
+ return yaml.load(match[1].trim());
196
+ }
197
+ return {};
198
+ }
199
+ set frontMatter(data) {
200
+ const frontMatter = this.frontMatterRaw;
201
+ const yamlString = yaml.dump(data);
202
+ const newFrontMatter = `---
203
+ ${yamlString}---
204
+ `;
205
+ this._content = this._content.replace(frontMatter, newFrontMatter);
206
+ }
207
+ getFrontMatterValue(key) {
208
+ return this.frontMatter[key];
209
+ }
210
+ async render(options) {
211
+ try {
212
+ let result = "";
213
+ if (this.isCacheEnabled(options)) {
214
+ const cached = await this._cache.getMarkdown(this._content, options);
215
+ if (cached) {
216
+ return cached;
217
+ }
218
+ }
219
+ let { engine } = this;
220
+ if (options) {
221
+ options = { ...this._options.renderOptions, ...options };
222
+ engine = this.createProcessor(options);
223
+ }
224
+ const file = await engine.process(this.body);
225
+ result = String(file);
226
+ if (this.isCacheEnabled(options)) {
227
+ await this._cache.setMarkdown(this._content, result, options);
228
+ }
229
+ return result;
230
+ } catch (error) {
231
+ throw new Error(`Failed to render markdown: ${error.message}`);
232
+ }
233
+ }
234
+ renderSync(options) {
235
+ try {
236
+ let result = "";
237
+ if (this.isCacheEnabled(options)) {
238
+ const cached = this._cache.getMarkdownSync(this._content, options);
239
+ if (cached) {
240
+ return cached;
241
+ }
242
+ }
243
+ let { engine } = this;
244
+ if (options) {
245
+ options = { ...this._options.renderOptions, ...options };
246
+ engine = this.createProcessor(options);
247
+ }
248
+ const file = engine.processSync(this.body);
249
+ result = String(file);
250
+ if (this.isCacheEnabled(options)) {
251
+ this._cache.setMarkdownSync(this._content, result, options);
252
+ }
253
+ return result;
254
+ } catch (error) {
255
+ throw new Error(`Failed to render markdown: ${error.message}`);
256
+ }
257
+ }
258
+ async renderReact(options, reactParseOptions) {
259
+ const html = await this.render(options);
260
+ return (0, import_html_react_parser.default)(html, reactParseOptions);
261
+ }
262
+ renderReactSync(options, reactParseOptions) {
263
+ const html = this.renderSync(options);
264
+ return (0, import_html_react_parser.default)(html, reactParseOptions);
265
+ }
266
+ async loadFromFile(filePath) {
267
+ const { readFile } = import_node_fs.default.promises;
268
+ this._content = await readFile(filePath, "utf8");
269
+ }
270
+ loadFromFileSync(filePath) {
271
+ this._content = import_node_fs.default.readFileSync(filePath, "utf8");
272
+ }
273
+ async saveToFile(filePath) {
274
+ const { writeFile, mkdir } = import_node_fs.default.promises;
275
+ const directoryPath = (0, import_node_path.dirname)(filePath);
276
+ await mkdir(directoryPath, { recursive: true });
277
+ await writeFile(filePath, this._content, "utf8");
278
+ }
279
+ saveToFileSync(filePath) {
280
+ const directoryPath = (0, import_node_path.dirname)(filePath);
281
+ import_node_fs.default.mkdirSync(directoryPath, { recursive: true });
282
+ import_node_fs.default.writeFileSync(filePath, this._content, "utf8");
283
+ }
284
+ isCacheEnabled(options) {
285
+ if (options?.caching !== void 0) {
286
+ return options.caching;
287
+ }
288
+ return this._options?.renderOptions?.caching ?? false;
289
+ }
290
+ createProcessor(options) {
291
+ const processor = (0, import_unified.unified)().use(import_remark_parse.default);
292
+ if (options.gfm) {
293
+ processor.use(import_remark_gfm.default);
294
+ }
295
+ if (options.toc) {
296
+ processor.use(import_remark_toc.default, { heading: "toc|table of contents" });
297
+ }
298
+ if (options.emoji) {
299
+ processor.use(import_remark_emoji.default);
300
+ }
301
+ processor.use(import_remark_rehype.default);
302
+ if (options.slug) {
303
+ processor.use(import_rehype_slug.default);
304
+ }
305
+ if (options.highlight) {
306
+ processor.use(import_rehype_highlight.default);
307
+ }
308
+ if (options.math) {
309
+ processor.use(import_remark_math.default).use(import_rehype_katex.default);
310
+ }
311
+ if (options.mdx) {
312
+ processor.use(import_remark_mdx.default);
313
+ }
314
+ processor.use(import_rehype_stringify.default);
315
+ return processor;
316
+ }
317
+ };
318
+ // Annotate the CommonJS export names for ESM import in node:
319
+ 0 && (module.exports = {
320
+ Writr
321
+ });
@@ -0,0 +1,71 @@
1
+ import * as unified from 'unified';
2
+ import * as hast from 'hast';
3
+ import * as mdast from 'mdast';
4
+ import React from 'react';
5
+ import { HTMLReactParserOptions } from 'html-react-parser';
6
+ import { Cacheable, CacheableMemory } from 'cacheable';
7
+ import { KeyvStoreAdapter } from 'keyv';
8
+
9
+ declare class WritrCache {
10
+ private _markdownStore;
11
+ private readonly _markdownStoreSync;
12
+ private readonly _hashStore;
13
+ get markdownStore(): Cacheable;
14
+ get markdownStoreSync(): CacheableMemory;
15
+ get hashStore(): CacheableMemory;
16
+ getMarkdown(markdown: string, options?: RenderOptions): Promise<string | undefined>;
17
+ getMarkdownSync(markdown: string, options?: RenderOptions): string | undefined;
18
+ setMarkdown(markdown: string, value: string, options?: RenderOptions): Promise<boolean>;
19
+ setMarkdownSync(markdown: string, value: string, options?: RenderOptions): boolean;
20
+ get(key: string): Promise<string | undefined>;
21
+ getSync(key: string): string | undefined;
22
+ set(key: string, value: string): Promise<boolean>;
23
+ setSync(key: string, value: string): boolean;
24
+ clear(): Promise<void>;
25
+ setStorageAdapter(adapter: KeyvStoreAdapter): void;
26
+ hash(markdown: string, options?: RenderOptions): string;
27
+ }
28
+
29
+ type WritrOptions = {
30
+ openai?: string;
31
+ renderOptions?: RenderOptions;
32
+ };
33
+ type RenderOptions = {
34
+ emoji?: boolean;
35
+ toc?: boolean;
36
+ slug?: boolean;
37
+ highlight?: boolean;
38
+ gfm?: boolean;
39
+ math?: boolean;
40
+ mdx?: boolean;
41
+ caching?: boolean;
42
+ };
43
+ declare class Writr {
44
+ engine: unified.Processor<mdast.Root, mdast.Root, hast.Root, hast.Root, string>;
45
+ private readonly _options;
46
+ private _content;
47
+ private readonly _cache;
48
+ constructor(arguments1?: string | WritrOptions, arguments2?: WritrOptions);
49
+ get options(): WritrOptions;
50
+ get content(): string;
51
+ set content(value: string);
52
+ get cache(): WritrCache;
53
+ get frontMatterRaw(): string;
54
+ get body(): string;
55
+ get markdown(): string;
56
+ get frontMatter(): Record<string, any>;
57
+ set frontMatter(data: Record<string, any>);
58
+ getFrontMatterValue<T>(key: string): T;
59
+ render(options?: RenderOptions): Promise<string>;
60
+ renderSync(options?: RenderOptions): string;
61
+ renderReact(options?: RenderOptions, reactParseOptions?: HTMLReactParserOptions): Promise<string | React.JSX.Element | React.JSX.Element[]>;
62
+ renderReactSync(options?: RenderOptions, reactParseOptions?: HTMLReactParserOptions): string | React.JSX.Element | React.JSX.Element[];
63
+ loadFromFile(filePath: string): Promise<void>;
64
+ loadFromFileSync(filePath: string): void;
65
+ saveToFile(filePath: string): Promise<void>;
66
+ saveToFileSync(filePath: string): void;
67
+ private isCacheEnabled;
68
+ private createProcessor;
69
+ }
70
+
71
+ export { type RenderOptions, Writr, type WritrOptions };
package/dist/writr.d.ts CHANGED
@@ -1,6 +1,31 @@
1
- import type React from 'react';
2
- import { type HTMLReactParserOptions } from 'html-react-parser';
3
- import { WritrCache } from './writr-cache.js';
1
+ import * as unified from 'unified';
2
+ import * as hast from 'hast';
3
+ import * as mdast from 'mdast';
4
+ import React from 'react';
5
+ import { HTMLReactParserOptions } from 'html-react-parser';
6
+ import { Cacheable, CacheableMemory } from 'cacheable';
7
+ import { KeyvStoreAdapter } from 'keyv';
8
+
9
+ declare class WritrCache {
10
+ private _markdownStore;
11
+ private readonly _markdownStoreSync;
12
+ private readonly _hashStore;
13
+ get markdownStore(): Cacheable;
14
+ get markdownStoreSync(): CacheableMemory;
15
+ get hashStore(): CacheableMemory;
16
+ getMarkdown(markdown: string, options?: RenderOptions): Promise<string | undefined>;
17
+ getMarkdownSync(markdown: string, options?: RenderOptions): string | undefined;
18
+ setMarkdown(markdown: string, value: string, options?: RenderOptions): Promise<boolean>;
19
+ setMarkdownSync(markdown: string, value: string, options?: RenderOptions): boolean;
20
+ get(key: string): Promise<string | undefined>;
21
+ getSync(key: string): string | undefined;
22
+ set(key: string, value: string): Promise<boolean>;
23
+ setSync(key: string, value: string): boolean;
24
+ clear(): Promise<void>;
25
+ setStorageAdapter(adapter: KeyvStoreAdapter): void;
26
+ hash(markdown: string, options?: RenderOptions): string;
27
+ }
28
+
4
29
  type WritrOptions = {
5
30
  openai?: string;
6
31
  renderOptions?: RenderOptions;
@@ -16,7 +41,7 @@ type RenderOptions = {
16
41
  caching?: boolean;
17
42
  };
18
43
  declare class Writr {
19
- engine: import("unified").Processor<import("mdast").Root, import("mdast").Root, import("hast").Root, import("hast").Root, string>;
44
+ engine: unified.Processor<mdast.Root, mdast.Root, hast.Root, hast.Root, string>;
20
45
  private readonly _options;
21
46
  private _content;
22
47
  private readonly _cache;
@@ -42,4 +67,5 @@ declare class Writr {
42
67
  private isCacheEnabled;
43
68
  private createProcessor;
44
69
  }
45
- export { Writr, type WritrOptions, type RenderOptions };
70
+
71
+ export { type RenderOptions, Writr, type WritrOptions };
package/dist/writr.js CHANGED
@@ -1,233 +1,286 @@
1
- import fs from 'node:fs';
2
- import { dirname } from 'node:path';
3
- import { unified } from 'unified';
4
- import remarkParse from 'remark-parse';
5
- import remarkRehype from 'remark-rehype';
6
- import rehypeSlug from 'rehype-slug';
7
- import rehypeHighlight from 'rehype-highlight';
8
- import rehypeStringify from 'rehype-stringify';
9
- import remarkToc from 'remark-toc';
10
- import remarkMath from 'remark-math';
11
- import rehypeKatex from 'rehype-katex';
12
- import remarkGfm from 'remark-gfm';
13
- import remarkEmoji from 'remark-emoji';
14
- import remarkMDX from 'remark-mdx';
15
- import parse from 'html-react-parser';
16
- import * as yaml from 'js-yaml';
17
- import { WritrCache } from './writr-cache.js';
18
- class Writr {
19
- engine = unified()
20
- .use(remarkParse)
21
- .use(remarkGfm) // Use GitHub Flavored Markdown
22
- .use(remarkToc) // Add table of contents
23
- .use(remarkEmoji) // Add emoji support
24
- .use(remarkRehype) // Convert markdown to HTML
25
- .use(rehypeSlug) // Add slugs to headings in HTML
26
- .use(remarkMath) // Add math support
27
- .use(rehypeKatex) // Add math support
28
- .use(rehypeHighlight) // Apply syntax highlighting
29
- .use(remarkMDX) // Add MDX support
30
- .use(rehypeStringify); // Stringify HTML
31
- _options = {
32
- openai: undefined,
33
- renderOptions: {
34
- emoji: true,
35
- toc: true,
36
- slug: true,
37
- highlight: true,
38
- gfm: true,
39
- math: true,
40
- mdx: true,
41
- caching: true,
42
- },
43
- };
44
- _content = '';
45
- _cache = new WritrCache();
46
- constructor(arguments1, arguments2) {
47
- if (typeof arguments1 === 'string') {
48
- this._content = arguments1;
49
- }
50
- else if (arguments1) {
51
- this._options = { ...this._options, ...arguments1 };
52
- if (this._options.renderOptions) {
53
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
54
- this.engine = this.createProcessor(this._options.renderOptions);
55
- }
56
- }
57
- if (arguments2) {
58
- this._options = { ...this._options, ...arguments2 };
59
- if (this._options.renderOptions) {
60
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
61
- this.engine = this.createProcessor(this._options.renderOptions);
62
- }
63
- }
1
+ // src/writr.ts
2
+ import fs from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { unified } from "unified";
5
+ import remarkParse from "remark-parse";
6
+ import remarkRehype from "remark-rehype";
7
+ import rehypeSlug from "rehype-slug";
8
+ import rehypeHighlight from "rehype-highlight";
9
+ import rehypeStringify from "rehype-stringify";
10
+ import remarkToc from "remark-toc";
11
+ import remarkMath from "remark-math";
12
+ import rehypeKatex from "rehype-katex";
13
+ import remarkGfm from "remark-gfm";
14
+ import remarkEmoji from "remark-emoji";
15
+ import remarkMDX from "remark-mdx";
16
+ import parse from "html-react-parser";
17
+ import * as yaml from "js-yaml";
18
+
19
+ // src/writr-cache.ts
20
+ import { createHash } from "node:crypto";
21
+ import { Cacheable, CacheableMemory } from "cacheable";
22
+ var WritrCache = class {
23
+ _markdownStore = new Cacheable();
24
+ _markdownStoreSync = new CacheableMemory();
25
+ _hashStore = new CacheableMemory();
26
+ get markdownStore() {
27
+ return this._markdownStore;
28
+ }
29
+ get markdownStoreSync() {
30
+ return this._markdownStoreSync;
31
+ }
32
+ get hashStore() {
33
+ return this._hashStore;
34
+ }
35
+ async getMarkdown(markdown, options) {
36
+ const key = this.hash(markdown, options);
37
+ return this.get(key);
38
+ }
39
+ getMarkdownSync(markdown, options) {
40
+ const key = this.hash(markdown, options);
41
+ return this.getSync(key);
42
+ }
43
+ async setMarkdown(markdown, value, options) {
44
+ const key = this.hash(markdown, options);
45
+ return this.set(key, value);
46
+ }
47
+ setMarkdownSync(markdown, value, options) {
48
+ const key = this.hash(markdown, options);
49
+ this.setSync(key, value);
50
+ return true;
51
+ }
52
+ async get(key) {
53
+ return this._markdownStore.get(key);
54
+ }
55
+ getSync(key) {
56
+ return this._markdownStoreSync.get(key);
57
+ }
58
+ async set(key, value) {
59
+ return this._markdownStore.set(key, value);
60
+ }
61
+ setSync(key, value) {
62
+ this._markdownStoreSync.set(key, value);
63
+ return true;
64
+ }
65
+ async clear() {
66
+ await this._markdownStore.clear();
67
+ this._markdownStoreSync.clear();
68
+ this._hashStore.clear();
69
+ }
70
+ setStorageAdapter(adapter) {
71
+ this._markdownStore = new Cacheable({ primary: adapter });
72
+ }
73
+ hash(markdown, options) {
74
+ const key = JSON.stringify({ markdown, options });
75
+ let result = this._hashStore.get(key);
76
+ if (result) {
77
+ return result;
64
78
  }
65
- get options() {
66
- return this._options;
67
- }
68
- get content() {
69
- return this._content;
70
- }
71
- set content(value) {
72
- this._content = value;
73
- }
74
- get cache() {
75
- return this._cache;
76
- }
77
- get frontMatterRaw() {
78
- const start = this._content.indexOf('---\n');
79
- if (start === -1) {
80
- return '';
81
- } // Return empty string if no starting delimiter is found
82
- const end = this._content.indexOf('\n---\n', start + 4);
83
- if (end === -1) {
84
- return '';
85
- } // Return empty string if no ending delimiter is found
86
- return this._content.slice(start, end + 5); // Extract front matter including delimiters
87
- }
88
- get body() {
89
- const start = this._content.indexOf('---\n');
90
- if (start === -1) {
91
- return this._content;
92
- }
93
- const end = this._content.indexOf('\n---\n', start + 4);
94
- if (end === -1) {
95
- return this._content;
96
- }
97
- // Return the content after the closing --- marker
98
- return this._content.slice(Math.max(0, end + 5)).trim();
79
+ result = createHash("sha256").update(key).digest("hex");
80
+ this._hashStore.set(key, result);
81
+ return result;
82
+ }
83
+ };
84
+
85
+ // src/writr.ts
86
+ var Writr = class {
87
+ engine = unified().use(remarkParse).use(remarkGfm).use(remarkToc).use(remarkEmoji).use(remarkRehype).use(rehypeSlug).use(remarkMath).use(rehypeKatex).use(rehypeHighlight).use(remarkMDX).use(rehypeStringify);
88
+ // Stringify HTML
89
+ _options = {
90
+ openai: void 0,
91
+ renderOptions: {
92
+ emoji: true,
93
+ toc: true,
94
+ slug: true,
95
+ highlight: true,
96
+ gfm: true,
97
+ math: true,
98
+ mdx: true,
99
+ caching: true
99
100
  }
100
- get markdown() {
101
- return this.body;
101
+ };
102
+ _content = "";
103
+ _cache = new WritrCache();
104
+ constructor(arguments1, arguments2) {
105
+ if (typeof arguments1 === "string") {
106
+ this._content = arguments1;
107
+ } else if (arguments1) {
108
+ this._options = { ...this._options, ...arguments1 };
109
+ if (this._options.renderOptions) {
110
+ this.engine = this.createProcessor(this._options.renderOptions);
111
+ }
102
112
  }
103
- get frontMatter() {
104
- const frontMatter = this.frontMatterRaw;
105
- const match = /^---\s*([\s\S]*?)\s*---\s*/.exec(frontMatter);
106
- if (match) {
107
- return yaml.load(match[1].trim());
108
- }
109
- return {};
110
- }
111
- set frontMatter(data) {
112
- const frontMatter = this.frontMatterRaw;
113
- const yamlString = yaml.dump(data);
114
- const newFrontMatter = `---\n${yamlString}---\n`;
115
- this._content = this._content.replace(frontMatter, newFrontMatter);
116
- }
117
- getFrontMatterValue(key) {
118
- return this.frontMatter[key];
119
- }
120
- async render(options) {
121
- try {
122
- let result = '';
123
- if (this.isCacheEnabled(options)) {
124
- const cached = await this._cache.getMarkdown(this._content, options);
125
- if (cached) {
126
- return cached;
127
- }
128
- }
129
- let { engine } = this;
130
- if (options) {
131
- options = { ...this._options.renderOptions, ...options };
132
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
133
- engine = this.createProcessor(options);
134
- }
135
- const file = await engine.process(this.body);
136
- result = String(file);
137
- if (this.isCacheEnabled(options)) {
138
- await this._cache.setMarkdown(this._content, result, options);
139
- }
140
- return result;
141
- }
142
- catch (error) {
143
- throw new Error(`Failed to render markdown: ${error.message}`);
144
- }
113
+ if (arguments2) {
114
+ this._options = { ...this._options, ...arguments2 };
115
+ if (this._options.renderOptions) {
116
+ this.engine = this.createProcessor(this._options.renderOptions);
117
+ }
118
+ }
119
+ }
120
+ get options() {
121
+ return this._options;
122
+ }
123
+ get content() {
124
+ return this._content;
125
+ }
126
+ set content(value) {
127
+ this._content = value;
128
+ }
129
+ get cache() {
130
+ return this._cache;
131
+ }
132
+ get frontMatterRaw() {
133
+ const start = this._content.indexOf("---\n");
134
+ if (start === -1) {
135
+ return "";
136
+ }
137
+ const end = this._content.indexOf("\n---\n", start + 4);
138
+ if (end === -1) {
139
+ return "";
140
+ }
141
+ return this._content.slice(start, end + 5);
142
+ }
143
+ get body() {
144
+ const start = this._content.indexOf("---\n");
145
+ if (start === -1) {
146
+ return this._content;
145
147
  }
146
- renderSync(options) {
147
- try {
148
- let result = '';
149
- if (this.isCacheEnabled(options)) {
150
- const cached = this._cache.getMarkdownSync(this._content, options);
151
- if (cached) {
152
- return cached;
153
- }
154
- }
155
- let { engine } = this;
156
- if (options) {
157
- options = { ...this._options.renderOptions, ...options };
158
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
159
- engine = this.createProcessor(options);
160
- }
161
- const file = engine.processSync(this.body);
162
- result = String(file);
163
- if (this.isCacheEnabled(options)) {
164
- this._cache.setMarkdownSync(this._content, result, options);
165
- }
166
- return result;
148
+ const end = this._content.indexOf("\n---\n", start + 4);
149
+ if (end === -1) {
150
+ return this._content;
151
+ }
152
+ return this._content.slice(Math.max(0, end + 5)).trim();
153
+ }
154
+ get markdown() {
155
+ return this.body;
156
+ }
157
+ get frontMatter() {
158
+ const frontMatter = this.frontMatterRaw;
159
+ const match = /^---\s*([\s\S]*?)\s*---\s*/.exec(frontMatter);
160
+ if (match) {
161
+ return yaml.load(match[1].trim());
162
+ }
163
+ return {};
164
+ }
165
+ set frontMatter(data) {
166
+ const frontMatter = this.frontMatterRaw;
167
+ const yamlString = yaml.dump(data);
168
+ const newFrontMatter = `---
169
+ ${yamlString}---
170
+ `;
171
+ this._content = this._content.replace(frontMatter, newFrontMatter);
172
+ }
173
+ getFrontMatterValue(key) {
174
+ return this.frontMatter[key];
175
+ }
176
+ async render(options) {
177
+ try {
178
+ let result = "";
179
+ if (this.isCacheEnabled(options)) {
180
+ const cached = await this._cache.getMarkdown(this._content, options);
181
+ if (cached) {
182
+ return cached;
167
183
  }
168
- catch (error) {
169
- throw new Error(`Failed to render markdown: ${error.message}`);
184
+ }
185
+ let { engine } = this;
186
+ if (options) {
187
+ options = { ...this._options.renderOptions, ...options };
188
+ engine = this.createProcessor(options);
189
+ }
190
+ const file = await engine.process(this.body);
191
+ result = String(file);
192
+ if (this.isCacheEnabled(options)) {
193
+ await this._cache.setMarkdown(this._content, result, options);
194
+ }
195
+ return result;
196
+ } catch (error) {
197
+ throw new Error(`Failed to render markdown: ${error.message}`);
198
+ }
199
+ }
200
+ renderSync(options) {
201
+ try {
202
+ let result = "";
203
+ if (this.isCacheEnabled(options)) {
204
+ const cached = this._cache.getMarkdownSync(this._content, options);
205
+ if (cached) {
206
+ return cached;
170
207
  }
208
+ }
209
+ let { engine } = this;
210
+ if (options) {
211
+ options = { ...this._options.renderOptions, ...options };
212
+ engine = this.createProcessor(options);
213
+ }
214
+ const file = engine.processSync(this.body);
215
+ result = String(file);
216
+ if (this.isCacheEnabled(options)) {
217
+ this._cache.setMarkdownSync(this._content, result, options);
218
+ }
219
+ return result;
220
+ } catch (error) {
221
+ throw new Error(`Failed to render markdown: ${error.message}`);
171
222
  }
172
- async renderReact(options, reactParseOptions) {
173
- const html = await this.render(options);
174
- return parse(html, reactParseOptions);
223
+ }
224
+ async renderReact(options, reactParseOptions) {
225
+ const html = await this.render(options);
226
+ return parse(html, reactParseOptions);
227
+ }
228
+ renderReactSync(options, reactParseOptions) {
229
+ const html = this.renderSync(options);
230
+ return parse(html, reactParseOptions);
231
+ }
232
+ async loadFromFile(filePath) {
233
+ const { readFile } = fs.promises;
234
+ this._content = await readFile(filePath, "utf8");
235
+ }
236
+ loadFromFileSync(filePath) {
237
+ this._content = fs.readFileSync(filePath, "utf8");
238
+ }
239
+ async saveToFile(filePath) {
240
+ const { writeFile, mkdir } = fs.promises;
241
+ const directoryPath = dirname(filePath);
242
+ await mkdir(directoryPath, { recursive: true });
243
+ await writeFile(filePath, this._content, "utf8");
244
+ }
245
+ saveToFileSync(filePath) {
246
+ const directoryPath = dirname(filePath);
247
+ fs.mkdirSync(directoryPath, { recursive: true });
248
+ fs.writeFileSync(filePath, this._content, "utf8");
249
+ }
250
+ isCacheEnabled(options) {
251
+ if (options?.caching !== void 0) {
252
+ return options.caching;
175
253
  }
176
- renderReactSync(options, reactParseOptions) {
177
- const html = this.renderSync(options);
178
- return parse(html, reactParseOptions);
254
+ return this._options?.renderOptions?.caching ?? false;
255
+ }
256
+ createProcessor(options) {
257
+ const processor = unified().use(remarkParse);
258
+ if (options.gfm) {
259
+ processor.use(remarkGfm);
179
260
  }
180
- async loadFromFile(filePath) {
181
- const { readFile } = fs.promises;
182
- this._content = await readFile(filePath, 'utf8');
261
+ if (options.toc) {
262
+ processor.use(remarkToc, { heading: "toc|table of contents" });
183
263
  }
184
- loadFromFileSync(filePath) {
185
- this._content = fs.readFileSync(filePath, 'utf8');
264
+ if (options.emoji) {
265
+ processor.use(remarkEmoji);
186
266
  }
187
- async saveToFile(filePath) {
188
- const { writeFile, mkdir } = fs.promises;
189
- const directoryPath = dirname(filePath);
190
- await mkdir(directoryPath, { recursive: true });
191
- await writeFile(filePath, this._content, 'utf8');
267
+ processor.use(remarkRehype);
268
+ if (options.slug) {
269
+ processor.use(rehypeSlug);
192
270
  }
193
- saveToFileSync(filePath) {
194
- const directoryPath = dirname(filePath);
195
- fs.mkdirSync(directoryPath, { recursive: true });
196
- fs.writeFileSync(filePath, this._content, 'utf8');
271
+ if (options.highlight) {
272
+ processor.use(rehypeHighlight);
197
273
  }
198
- isCacheEnabled(options) {
199
- if (options?.caching !== undefined) {
200
- return options.caching;
201
- }
202
- return this._options?.renderOptions?.caching ?? false;
274
+ if (options.math) {
275
+ processor.use(remarkMath).use(rehypeKatex);
203
276
  }
204
- createProcessor(options) {
205
- const processor = unified().use(remarkParse);
206
- if (options.gfm) {
207
- processor.use(remarkGfm);
208
- }
209
- if (options.toc) {
210
- processor.use(remarkToc, { heading: 'toc|table of contents' });
211
- }
212
- if (options.emoji) {
213
- processor.use(remarkEmoji);
214
- }
215
- processor.use(remarkRehype);
216
- if (options.slug) {
217
- processor.use(rehypeSlug);
218
- }
219
- if (options.highlight) {
220
- processor.use(rehypeHighlight);
221
- }
222
- if (options.math) {
223
- processor.use(remarkMath).use(rehypeKatex);
224
- }
225
- if (options.mdx) {
226
- processor.use(remarkMDX);
227
- }
228
- processor.use(rehypeStringify);
229
- return processor;
277
+ if (options.mdx) {
278
+ processor.use(remarkMDX);
230
279
  }
231
- }
232
- export { Writr };
233
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd3JpdHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3pCLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDbEMsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUNoQyxPQUFPLFdBQVcsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxZQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sVUFBVSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLGVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLGVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDbkMsT0FBTyxVQUFVLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sV0FBVyxNQUFNLGNBQWMsQ0FBQztBQUN2QyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDbkMsT0FBTyxXQUFXLE1BQU0sY0FBYyxDQUFDO0FBQ3ZDLE9BQU8sU0FBUyxNQUFNLFlBQVksQ0FBQztBQUVuQyxPQUFPLEtBQW9DLE1BQU0sbUJBQW1CLENBQUM7QUFDckUsT0FBTyxLQUFLLElBQUksTUFBTSxTQUFTLENBQUM7QUFDaEMsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBa0I1QyxNQUFNLEtBQUs7SUFDSCxNQUFNLEdBQUcsT0FBTyxFQUFFO1NBQ3ZCLEdBQUcsQ0FBQyxXQUFXLENBQUM7U0FDaEIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLCtCQUErQjtTQUM5QyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsd0JBQXdCO1NBQ3ZDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxvQkFBb0I7U0FDckMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDLDJCQUEyQjtTQUM3QyxHQUFH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QUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ25CLFNBQVMsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUIsQ0FBQztRQUVELFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFNUIsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMzQixDQUFDO1FBRUQsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdkIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBRUQsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQ2pCLFNBQVMsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUIsQ0FBQztRQUVELFNBQVMsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFL0IsT0FBTyxTQUFTLENBQUM7SUFDbEIsQ0FBQztDQUNEO0FBRUQsT0FBTyxFQUFDLEtBQUssRUFBd0MsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBmcyBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7ZGlybmFtZX0gZnJvbSAnbm9kZTpwYXRoJztcbmltcG9ydCB7dW5pZmllZH0gZnJvbSAndW5pZmllZCc7XG5pbXBvcnQgcmVtYXJrUGFyc2UgZnJvbSAncmVtYXJrLXBhcnNlJztcbmltcG9ydCByZW1hcmtSZWh5cGUgZnJvbSAncmVtYXJrLXJlaHlwZSc7XG5pbXBvcnQgcmVoeXBlU2x1ZyBmcm9tICdyZWh5cGUtc2x1Zyc7XG5pbXBvcnQgcmVoeXBlSGlnaGxpZ2h0IGZyb20gJ3JlaHlwZS1oaWdobGlnaHQnO1xuaW1wb3J0IHJlaHlwZVN0cmluZ2lmeSBmcm9tICdyZWh5cGUtc3RyaW5naWZ5JztcbmltcG9ydCByZW1hcmtUb2MgZnJvbSAncmVtYXJrLXRvYyc7XG5pbXBvcnQgcmVtYXJrTWF0aCBmcm9tICdyZW1hcmstbWF0aCc7XG5pbXBvcnQgcmVoeXBlS2F0ZXggZnJvbSAncmVoeXBlLWthdGV4JztcbmltcG9ydCByZW1hcmtHZm0gZnJvbSAncmVtYXJrLWdmbSc7XG5pbXBvcnQgcmVtYXJrRW1vamkgZnJvbSAncmVtYXJrLWVtb2ppJztcbmltcG9ydCByZW1hcmtNRFggZnJvbSAncmVtYXJrLW1keCc7XG5pbXBvcnQgdHlwZSBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgcGFyc2UsIHt0eXBlIEhUTUxSZWFjdFBhcnNlck9wdGlvbnN9IGZyb20gJ2h0bWwtcmVhY3QtcGFyc2VyJztcbmltcG9ydCAqIGFzIHlhbWwgZnJvbSAnanMteWFtbCc7XG5pbXBvcnQge1dyaXRyQ2FjaGV9IGZyb20gJy4vd3JpdHItY2FjaGUuanMnO1xuXG50eXBlIFdyaXRyT3B0aW9ucyA9IHtcblx0b3BlbmFpPzogc3RyaW5nOyAvLyBPcGVuYWkgYXBpIGtleSAoZGVmYXVsdDogdW5kZWZpbmVkKVxuXHRyZW5kZXJPcHRpb25zPzogUmVuZGVyT3B0aW9uczsgLy8gRGVmYXVsdCByZW5kZXIgb3B0aW9ucyAoZGVmYXVsdDogdW5kZWZpbmVkKVxufTtcblxudHlwZSBSZW5kZXJPcHRpb25zID0ge1xuXHRlbW9qaT86IGJvb2xlYW47IC8vIEVtb2ppIHN1cHBvcnQgKGRlZmF1bHQ6IHRydWUpXG5cdHRvYz86IGJvb2xlYW47IC8vIFRhYmxlIG9mIGNvbnRlbnRzIGdlbmVyYXRpb24gKGRlZmF1bHQ6IHRydWUpXG5cdHNsdWc/OiBib29sZWFuOyAvLyBTbHVnIGdlbmVyYXRpb24gKGRlZmF1bHQ6IHRydWUpXG5cdGhpZ2hsaWdodD86IGJvb2xlYW47IC8vIENvZGUgaGlnaGxpZ2h0aW5nIChkZWZhdWx0OiB0cnVlKVxuXHRnZm0/OiBib29sZWFuOyAvLyBHaXRodWIgZmxhdm9yIG1hcmtkb3duIChkZWZhdWx0OiB0cnVlKVxuXHRtYXRoPzogYm9vbGVhbjsgLy8gTWF0aCBzdXBwb3J0IChkZWZhdWx0OiB0cnVlKVxuXHRtZHg/OiBib29sZWFuOyAvLyBNRFggc3VwcG9ydCAoZGVmYXVsdDogdHJ1ZSlcblx0Y2FjaGluZz86IGJvb2xlYW47IC8vIENhY2hpbmcgKGRlZmF1bHQ6IHRydWUpXG59O1xuXG5jbGFzcyBXcml0ciB7XG5cdHB1YmxpYyBlbmdpbmUgPSB1bmlmaWVkKClcblx0XHQudXNlKHJlbWFya1BhcnNlKVxuXHRcdC51c2UocmVtYXJrR2ZtKSAvLyBVc2UgR2l0SHViIEZsYXZvcmVkIE1hcmtkb3duXG5cdFx0LnVzZShyZW1hcmtUb2MpIC8vIEFkZCB0YWJsZSBvZiBjb250ZW50c1xuXHRcdC51c2UocmVtYXJrRW1vamkpIC8vIEFkZCBlbW9qaSBzdXBwb3J0XG5cdFx0LnVzZShyZW1hcmtSZWh5cGUpIC8vIENvbnZlcnQgbWFya2Rvd24gdG8gSFRNTFxuXHRcdC51c2UocmVoeXBlU2x1ZykgLy8gQWRkIHNsdWdzIHRvIGhlYWRpbmdzIGluIEhUTUxcblx0XHQudXNlKHJlbWFya01hdGgpIC8vIEFkZCBtYXRoIHN1cHBvcnRcblx0XHQudXNlKHJlaHlwZUthdGV4KSAvLyBBZGQgbWF0aCBzdXBwb3J0XG5cdFx0LnVzZShyZWh5cGVIaWdobGlnaHQpIC8vIEFwcGx5IHN5bnRheCBoaWdobGlnaHRpbmdcblx0XHQudXNlKHJlbWFya01EWCkgLy8gQWRkIE1EWCBzdXBwb3J0XG5cdFx0LnVzZShyZWh5cGVTdHJpbmdpZnkpOyAvLyBTdHJpbmdpZnkgSFRNTFxuXG5cdHByaXZhdGUgcmVhZG9ubHkgX29wdGlvbnM6IFdyaXRyT3B0aW9ucyA9IHtcblx0XHRvcGVuYWk6IHVuZGVmaW5lZCxcblx0XHRyZW5kZXJPcHRpb25zOiB7XG5cdFx0XHRlbW9qaTogdHJ1ZSxcblx0XHRcdHRvYzogdHJ1ZSxcblx0XHRcdHNsdWc6IHRydWUsXG5cdFx0XHRoaWdobGlnaHQ6IHRydWUsXG5cdFx0XHRnZm06IHRydWUsXG5cdFx0XHRtYXRoOiB0cnVlLFxuXHRcdFx0bWR4OiB0cnVlLFxuXHRcdFx0Y2FjaGluZzogdHJ1ZSxcblx0XHR9LFxuXHR9O1xuXG5cdHByaXZhdGUgX2NvbnRlbnQgPSAnJztcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9jYWNoZSA9IG5ldyBXcml0ckNhY2hlKCk7XG5cblx0Y29uc3RydWN0b3IoYXJndW1lbnRzMT86IHN0cmluZyB8IFdyaXRyT3B0aW9ucywgYXJndW1lbnRzMj86IFdyaXRyT3B0aW9ucykge1xuXHRcdGlmICh0eXBlb2YgYXJndW1lbnRzMSA9PT0gJ3N0cmluZycpIHtcblx0XHRcdHRoaXMuX2NvbnRlbnQgPSBhcmd1bWVudHMxO1xuXHRcdH0gZWxzZSBpZiAoYXJndW1lbnRzMSkge1xuXHRcdFx0dGhpcy5fb3B0aW9ucyA9IHsuLi50aGlzLl9vcHRpb25zLCAuLi5hcmd1bWVudHMxfTtcblx0XHRcdGlmICh0aGlzLl9vcHRpb25zLnJlbmRlck9wdGlvbnMpIHtcblx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXNzaWdubWVudFxuXHRcdFx0XHR0aGlzLmVuZ2luZSA9IHRoaXMuY3JlYXRlUHJvY2Vzc29yKHRoaXMuX29wdGlvbnMucmVuZGVyT3B0aW9ucyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKGFyZ3VtZW50czIpIHtcblx0XHRcdHRoaXMuX29wdGlvbnMgPSB7Li4udGhpcy5fb3B0aW9ucywgLi4uYXJndW1lbnRzMn07XG5cdFx0XHRpZiAodGhpcy5fb3B0aW9ucy5yZW5kZXJPcHRpb25zKSB7XG5cdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnRcblx0XHRcdFx0dGhpcy5lbmdpbmUgPSB0aGlzLmNyZWF0ZVByb2Nlc3Nvcih0aGlzLl9vcHRpb25zLnJlbmRlck9wdGlvbnMpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBnZXQgb3B0aW9ucygpOiBXcml0ck9wdGlvbnMge1xuXHRcdHJldHVybiB0aGlzLl9vcHRpb25zO1xuXHR9XG5cblx0cHVibGljIGdldCBjb250ZW50KCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIHRoaXMuX2NvbnRlbnQ7XG5cdH1cblxuXHRwdWJsaWMgc2V0IGNvbnRlbnQodmFsdWU6IHN0cmluZykge1xuXHRcdHRoaXMuX2NvbnRlbnQgPSB2YWx1ZTtcblx0fVxuXG5cdHB1YmxpYyBnZXQgY2FjaGUoKTogV3JpdHJDYWNoZSB7XG5cdFx0cmV0dXJuIHRoaXMuX2NhY2hlO1xuXHR9XG5cblx0Z2V0IGZyb250TWF0dGVyUmF3KCk6IHN0cmluZyB7XG5cdFx0Y29uc3Qgc3RhcnQgPSB0aGlzLl9jb250ZW50LmluZGV4T2YoJy0tLVxcbicpO1xuXHRcdGlmIChzdGFydCA9PT0gLTEpIHtcblx0XHRcdHJldHVybiAnJztcblx0XHR9IC8vIFJldHVybiBlbXB0eSBzdHJpbmcgaWYgbm8gc3RhcnRpbmcgZGVsaW1pdGVyIGlzIGZvdW5kXG5cblx0XHRjb25zdCBlbmQgPSB0aGlzLl9jb250ZW50LmluZGV4T2YoJ1xcbi0tLVxcbicsIHN0YXJ0ICsgNCk7XG5cdFx0aWYgKGVuZCA9PT0gLTEpIHtcblx0XHRcdHJldHVybiAnJztcblx0XHR9IC8vIFJldHVybiBlbXB0eSBzdHJpbmcgaWYgbm8gZW5kaW5nIGRlbGltaXRlciBpcyBmb3VuZFxuXG5cdFx0cmV0dXJuIHRoaXMuX2NvbnRlbnQuc2xpY2Uoc3RhcnQsIGVuZCArIDUpOyAvLyBFeHRyYWN0IGZyb250IG1hdHRlciBpbmNsdWRpbmcgZGVsaW1pdGVyc1xuXHR9XG5cblx0Z2V0IGJvZHkoKTogc3RyaW5nIHtcblx0XHRjb25zdCBzdGFydCA9IHRoaXMuX2NvbnRlbnQuaW5kZXhPZignLS0tXFxuJyk7XG5cdFx0aWYgKHN0YXJ0ID09PSAtMSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuX2NvbnRlbnQ7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZW5kID0gdGhpcy5fY29udGVudC5pbmRleE9mKCdcXG4tLS1cXG4nLCBzdGFydCArIDQpO1xuXHRcdGlmIChlbmQgPT09IC0xKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5fY29udGVudDtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm4gdGhlIGNvbnRlbnQgYWZ0ZXIgdGhlIGNsb3NpbmcgLS0tIG1hcmtlclxuXHRcdHJldHVybiB0aGlzLl9jb250ZW50LnNsaWNlKE1hdGgubWF4KDAsIGVuZCArIDUpKS50cmltKCk7XG5cdH1cblxuXHRnZXQgbWFya2Rvd24oKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gdGhpcy5ib2R5O1xuXHR9XG5cblx0Z2V0IGZyb250TWF0dGVyKCk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuXHRcdGNvbnN0IGZyb250TWF0dGVyID0gdGhpcy5mcm9udE1hdHRlclJhdztcblx0XHRjb25zdCBtYXRjaCA9IC9eLS0tXFxzKihbXFxzXFxTXSo/KVxccyotLS1cXHMqLy5leGVjKGZyb250TWF0dGVyKTtcblx0XHRpZiAobWF0Y2gpIHtcblx0XHRcdHJldHVybiB5YW1sLmxvYWQobWF0Y2hbMV0udHJpbSgpKSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXHRcdH1cblxuXHRcdHJldHVybiB7fTtcblx0fVxuXG5cdHNldCBmcm9udE1hdHRlcihkYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KSB7XG5cdFx0Y29uc3QgZnJvbnRNYXR0ZXIgPSB0aGlzLmZyb250TWF0dGVyUmF3O1xuXHRcdGNvbnN0IHlhbWxTdHJpbmcgPSB5YW1sLmR1bXAoZGF0YSk7XG5cdFx0Y29uc3QgbmV3RnJvbnRNYXR0ZXIgPSBgLS0tXFxuJHt5YW1sU3RyaW5nfS0tLVxcbmA7XG5cdFx0dGhpcy5fY29udGVudCA9IHRoaXMuX2NvbnRlbnQucmVwbGFjZShmcm9udE1hdHRlciwgbmV3RnJvbnRNYXR0ZXIpO1xuXHR9XG5cblx0cHVibGljIGdldEZyb250TWF0dGVyVmFsdWU8VD4oa2V5OiBzdHJpbmcpOiBUIHtcblx0XHRyZXR1cm4gdGhpcy5mcm9udE1hdHRlcltrZXldIGFzIFQ7XG5cdH1cblxuXHRhc3luYyByZW5kZXIob3B0aW9ucz86IFJlbmRlck9wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4ge1xuXHRcdHRyeSB7XG5cdFx0XHRsZXQgcmVzdWx0ID0gJyc7XG5cdFx0XHRpZiAodGhpcy5pc0NhY2hlRW5hYmxlZChvcHRpb25zKSkge1xuXHRcdFx0XHRjb25zdCBjYWNoZWQgPSBhd2FpdCB0aGlzLl9jYWNoZS5nZXRNYXJrZG93bih0aGlzLl9jb250ZW50LCBvcHRpb25zKTtcblx0XHRcdFx0aWYgKGNhY2hlZCkge1xuXHRcdFx0XHRcdHJldHVybiBjYWNoZWQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0bGV0IHtlbmdpbmV9ID0gdGhpcztcblx0XHRcdGlmIChvcHRpb25zKSB7XG5cdFx0XHRcdG9wdGlvbnMgPSB7Li4udGhpcy5fb3B0aW9ucy5yZW5kZXJPcHRpb25zLCAuLi5vcHRpb25zfTtcblx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXNzaWdubWVudFxuXHRcdFx0XHRlbmdpbmUgPSB0aGlzLmNyZWF0ZVByb2Nlc3NvcihvcHRpb25zKTtcblx0XHRcdH1cblxuXHRcdFx0Y29uc3QgZmlsZSA9IGF3YWl0IGVuZ2luZS5wcm9jZXNzKHRoaXMuYm9keSk7XG5cdFx0XHRyZXN1bHQgPSBTdHJpbmcoZmlsZSk7XG5cdFx0XHRpZiAodGhpcy5pc0NhY2hlRW5hYmxlZChvcHRpb25zKSkge1xuXHRcdFx0XHRhd2FpdCB0aGlzLl9jYWNoZS5zZXRNYXJrZG93bih0aGlzLl9jb250ZW50LCByZXN1bHQsIG9wdGlvbnMpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZW5kZXIgbWFya2Rvd246ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuXHRcdH1cblx0fVxuXG5cdHJlbmRlclN5bmMob3B0aW9ucz86IFJlbmRlck9wdGlvbnMpOiBzdHJpbmcge1xuXHRcdHRyeSB7XG5cdFx0XHRsZXQgcmVzdWx0ID0gJyc7XG5cdFx0XHRpZiAodGhpcy5pc0NhY2hlRW5hYmxlZChvcHRpb25zKSkge1xuXHRcdFx0XHRjb25zdCBjYWNoZWQgPSB0aGlzLl9jYWNoZS5nZXRNYXJrZG93blN5bmModGhpcy5fY29udGVudCwgb3B0aW9ucyk7XG5cdFx0XHRcdGlmIChjYWNoZWQpIHtcblx0XHRcdFx0XHRyZXR1cm4gY2FjaGVkO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGxldCB7ZW5naW5lfSA9IHRoaXM7XG5cdFx0XHRpZiAob3B0aW9ucykge1xuXHRcdFx0XHRvcHRpb25zID0gey4uLnRoaXMuX29wdGlvbnMucmVuZGVyT3B0aW9ucywgLi4ub3B0aW9uc307XG5cdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnRcblx0XHRcdFx0ZW5naW5lID0gdGhpcy5jcmVhdGVQcm9jZXNzb3Iob3B0aW9ucyk7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGZpbGUgPSBlbmdpbmUucHJvY2Vzc1N5bmModGhpcy5ib2R5KTtcblx0XHRcdHJlc3VsdCA9IFN0cmluZyhmaWxlKTtcblx0XHRcdGlmICh0aGlzLmlzQ2FjaGVFbmFibGVkKG9wdGlvbnMpKSB7XG5cdFx0XHRcdHRoaXMuX2NhY2hlLnNldE1hcmtkb3duU3luYyh0aGlzLl9jb250ZW50LCByZXN1bHQsIG9wdGlvbnMpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZW5kZXIgbWFya2Rvd246ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuXHRcdH1cblx0fVxuXG5cdGFzeW5jIHJlbmRlclJlYWN0KG9wdGlvbnM/OiBSZW5kZXJPcHRpb25zLCByZWFjdFBhcnNlT3B0aW9ucz86IEhUTUxSZWFjdFBhcnNlck9wdGlvbnMpOiBQcm9taXNlPHN0cmluZyB8IFJlYWN0LkpTWC5FbGVtZW50IHwgUmVhY3QuSlNYLkVsZW1lbnRbXT4ge1xuXHRcdGNvbnN0IGh0bWwgPSBhd2FpdCB0aGlzLnJlbmRlcihvcHRpb25zKTtcblxuXHRcdHJldHVybiBwYXJzZShodG1sLCByZWFjdFBhcnNlT3B0aW9ucyk7XG5cdH1cblxuXHRyZW5kZXJSZWFjdFN5bmMob3B0aW9ucz86IFJlbmRlck9wdGlvbnMsIHJlYWN0UGFyc2VPcHRpb25zPzogSFRNTFJlYWN0UGFyc2VyT3B0aW9ucyk6IHN0cmluZyB8IFJlYWN0LkpTWC5FbGVtZW50IHwgUmVhY3QuSlNYLkVsZW1lbnRbXSB7XG5cdFx0Y29uc3QgaHRtbCA9IHRoaXMucmVuZGVyU3luYyhvcHRpb25zKTtcblx0XHRyZXR1cm4gcGFyc2UoaHRtbCwgcmVhY3RQYXJzZU9wdGlvbnMpO1xuXHR9XG5cblx0YXN5bmMgbG9hZEZyb21GaWxlKGZpbGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRjb25zdCB7cmVhZEZpbGV9ID0gZnMucHJvbWlzZXM7XG5cdFx0dGhpcy5fY29udGVudCA9IGF3YWl0IHJlYWRGaWxlKGZpbGVQYXRoLCAndXRmOCcpO1xuXHR9XG5cblx0bG9hZEZyb21GaWxlU3luYyhmaWxlUGF0aDogc3RyaW5nKTogdm9pZCB7XG5cdFx0dGhpcy5fY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCwgJ3V0ZjgnKTtcblx0fVxuXG5cdGFzeW5jIHNhdmVUb0ZpbGUoZmlsZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IHt3cml0ZUZpbGUsIG1rZGlyfSA9IGZzLnByb21pc2VzO1xuXHRcdGNvbnN0IGRpcmVjdG9yeVBhdGggPSBkaXJuYW1lKGZpbGVQYXRoKTtcblx0XHRhd2FpdCBta2RpcihkaXJlY3RvcnlQYXRoLCB7cmVjdXJzaXZlOiB0cnVlfSk7XG5cdFx0YXdhaXQgd3JpdGVGaWxlKGZpbGVQYXRoLCB0aGlzLl9jb250ZW50LCAndXRmOCcpO1xuXHR9XG5cblx0c2F2ZVRvRmlsZVN5bmMoZmlsZVBhdGg6IHN0cmluZyk6IHZvaWQge1xuXHRcdGNvbnN0IGRpcmVjdG9yeVBhdGggPSBkaXJuYW1lKGZpbGVQYXRoKTtcblx0XHRmcy5ta2RpclN5bmMoZGlyZWN0b3J5UGF0aCwge3JlY3Vyc2l2ZTogdHJ1ZX0pO1xuXHRcdGZzLndyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIHRoaXMuX2NvbnRlbnQsICd1dGY4Jyk7XG5cdH1cblxuXHRwcml2YXRlIGlzQ2FjaGVFbmFibGVkKG9wdGlvbnM/OiBSZW5kZXJPcHRpb25zKTogYm9vbGVhbiB7XG5cdFx0aWYgKG9wdGlvbnM/LmNhY2hpbmcgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuIG9wdGlvbnMuY2FjaGluZztcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5fb3B0aW9ucz8ucmVuZGVyT3B0aW9ucz8uY2FjaGluZyA/PyBmYWxzZTtcblx0fVxuXG5cdHByaXZhdGUgY3JlYXRlUHJvY2Vzc29yKG9wdGlvbnM6IFJlbmRlck9wdGlvbnMpOiBhbnkge1xuXHRcdGNvbnN0IHByb2Nlc3NvciA9IHVuaWZpZWQoKS51c2UocmVtYXJrUGFyc2UpO1xuXG5cdFx0aWYgKG9wdGlvbnMuZ2ZtKSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlbWFya0dmbSk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMudG9jKSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlbWFya1RvYywge2hlYWRpbmc6ICd0b2N8dGFibGUgb2YgY29udGVudHMnfSk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuZW1vamkpIHtcblx0XHRcdHByb2Nlc3Nvci51c2UocmVtYXJrRW1vamkpO1xuXHRcdH1cblxuXHRcdHByb2Nlc3Nvci51c2UocmVtYXJrUmVoeXBlKTtcblxuXHRcdGlmIChvcHRpb25zLnNsdWcpIHtcblx0XHRcdHByb2Nlc3Nvci51c2UocmVoeXBlU2x1Zyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuaGlnaGxpZ2h0KSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlaHlwZUhpZ2hsaWdodCk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMubWF0aCkge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZW1hcmtNYXRoKS51c2UocmVoeXBlS2F0ZXgpO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLm1keCkge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZW1hcmtNRFgpO1xuXHRcdH1cblxuXHRcdHByb2Nlc3Nvci51c2UocmVoeXBlU3RyaW5naWZ5KTtcblxuXHRcdHJldHVybiBwcm9jZXNzb3I7XG5cdH1cbn1cblxuZXhwb3J0IHtXcml0ciwgdHlwZSBXcml0ck9wdGlvbnMsIHR5cGUgUmVuZGVyT3B0aW9uc307XG5cbiJdfQ==
280
+ processor.use(rehypeStringify);
281
+ return processor;
282
+ }
283
+ };
284
+ export {
285
+ Writr
286
+ };
package/package.json CHANGED
@@ -1,10 +1,17 @@
1
1
  {
2
2
  "name": "writr",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Markdown Rendering Simplified",
5
5
  "type": "module",
6
- "exports": "./dist/writr.js",
6
+ "main": "./dist/writr.cjs",
7
+ "module": "./dist/writr.js",
7
8
  "types": "./dist/writr.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "require": "./dist/writr.cjs",
12
+ "import": "./dist/writr.js"
13
+ }
14
+ },
8
15
  "repository": "https://github.com/jaredwray/writr.git",
9
16
  "author": "Jared Wray <me@jaredwray.com>",
10
17
  "engines": {
@@ -41,44 +48,46 @@
41
48
  ],
42
49
  "scripts": {
43
50
  "clean": "rimraf ./dist ./coverage ./node_modules ./package-lock.json ./yarn.lock ./site/README.md ./site/dist",
44
- "build": "rimraf ./dist && tsc",
45
- "test": "xo --fix && vitest run --coverage",
51
+ "build": "rimraf ./dist && tsup src/writr.ts --format cjs,esm --dts --clean",
46
52
  "prepare": "npm run build",
53
+ "test": "xo --fix && vitest run --coverage",
47
54
  "website:build": "rimraf ./site/README.md ./site/dist && npx docula build -s ./site -o ./site/dist",
48
55
  "website:serve": "rimraf ./site/README.md ./site/dist && npx docula serve -s ./site -o ./site/dist"
49
56
  },
50
57
  "dependencies": {
58
+ "cacheable": "^1.7.1",
51
59
  "crypto": "^1.0.1",
52
60
  "fs": "^0.0.1-security",
53
- "html-react-parser": "^5.1.15",
61
+ "html-react-parser": "^5.1.16",
54
62
  "js-yaml": "^4.1.0",
55
- "keyv": "^5.0.1",
63
+ "keyv": "^5.0.3",
56
64
  "react": "^18.3.1",
57
65
  "rehype-highlight": "^7.0.0",
58
66
  "rehype-katex": "^7.0.1",
59
67
  "rehype-slug": "^6.0.0",
60
- "rehype-stringify": "^10.0.0",
68
+ "rehype-stringify": "^10.0.1",
61
69
  "remark-emoji": "^5.0.1",
62
70
  "remark-gfm": "^4.0.0",
63
71
  "remark-math": "^6.0.0",
64
72
  "remark-mdx": "^3.0.1",
65
73
  "remark-parse": "^11.0.0",
66
- "remark-rehype": "^11.1.0",
74
+ "remark-rehype": "^11.1.1",
67
75
  "remark-toc": "^9.0.0",
68
76
  "unified": "^11.0.5"
69
77
  },
70
78
  "devDependencies": {
71
79
  "@keyv/sqlite": "^4.0.1",
72
80
  "@types/js-yaml": "^4.0.9",
73
- "@types/node": "^22.5.1",
74
- "@types/react": "^18.3.5",
75
- "@vitest/coverage-v8": "^2.0.5",
76
- "docula": "^0.9.0",
81
+ "@types/node": "^22.7.4",
82
+ "@types/react": "^18.3.10",
83
+ "@vitest/coverage-v8": "^2.1.1",
84
+ "docula": "^0.9.1",
77
85
  "rimraf": "^6.0.1",
78
86
  "ts-node": "^10.9.2",
79
- "typescript": "^5.5.4",
80
- "vitest": "^2.0.5",
81
- "webpack": "^5.94.0",
87
+ "tsup": "^8.3.0",
88
+ "typescript": "^5.6.2",
89
+ "vitest": "^2.1.1",
90
+ "webpack": "^5.95.0",
82
91
  "xo": "^0.59.3"
83
92
  },
84
93
  "xo": {
@@ -1,22 +0,0 @@
1
- import { Keyv, type KeyvStoreAdapter } from 'keyv';
2
- import { type RenderOptions } from './writr.js';
3
- export declare class WritrCache {
4
- private _markdownStore;
5
- private _markdownStoreSync;
6
- private _hashStore;
7
- constructor();
8
- get markdownStore(): Keyv;
9
- get markdownStoreSync(): Map<string, string>;
10
- get hashStore(): Map<string, string>;
11
- getMarkdown(markdown: string, options?: RenderOptions): Promise<string | undefined>;
12
- getMarkdownSync(markdown: string, options?: RenderOptions): string | undefined;
13
- setMarkdown(markdown: string, value: string, options?: RenderOptions): Promise<boolean>;
14
- setMarkdownSync(markdown: string, value: string, options?: RenderOptions): boolean;
15
- get(key: string): Promise<string | undefined>;
16
- getSync(key: string): string | undefined;
17
- set(key: string, value: string): Promise<boolean>;
18
- setSync(key: string, value: string): boolean;
19
- clear(): Promise<void>;
20
- setStorageAdapter(adapter: KeyvStoreAdapter): void;
21
- hash(markdown: string, options?: RenderOptions): string;
22
- }
@@ -1,70 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { Keyv } from 'keyv';
3
- export class WritrCache {
4
- _markdownStore;
5
- _markdownStoreSync;
6
- _hashStore;
7
- constructor() {
8
- this._markdownStore = new Keyv();
9
- this._markdownStoreSync = new Map();
10
- this._hashStore = new Map();
11
- }
12
- get markdownStore() {
13
- return this._markdownStore;
14
- }
15
- get markdownStoreSync() {
16
- return this._markdownStoreSync;
17
- }
18
- get hashStore() {
19
- return this._hashStore;
20
- }
21
- async getMarkdown(markdown, options) {
22
- const key = this.hash(markdown, options);
23
- return this.get(key);
24
- }
25
- getMarkdownSync(markdown, options) {
26
- const key = this.hash(markdown, options);
27
- return this.getSync(key);
28
- }
29
- async setMarkdown(markdown, value, options) {
30
- const key = this.hash(markdown, options);
31
- return this.set(key, value);
32
- }
33
- setMarkdownSync(markdown, value, options) {
34
- const key = this.hash(markdown, options);
35
- this.setSync(key, value);
36
- return true;
37
- }
38
- async get(key) {
39
- return this._markdownStore.get(key);
40
- }
41
- getSync(key) {
42
- return this._markdownStoreSync.get(key);
43
- }
44
- async set(key, value) {
45
- return this._markdownStore.set(key, value);
46
- }
47
- setSync(key, value) {
48
- this._markdownStoreSync.set(key, value);
49
- return true;
50
- }
51
- async clear() {
52
- await this._markdownStore.clear();
53
- this._markdownStoreSync = new Map();
54
- this._hashStore = new Map();
55
- }
56
- setStorageAdapter(adapter) {
57
- this._markdownStore = new Keyv({ store: adapter });
58
- }
59
- hash(markdown, options) {
60
- const key = JSON.stringify({ markdown, options });
61
- let result = this._hashStore.get(key);
62
- if (result) {
63
- return result;
64
- }
65
- result = createHash('sha256').update(key).digest('hex');
66
- this._hashStore.set(key, result);
67
- return result;
68
- }
69
- }
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdHItY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd3JpdHItY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUN2QyxPQUFPLEVBQUMsSUFBSSxFQUF3QixNQUFNLE1BQU0sQ0FBQztBQUdqRCxNQUFNLE9BQU8sVUFBVTtJQUNkLGNBQWMsQ0FBTztJQUNyQixrQkFBa0IsQ0FBc0I7SUFDeEMsVUFBVSxDQUFzQjtJQUV4QztRQUNDLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNqQyxJQUFJLENBQUMsa0JBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVELElBQVcsYUFBYTtRQUN2QixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDNUIsQ0FBQztJQUVELElBQVcsaUJBQWlCO1FBQzNCLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDO0lBQ2hDLENBQUM7SUFFRCxJQUFXLFNBQVM7UUFDbkIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO0lBQ3hCLENBQUM7SUFFTSxLQUFLLENBQUMsV0FBVyxDQUFDLFFBQWdCLEVBQUUsT0FBdUI7UUFDakUsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLENBQUM7SUFFTSxlQUFlLENBQUMsUUFBZ0IsRUFBRSxPQUF1QjtRQUMvRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUN6QyxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUVNLEtBQUssQ0FBQyxXQUFXLENBQUMsUUFBZ0IsRUFBRSxLQUFhLEVBQUUsT0FBdUI7UUFDaEYsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDekMsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRU0sZUFBZSxDQUFDLFFBQWdCLEVBQUUsS0FBYSxFQUFFLE9BQXVCO1FBQzlFLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3pDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ3pCLE9BQU8sSUFBSSxDQUFDO0lBQ2IsQ0FBQztJQUVNLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBVztRQUMzQixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFTSxPQUFPLENBQUMsR0FBVztRQUN6QixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUVNLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBVyxFQUFFLEtBQWE7UUFDMUMsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVNLE9BQU8sQ0FBQyxHQUFXLEVBQUUsS0FBYTtRQUN4QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN4QyxPQUFPLElBQUksQ0FBQztJQUNiLENBQUM7SUFFTSxLQUFLLENBQUMsS0FBSztRQUNqQixNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbEMsSUFBSSxDQUFDLGtCQUFrQixHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7UUFDcEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFTSxpQkFBaUIsQ0FBQyxPQUF5QjtRQUNqRCxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksSUFBSSxDQUFDLEVBQUMsS0FBSyxFQUFFLE9BQU8sRUFBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVNLElBQUksQ0FBQyxRQUFnQixFQUFFLE9BQXVCO1FBQ3BELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBQyxRQUFRLEVBQUUsT0FBTyxFQUFDLENBQUMsQ0FBQztRQUNoRCxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN0QyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1osT0FBTyxNQUFNLENBQUM7UUFDZixDQUFDO1FBRUQsTUFBTSxHQUFHLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUVqQyxPQUFPLE1BQU0sQ0FBQztJQUNmLENBQUM7Q0FDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Y3JlYXRlSGFzaH0gZnJvbSAnbm9kZTpjcnlwdG8nO1xuaW1wb3J0IHtLZXl2LCB0eXBlIEtleXZTdG9yZUFkYXB0ZXJ9IGZyb20gJ2tleXYnO1xuaW1wb3J0IHt0eXBlIFJlbmRlck9wdGlvbnN9IGZyb20gJy4vd3JpdHIuanMnO1xuXG5leHBvcnQgY2xhc3MgV3JpdHJDYWNoZSB7XG5cdHByaXZhdGUgX21hcmtkb3duU3RvcmU6IEtleXY7XG5cdHByaXZhdGUgX21hcmtkb3duU3RvcmVTeW5jOiBNYXA8c3RyaW5nLCBzdHJpbmc+O1xuXHRwcml2YXRlIF9oYXNoU3RvcmU6IE1hcDxzdHJpbmcsIHN0cmluZz47XG5cblx0Y29uc3RydWN0b3IoKSB7XG5cdFx0dGhpcy5fbWFya2Rvd25TdG9yZSA9IG5ldyBLZXl2KCk7XG5cdFx0dGhpcy5fbWFya2Rvd25TdG9yZVN5bmMgPSBuZXcgTWFwKCk7XG5cdFx0dGhpcy5faGFzaFN0b3JlID0gbmV3IE1hcCgpO1xuXHR9XG5cblx0cHVibGljIGdldCBtYXJrZG93blN0b3JlKCk6IEtleXYge1xuXHRcdHJldHVybiB0aGlzLl9tYXJrZG93blN0b3JlO1xuXHR9XG5cblx0cHVibGljIGdldCBtYXJrZG93blN0b3JlU3luYygpOiBNYXA8c3RyaW5nLCBzdHJpbmc+IHtcblx0XHRyZXR1cm4gdGhpcy5fbWFya2Rvd25TdG9yZVN5bmM7XG5cdH1cblxuXHRwdWJsaWMgZ2V0IGhhc2hTdG9yZSgpOiBNYXA8c3RyaW5nLCBzdHJpbmc+IHtcblx0XHRyZXR1cm4gdGhpcy5faGFzaFN0b3JlO1xuXHR9XG5cblx0cHVibGljIGFzeW5jIGdldE1hcmtkb3duKG1hcmtkb3duOiBzdHJpbmcsIG9wdGlvbnM/OiBSZW5kZXJPcHRpb25zKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcblx0XHRjb25zdCBrZXkgPSB0aGlzLmhhc2gobWFya2Rvd24sIG9wdGlvbnMpO1xuXHRcdHJldHVybiB0aGlzLmdldChrZXkpO1xuXHR9XG5cblx0cHVibGljIGdldE1hcmtkb3duU3luYyhtYXJrZG93bjogc3RyaW5nLCBvcHRpb25zPzogUmVuZGVyT3B0aW9ucyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG5cdFx0Y29uc3Qga2V5ID0gdGhpcy5oYXNoKG1hcmtkb3duLCBvcHRpb25zKTtcblx0XHRyZXR1cm4gdGhpcy5nZXRTeW5jKGtleSk7XG5cdH1cblxuXHRwdWJsaWMgYXN5bmMgc2V0TWFya2Rvd24obWFya2Rvd246IHN0cmluZywgdmFsdWU6IHN0cmluZywgb3B0aW9ucz86IFJlbmRlck9wdGlvbnMpOiBQcm9taXNlPGJvb2xlYW4+IHtcblx0XHRjb25zdCBrZXkgPSB0aGlzLmhhc2gobWFya2Rvd24sIG9wdGlvbnMpO1xuXHRcdHJldHVybiB0aGlzLnNldChrZXksIHZhbHVlKTtcblx0fVxuXG5cdHB1YmxpYyBzZXRNYXJrZG93blN5bmMobWFya2Rvd246IHN0cmluZywgdmFsdWU6IHN0cmluZywgb3B0aW9ucz86IFJlbmRlck9wdGlvbnMpOiBib29sZWFuIHtcblx0XHRjb25zdCBrZXkgPSB0aGlzLmhhc2gobWFya2Rvd24sIG9wdGlvbnMpO1xuXHRcdHRoaXMuc2V0U3luYyhrZXksIHZhbHVlKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyBnZXQoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuXHRcdHJldHVybiB0aGlzLl9tYXJrZG93blN0b3JlLmdldChrZXkpO1xuXHR9XG5cblx0cHVibGljIGdldFN5bmMoa2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuXHRcdHJldHVybiB0aGlzLl9tYXJrZG93blN0b3JlU3luYy5nZXQoa2V5KTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyBzZXQoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcblx0XHRyZXR1cm4gdGhpcy5fbWFya2Rvd25TdG9yZS5zZXQoa2V5LCB2YWx1ZSk7XG5cdH1cblxuXHRwdWJsaWMgc2V0U3luYyhrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXHRcdHRoaXMuX21hcmtkb3duU3RvcmVTeW5jLnNldChrZXksIHZhbHVlKTtcblx0XHRyZXR1cm4gdHJ1ZTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyBjbGVhcigpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRhd2FpdCB0aGlzLl9tYXJrZG93blN0b3JlLmNsZWFyKCk7XG5cdFx0dGhpcy5fbWFya2Rvd25TdG9yZVN5bmMgPSBuZXcgTWFwKCk7XG5cdFx0dGhpcy5faGFzaFN0b3JlID0gbmV3IE1hcCgpO1xuXHR9XG5cblx0cHVibGljIHNldFN0b3JhZ2VBZGFwdGVyKGFkYXB0ZXI6IEtleXZTdG9yZUFkYXB0ZXIpOiB2b2lkIHtcblx0XHR0aGlzLl9tYXJrZG93blN0b3JlID0gbmV3IEtleXYoe3N0b3JlOiBhZGFwdGVyfSk7XG5cdH1cblxuXHRwdWJsaWMgaGFzaChtYXJrZG93bjogc3RyaW5nLCBvcHRpb25zPzogUmVuZGVyT3B0aW9ucyk6IHN0cmluZyB7XG5cdFx0Y29uc3Qga2V5ID0gSlNPTi5zdHJpbmdpZnkoe21hcmtkb3duLCBvcHRpb25zfSk7XG5cdFx0bGV0IHJlc3VsdCA9IHRoaXMuX2hhc2hTdG9yZS5nZXQoa2V5KTtcblx0XHRpZiAocmVzdWx0KSB7XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH1cblxuXHRcdHJlc3VsdCA9IGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShrZXkpLmRpZ2VzdCgnaGV4Jyk7XG5cdFx0dGhpcy5faGFzaFN0b3JlLnNldChrZXksIHJlc3VsdCk7XG5cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG59XG4iXX0=