writr 3.2.3 → 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 +116 -52
- package/dist/writr.cjs +321 -0
- package/dist/writr.d.cts +71 -0
- package/dist/writr.d.ts +53 -10
- package/dist/writr.js +278 -110
- package/package.json +42 -25
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
## Markdown Rendering Simplified
|
|
6
|
-
[](https://github.com/jaredwray/writr/actions/workflows/tests.yml)
|
|
7
7
|
[](https://github.com/jaredwray/writr/blob/master/LICENSE)
|
|
8
8
|
[](https://codecov.io/gh/jaredwray/writr)
|
|
9
9
|
[](https://npmjs.com/package/writr)
|
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
- [License - MIT](#license)
|
|
17
17
|
|
|
18
18
|
## Features
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Removes the remark / unified complexity and easy to use.
|
|
20
|
+
* Built in caching 💥 making it render very fast when there isnt a change
|
|
21
|
+
* Frontmatter support built in by default. :tada:
|
|
21
22
|
* Easily Render to `React` or `HTML`.
|
|
22
23
|
* Generates a Table of Contents for your markdown files (remark-toc).
|
|
23
24
|
* Slug generation for your markdown files (rehype-slug).
|
|
@@ -27,67 +28,65 @@
|
|
|
27
28
|
* Github Flavor Markdown (remark-gfm).
|
|
28
29
|
* Emoji Support (remark-emoji).
|
|
29
30
|
* MDX Support (remark-mdx).
|
|
31
|
+
* ESM and Node 20+
|
|
30
32
|
|
|
31
33
|
## Getting Started
|
|
32
34
|
|
|
33
|
-
##
|
|
35
|
+
## Install Writr
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
38
|
> npm install writr
|
|
37
39
|
```
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
Then you can use it like this:
|
|
40
42
|
|
|
41
43
|
```javascript
|
|
42
44
|
import { Writr } from 'writr';
|
|
43
45
|
|
|
44
|
-
const writr = new Writr();
|
|
45
|
-
const markdown = `# Hello World ::-):\n\n This is a test.`;
|
|
46
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
46
47
|
|
|
47
|
-
const html = await writr.render(
|
|
48
|
+
const html = await writr.render(); // <h1>Hello World 🙂</h1><p>This is a test.</p>
|
|
48
49
|
```
|
|
49
50
|
Its just that simple. Want to add some options? No problem.
|
|
50
51
|
|
|
51
52
|
```javascript
|
|
52
53
|
import { Writr } from 'writr';
|
|
53
|
-
const writr = new Writr();
|
|
54
|
-
const markdown = `# Hello World ::-):\n\n This is a test.`;
|
|
54
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
55
55
|
const options = {
|
|
56
56
|
emoji: false
|
|
57
57
|
}
|
|
58
|
-
const html = await writr.render(
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Want to render to a translation? No problem.
|
|
62
|
-
|
|
63
|
-
```javascript
|
|
64
|
-
import { Writr } from 'writr';
|
|
65
|
-
const writr = new Writr({ openai: 'your-api-key'});
|
|
66
|
-
const markdown = `# Hello World ::-):\n\n This is a test.`;
|
|
67
|
-
const langCode = 'es';
|
|
68
|
-
const html = await writr.renderTranslation(markdown, langCode, options); // <h1>Hola Mundo 🙂</h1><p>Esta es una prueba.</p>
|
|
58
|
+
const html = await writr.render(options); // <h1>Hello World ::-):</h1><p>This is a test.</p>
|
|
69
59
|
```
|
|
70
60
|
|
|
71
|
-
|
|
61
|
+
An example passing in the options also via the constructor:
|
|
72
62
|
|
|
73
63
|
```javascript
|
|
74
|
-
import { Writr } from 'writr';
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
79
|
```
|
|
80
80
|
|
|
81
81
|
## API
|
|
82
82
|
|
|
83
|
-
### `new Writr(options?: WritrOptions)`
|
|
83
|
+
### `new Writr(arg?: string | WritrOptions, options?: WritrOptions)`
|
|
84
84
|
|
|
85
|
-
You can access the `WritrOptions` from the instance of Writr. Here is an example of WritrOptions.
|
|
85
|
+
By default the constructor takes in a markdown `string` or `WritrOptions` in the first parameter. You can also send in nothing and set the markdown via `.content` property. If you want to pass in your markdown and options you can easily do this with `new Writr('## Your Markdown Here', { ...options here})`. You can access the `WritrOptions` from the instance of Writr. Here is an example of WritrOptions.
|
|
86
86
|
|
|
87
87
|
```javascript
|
|
88
88
|
import { Writr, WritrOptions } from 'writr';
|
|
89
89
|
const writrOptions = {
|
|
90
|
-
openai: 'your-api-key', // openai api key (default: undefined)
|
|
91
90
|
renderOptions: {
|
|
92
91
|
emoji: true,
|
|
93
92
|
toc: true,
|
|
@@ -95,22 +94,59 @@ const writrOptions = {
|
|
|
95
94
|
highlight: true,
|
|
96
95
|
gfm: true,
|
|
97
96
|
math: true,
|
|
98
|
-
mdx: true
|
|
97
|
+
mdx: true,
|
|
98
|
+
caching: true,
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
101
|
const writr = new Writr(writrOptions);
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
### `.
|
|
104
|
+
### `.content`
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
Setting the markdown content for the instance of Writr. This can be set via the constructor or directly on the instance and can even handle `frontmatter`.
|
|
107
107
|
|
|
108
|
+
```javascript
|
|
109
|
+
|
|
110
|
+
import { Writr } from 'writr';
|
|
111
|
+
const writr = new Writr();
|
|
112
|
+
writr.content = `---
|
|
113
|
+
title: Hello World
|
|
114
|
+
---
|
|
115
|
+
# Hello World ::-):\n\n This is a test.`;
|
|
116
|
+
```
|
|
108
117
|
|
|
109
118
|
### `.options`
|
|
110
119
|
|
|
111
120
|
Accessing the default options for this instance of Writr.
|
|
112
121
|
|
|
113
|
-
### `.
|
|
122
|
+
### `.cache`
|
|
123
|
+
|
|
124
|
+
Accessing the cache for this instance of Writr. By default this is an in memory cache and is enabled by default. You can disable this by setting `caching: false` in the `RenderOptions` of the `WritrOptions` or when calling render passing the `RenderOptions` like here:
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
import { Writr } from 'writr';
|
|
128
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
129
|
+
const options = {
|
|
130
|
+
caching: false
|
|
131
|
+
}
|
|
132
|
+
const html = await writr.render(options); // <h1>Hello World ::-):</h1><p>This is a test.</p>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If you would like to use a specific storage adapter from https://keyv.org you can pass in the adapter like so:
|
|
136
|
+
|
|
137
|
+
```javascript
|
|
138
|
+
import { Writr } from 'writr';
|
|
139
|
+
import Keyv from '@keyv/redis';
|
|
140
|
+
const keyvRedis = new Keyv('redis://user:pass@localhost:6379');
|
|
141
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
142
|
+
writr.cache.setStorageAdapter(keyvRedis);
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `.engine`
|
|
146
|
+
|
|
147
|
+
Accessing the underlying engine for this instance of Writr. This is a `Processor<Root, Root, Root, undefined, undefined>` fro the unified `.use()` function. You can use this to add additional plugins to the engine.
|
|
148
|
+
|
|
149
|
+
### `.render(options?: RenderOptions): Promise<string>`
|
|
114
150
|
|
|
115
151
|
Rendering markdown to HTML. the options are based on RenderOptions. Which you can access from the Writr instance.
|
|
116
152
|
|
|
@@ -120,48 +156,76 @@ import { Writr, RenderOptions } from 'writr';
|
|
|
120
156
|
## `RenderOptions`
|
|
121
157
|
|
|
122
158
|
```js
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
159
|
+
type RenderOptions = {
|
|
160
|
+
emoji?: boolean; // Emoji support (default: true)
|
|
161
|
+
toc?: boolean; // Table of contents generation (default: true)
|
|
162
|
+
slug?: boolean; // Slug generation (default: true)
|
|
163
|
+
highlight?: boolean; // Code highlighting (default: true)
|
|
164
|
+
gfm?: boolean; // Github flavor markdown (default: true)
|
|
165
|
+
math?: boolean; // Math support (default: true)
|
|
166
|
+
mdx?: boolean; // MDX support (default: true)
|
|
167
|
+
caching?: boolean; // Caching (default: true)
|
|
168
|
+
};
|
|
130
169
|
```
|
|
131
170
|
|
|
132
|
-
### `.renderSync(
|
|
171
|
+
### `.renderSync(options?: RenderOptions): string`
|
|
133
172
|
|
|
134
173
|
Rendering markdown to HTML synchronously. the options are based on RenderOptions. Which you can access from the Writr instance. The parameters are the same as the `.render()` function.
|
|
135
174
|
|
|
136
175
|
```javascript
|
|
137
176
|
import { Writr } from 'writr';
|
|
138
|
-
const writr = new Writr();
|
|
139
|
-
const
|
|
140
|
-
const html = writr.renderSync(markdown); // <h1>Hello World 🙂</h1><p>This is a test.</p>
|
|
177
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
178
|
+
const html = writr.renderSync(); // <h1>Hello World 🙂</h1><p>This is a test.</p>
|
|
141
179
|
```
|
|
142
180
|
|
|
143
|
-
### '.renderReact(
|
|
181
|
+
### '.renderReact(options?: RenderOptions, reactOptions?: HTMLReactParserOptions): Promise<React.JSX.Element />'
|
|
144
182
|
|
|
145
183
|
Rendering markdown to React. The options are based on RenderOptions and now HTMLReactParserOptions from `html-react-parser`.
|
|
146
184
|
|
|
147
185
|
```javascript
|
|
148
186
|
import { Writr } from 'writr';
|
|
149
|
-
const writr = new Writr();
|
|
150
|
-
const
|
|
151
|
-
const reactElement = await writr.renderReact(markdown); // Will return a React.JSX.Element
|
|
187
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
188
|
+
const reactElement = await writr.renderReact(); // Will return a React.JSX.Element
|
|
152
189
|
```
|
|
153
190
|
|
|
154
|
-
### '.renderReactSync(
|
|
191
|
+
### '.renderReactSync( options?: RenderOptions, reactOptions?: HTMLReactParserOptions): React.JSX.Element'
|
|
155
192
|
|
|
156
193
|
Rendering markdown to React. The options are based on RenderOptions and now HTMLReactParserOptions from `html-react-parser`.
|
|
157
194
|
|
|
195
|
+
```javascript
|
|
196
|
+
import { Writr } from 'writr';
|
|
197
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
198
|
+
const reactElement = writr.renderReactSync(); // Will return a React.JSX.Element
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `.loadFromFile(filePath: string): Promise<void>`
|
|
202
|
+
|
|
203
|
+
Load your markdown content from a file path.
|
|
204
|
+
|
|
158
205
|
```javascript
|
|
159
206
|
import { Writr } from 'writr';
|
|
160
207
|
const writr = new Writr();
|
|
161
|
-
|
|
162
|
-
const reactElement = writr.renderReactSync(markdown); // Will return a React.JSX.Element
|
|
208
|
+
await writr.loadFromFile('path/to/file.md');
|
|
163
209
|
```
|
|
164
210
|
|
|
211
|
+
### `.loadFromFileSync(filePath: string): void`
|
|
212
|
+
|
|
213
|
+
Load your markdown content from a file path synchronously.
|
|
214
|
+
|
|
215
|
+
### `.saveToFile(filePath: string): Promise<void>`
|
|
216
|
+
|
|
217
|
+
Save your markdown and frontmatter (if included) content to a file path.
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
import { Writr } from 'writr';
|
|
221
|
+
const writr = new Writr(`# Hello World ::-):\n\n This is a test.`);
|
|
222
|
+
await writr.saveToFile('path/to/file.md');
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### `.saveToFileSync(filePath: string): void`
|
|
226
|
+
|
|
227
|
+
Save your markdown and frontmatter (if included) content to a file path synchronously.
|
|
228
|
+
|
|
165
229
|
## Code of Conduct and Contributing
|
|
166
230
|
[Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) guidelines.
|
|
167
231
|
|
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
|
+
});
|
package/dist/writr.d.cts
ADDED
|
@@ -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
|
|
2
|
-
import
|
|
3
|
-
import
|
|
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;
|
|
@@ -13,16 +38,34 @@ type RenderOptions = {
|
|
|
13
38
|
gfm?: boolean;
|
|
14
39
|
math?: boolean;
|
|
15
40
|
mdx?: boolean;
|
|
41
|
+
caching?: boolean;
|
|
16
42
|
};
|
|
17
43
|
declare class Writr {
|
|
18
|
-
engine: Processor<
|
|
44
|
+
engine: unified.Processor<mdast.Root, mdast.Root, hast.Root, hast.Root, string>;
|
|
19
45
|
private readonly _options;
|
|
20
|
-
|
|
46
|
+
private _content;
|
|
47
|
+
private readonly _cache;
|
|
48
|
+
constructor(arguments1?: string | WritrOptions, arguments2?: WritrOptions);
|
|
21
49
|
get options(): WritrOptions;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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;
|
|
26
68
|
private createProcessor;
|
|
27
69
|
}
|
|
28
|
-
|
|
70
|
+
|
|
71
|
+
export { type RenderOptions, Writr, type WritrOptions };
|
package/dist/writr.js
CHANGED
|
@@ -1,118 +1,286 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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;
|
|
47
78
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
65
100
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
catch (error) {
|
|
78
|
-
throw new Error(`Failed to render markdown: ${error.message}`);
|
|
79
|
-
}
|
|
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
|
+
}
|
|
80
112
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
113
|
+
if (arguments2) {
|
|
114
|
+
this._options = { ...this._options, ...arguments2 };
|
|
115
|
+
if (this._options.renderOptions) {
|
|
116
|
+
this.engine = this.createProcessor(this._options.renderOptions);
|
|
117
|
+
}
|
|
84
118
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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 "";
|
|
88
136
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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;
|
|
147
|
+
}
|
|
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;
|
|
109
183
|
}
|
|
110
|
-
|
|
111
|
-
|
|
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;
|
|
112
207
|
}
|
|
113
|
-
|
|
114
|
-
|
|
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}`);
|
|
222
|
+
}
|
|
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;
|
|
253
|
+
}
|
|
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);
|
|
260
|
+
}
|
|
261
|
+
if (options.toc) {
|
|
262
|
+
processor.use(remarkToc, { heading: "toc|table of contents" });
|
|
263
|
+
}
|
|
264
|
+
if (options.emoji) {
|
|
265
|
+
processor.use(remarkEmoji);
|
|
266
|
+
}
|
|
267
|
+
processor.use(remarkRehype);
|
|
268
|
+
if (options.slug) {
|
|
269
|
+
processor.use(rehypeSlug);
|
|
270
|
+
}
|
|
271
|
+
if (options.highlight) {
|
|
272
|
+
processor.use(rehypeHighlight);
|
|
273
|
+
}
|
|
274
|
+
if (options.math) {
|
|
275
|
+
processor.use(remarkMath).use(rehypeKatex);
|
|
276
|
+
}
|
|
277
|
+
if (options.mdx) {
|
|
278
|
+
processor.use(remarkMDX);
|
|
115
279
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd3JpdHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE9BQU8sRUFBWSxNQUFNLFNBQVMsQ0FBQztBQUMzQyxPQUFPLFdBQVcsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxZQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sVUFBVSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLGVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLGVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDbkMsT0FBTyxVQUFVLE1BQU0sYUFBYSxDQUFDO0FBQ3JDLE9BQU8sV0FBVyxNQUFNLGNBQWMsQ0FBQztBQUN2QyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDbkMsT0FBTyxXQUFXLE1BQU0sY0FBYyxDQUFDO0FBQ3ZDLE9BQU8sU0FBUyxNQUFNLFlBQVksQ0FBQztBQUVuQyxPQUFPLEtBQW9DLE1BQU0sbUJBQW1CLENBQUM7QUFpQnJFLE1BQU0sS0FBSztJQUNILE1BQU0sR0FBRyxPQUFPLEVBQUU7U0FDdkIsR0FBRyxDQUFDLFdBQVcsQ0FBQztTQUNoQixHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsK0JBQStCO1NBQzlDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyx3QkFBd0I7U0FDdkMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLG9CQUFvQjtTQUNyQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsMkJBQTJCO1NBQzdDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxnQ0FBZ0M7U0FDaEQsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLG1CQUFtQjtTQUNuQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsbUJBQW1CO1NBQ3BDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyw0QkFBNEI7U0FDakQsR0FB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LENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFCLENBQUM7UUFFRCxTQUFTLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBRS9CLE9BQU8sU0FBUyxDQUFDO0lBQ2xCLENBQUM7Q0FDRDtBQUVELE9BQU8sRUFBQyxLQUFLLEVBQXdDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge3VuaWZpZWQsIFByb2Nlc3Nvcn0gZnJvbSAndW5pZmllZCc7XG5pbXBvcnQgcmVtYXJrUGFyc2UgZnJvbSAncmVtYXJrLXBhcnNlJztcbmltcG9ydCByZW1hcmtSZWh5cGUgZnJvbSAncmVtYXJrLXJlaHlwZSc7XG5pbXBvcnQgcmVoeXBlU2x1ZyBmcm9tICdyZWh5cGUtc2x1Zyc7XG5pbXBvcnQgcmVoeXBlSGlnaGxpZ2h0IGZyb20gJ3JlaHlwZS1oaWdobGlnaHQnO1xuaW1wb3J0IHJlaHlwZVN0cmluZ2lmeSBmcm9tICdyZWh5cGUtc3RyaW5naWZ5JztcbmltcG9ydCByZW1hcmtUb2MgZnJvbSAncmVtYXJrLXRvYyc7XG5pbXBvcnQgcmVtYXJrTWF0aCBmcm9tICdyZW1hcmstbWF0aCc7XG5pbXBvcnQgcmVoeXBlS2F0ZXggZnJvbSAncmVoeXBlLWthdGV4JztcbmltcG9ydCByZW1hcmtHZm0gZnJvbSAncmVtYXJrLWdmbSc7XG5pbXBvcnQgcmVtYXJrRW1vamkgZnJvbSAncmVtYXJrLWVtb2ppJztcbmltcG9ydCByZW1hcmtNRFggZnJvbSAncmVtYXJrLW1keCc7XG5pbXBvcnQgdHlwZSBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQgcGFyc2UsIHt0eXBlIEhUTUxSZWFjdFBhcnNlck9wdGlvbnN9IGZyb20gJ2h0bWwtcmVhY3QtcGFyc2VyJztcblxudHlwZSBXcml0ck9wdGlvbnMgPSB7XG5cdG9wZW5haT86IHN0cmluZzsgLy8gT3BlbmFpIGFwaSBrZXkgKGRlZmF1bHQ6IHVuZGVmaW5lZClcblx0cmVuZGVyT3B0aW9ucz86IFJlbmRlck9wdGlvbnM7IC8vIERlZmF1bHQgcmVuZGVyIG9wdGlvbnMgKGRlZmF1bHQ6IHVuZGVmaW5lZClcbn07XG5cbnR5cGUgUmVuZGVyT3B0aW9ucyA9IHtcblx0ZW1vamk/OiBib29sZWFuOyAvLyBFbW9qaSBzdXBwb3J0IChkZWZhdWx0OiB0cnVlKVxuXHR0b2M/OiBib29sZWFuOyAvLyBUYWJsZSBvZiBjb250ZW50cyBnZW5lcmF0aW9uIChkZWZhdWx0OiB0cnVlKVxuXHRzbHVnPzogYm9vbGVhbjsgLy8gU2x1ZyBnZW5lcmF0aW9uIChkZWZhdWx0OiB0cnVlKVxuXHRoaWdobGlnaHQ/OiBib29sZWFuOyAvLyBDb2RlIGhpZ2hsaWdodGluZyAoZGVmYXVsdDogdHJ1ZSlcblx0Z2ZtPzogYm9vbGVhbjsgLy8gR2l0aHViIGZsYXZvciBtYXJrZG93biAoZGVmYXVsdDogdHJ1ZSlcblx0bWF0aD86IGJvb2xlYW47IC8vIE1hdGggc3VwcG9ydCAoZGVmYXVsdDogdHJ1ZSlcblx0bWR4PzogYm9vbGVhbjsgLy8gTURYIHN1cHBvcnQgKGRlZmF1bHQ6IHRydWUpXG59O1xuXG5jbGFzcyBXcml0ciB7XG5cdHB1YmxpYyBlbmdpbmUgPSB1bmlmaWVkKClcblx0XHQudXNlKHJlbWFya1BhcnNlKVxuXHRcdC51c2UocmVtYXJrR2ZtKSAvLyBVc2UgR2l0SHViIEZsYXZvcmVkIE1hcmtkb3duXG5cdFx0LnVzZShyZW1hcmtUb2MpIC8vIEFkZCB0YWJsZSBvZiBjb250ZW50c1xuXHRcdC51c2UocmVtYXJrRW1vamkpIC8vIEFkZCBlbW9qaSBzdXBwb3J0XG5cdFx0LnVzZShyZW1hcmtSZWh5cGUpIC8vIENvbnZlcnQgbWFya2Rvd24gdG8gSFRNTFxuXHRcdC51c2UocmVoeXBlU2x1ZykgLy8gQWRkIHNsdWdzIHRvIGhlYWRpbmdzIGluIEhUTUxcblx0XHQudXNlKHJlbWFya01hdGgpIC8vIEFkZCBtYXRoIHN1cHBvcnRcblx0XHQudXNlKHJlaHlwZUthdGV4KSAvLyBBZGQgbWF0aCBzdXBwb3J0XG5cdFx0LnVzZShyZWh5cGVIaWdobGlnaHQpIC8vIEFwcGx5IHN5bnRheCBoaWdobGlnaHRpbmdcblx0XHQudXNlKHJlbWFya01EWCkgLy8gQWRkIE1EWCBzdXBwb3J0XG5cdFx0LnVzZShyZWh5cGVTdHJpbmdpZnkpOyAvLyBTdHJpbmdpZnkgSFRNTFxuXG5cdHByaXZhdGUgcmVhZG9ubHkgX29wdGlvbnM6IFdyaXRyT3B0aW9ucyA9IHtcblx0XHRvcGVuYWk6IHVuZGVmaW5lZCxcblx0XHRyZW5kZXJPcHRpb25zOiB7XG5cdFx0XHRlbW9qaTogdHJ1ZSxcblx0XHRcdHRvYzogdHJ1ZSxcblx0XHRcdHNsdWc6IHRydWUsXG5cdFx0XHRoaWdobGlnaHQ6IHRydWUsXG5cdFx0XHRnZm06IHRydWUsXG5cdFx0XHRtYXRoOiB0cnVlLFxuXHRcdFx0bWR4OiB0cnVlLFxuXHRcdH0sXG5cdH07XG5cblx0Y29uc3RydWN0b3Iob3B0aW9ucz86IFdyaXRyT3B0aW9ucykge1xuXHRcdGlmIChvcHRpb25zKSB7XG5cdFx0XHR0aGlzLl9vcHRpb25zID0gey4uLnRoaXMuX29wdGlvbnMsIC4uLm9wdGlvbnN9O1xuXHRcdFx0aWYgKHRoaXMuX29wdGlvbnMucmVuZGVyT3B0aW9ucykge1xuXHRcdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50XG5cdFx0XHRcdHRoaXMuZW5naW5lID0gdGhpcy5jcmVhdGVQcm9jZXNzb3IodGhpcy5fb3B0aW9ucy5yZW5kZXJPcHRpb25zKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgZ2V0IG9wdGlvbnMoKTogV3JpdHJPcHRpb25zIHtcblx0XHRyZXR1cm4gdGhpcy5fb3B0aW9ucztcblx0fVxuXG5cdGFzeW5jIHJlbmRlcihtYXJrZG93bjogc3RyaW5nLCBvcHRpb25zPzogUmVuZGVyT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7XG5cdFx0dHJ5IHtcblx0XHRcdGxldCB7ZW5naW5lfSA9IHRoaXM7XG5cdFx0XHRpZiAob3B0aW9ucykge1xuXHRcdFx0XHRvcHRpb25zID0gey4uLnRoaXMuX29wdGlvbnMucmVuZGVyT3B0aW9ucywgLi4ub3B0aW9uc307XG5cdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnRcblx0XHRcdFx0ZW5naW5lID0gdGhpcy5jcmVhdGVQcm9jZXNzb3Iob3B0aW9ucyk7XG5cdFx0XHR9XG5cblx0XHRcdGNvbnN0IGZpbGUgPSBhd2FpdCBlbmdpbmUucHJvY2VzcyhtYXJrZG93bik7XG5cdFx0XHRyZXR1cm4gU3RyaW5nKGZpbGUpO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byByZW5kZXIgbWFya2Rvd246ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuXHRcdH1cblx0fVxuXG5cdHJlbmRlclN5bmMobWFya2Rvd246IHN0cmluZywgb3B0aW9ucz86IFJlbmRlck9wdGlvbnMpOiBzdHJpbmcge1xuXHRcdHRyeSB7XG5cdFx0XHRsZXQge2VuZ2luZX0gPSB0aGlzO1xuXHRcdFx0aWYgKG9wdGlvbnMpIHtcblx0XHRcdFx0b3B0aW9ucyA9IHsuLi50aGlzLl9vcHRpb25zLnJlbmRlck9wdGlvbnMsIC4uLm9wdGlvbnN9O1xuXHRcdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50XG5cdFx0XHRcdGVuZ2luZSA9IHRoaXMuY3JlYXRlUHJvY2Vzc29yKG9wdGlvbnMpO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBmaWxlID0gZW5naW5lLnByb2Nlc3NTeW5jKG1hcmtkb3duKTtcblx0XHRcdHJldHVybiBTdHJpbmcoZmlsZSk7XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIHJlbmRlciBtYXJrZG93bjogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgcmVuZGVyUmVhY3QobWFya2Rvd246IHN0cmluZywgb3B0aW9ucz86IFJlbmRlck9wdGlvbnMsIHJlYWN0UGFyc2VPcHRpb25zPzogSFRNTFJlYWN0UGFyc2VyT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nIHwgUmVhY3QuSlNYLkVsZW1lbnQgfCBSZWFjdC5KU1guRWxlbWVudFtdPiB7XG5cdFx0Y29uc3QgaHRtbCA9IGF3YWl0IHRoaXMucmVuZGVyKG1hcmtkb3duLCBvcHRpb25zKTtcblxuXHRcdHJldHVybiBwYXJzZShodG1sLCByZWFjdFBhcnNlT3B0aW9ucyk7XG5cdH1cblxuXHRyZW5kZXJSZWFjdFN5bmMobWFya2Rvd246IHN0cmluZywgb3B0aW9ucz86IFJlbmRlck9wdGlvbnMsIHJlYWN0UGFyc2VPcHRpb25zPzogSFRNTFJlYWN0UGFyc2VyT3B0aW9ucyk6IHN0cmluZyB8IFJlYWN0LkpTWC5FbGVtZW50IHwgUmVhY3QuSlNYLkVsZW1lbnRbXSB7XG5cdFx0Y29uc3QgaHRtbCA9IHRoaXMucmVuZGVyU3luYyhtYXJrZG93biwgb3B0aW9ucyk7XG5cdFx0cmV0dXJuIHBhcnNlKGh0bWwsIHJlYWN0UGFyc2VPcHRpb25zKTtcblx0fVxuXG5cdHByaXZhdGUgY3JlYXRlUHJvY2Vzc29yKG9wdGlvbnM6IFJlbmRlck9wdGlvbnMpOiBhbnkge1xuXHRcdGNvbnN0IHByb2Nlc3NvciA9IHVuaWZpZWQoKS51c2UocmVtYXJrUGFyc2UpO1xuXG5cdFx0aWYgKG9wdGlvbnMuZ2ZtKSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlbWFya0dmbSk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMudG9jKSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlbWFya1RvYywge2hlYWRpbmc6ICd0b2N8dGFibGUgb2YgY29udGVudHMnfSk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuZW1vamkpIHtcblx0XHRcdHByb2Nlc3Nvci51c2UocmVtYXJrRW1vamkpO1xuXHRcdH1cblxuXHRcdHByb2Nlc3Nvci51c2UocmVtYXJrUmVoeXBlKTtcblxuXHRcdGlmIChvcHRpb25zLnNsdWcpIHtcblx0XHRcdHByb2Nlc3Nvci51c2UocmVoeXBlU2x1Zyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuaGlnaGxpZ2h0KSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlaHlwZUhpZ2hsaWdodCk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMubWF0aCkge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZW1hcmtNYXRoKS51c2UocmVoeXBlS2F0ZXgpO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLm1keCkge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZW1hcmtNRFgpO1xuXHRcdH1cblxuXHRcdHByb2Nlc3Nvci51c2UocmVoeXBlU3RyaW5naWZ5KTtcblxuXHRcdHJldHVybiBwcm9jZXNzb3I7XG5cdH1cbn1cblxuZXhwb3J0IHtXcml0ciwgdHlwZSBXcml0ck9wdGlvbnMsIHR5cGUgUmVuZGVyT3B0aW9uc307XG5cbiJdfQ==
|
|
280
|
+
processor.use(rehypeStringify);
|
|
281
|
+
return processor;
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
export {
|
|
285
|
+
Writr
|
|
286
|
+
};
|
package/package.json
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "writr",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Markdown Rendering Simplified",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"
|
|
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": {
|
|
11
|
-
"node": ">=
|
|
18
|
+
"node": ">=20"
|
|
12
19
|
},
|
|
13
20
|
"license": "MIT",
|
|
14
21
|
"keywords": [
|
|
@@ -40,40 +47,48 @@
|
|
|
40
47
|
"markdown-to-react"
|
|
41
48
|
],
|
|
42
49
|
"scripts": {
|
|
43
|
-
"clean": "rimraf ./dist ./coverage ./node_modules ./package-lock.json ./yarn.lock ./site/README.md ./site
|
|
44
|
-
"build": "rimraf ./dist &&
|
|
45
|
-
"test": "xo --fix && vitest run --coverage",
|
|
50
|
+
"clean": "rimraf ./dist ./coverage ./node_modules ./package-lock.json ./yarn.lock ./site/README.md ./site/dist",
|
|
51
|
+
"build": "rimraf ./dist && tsup src/writr.ts --format cjs,esm --dts --clean",
|
|
46
52
|
"prepare": "npm run build",
|
|
47
|
-
"
|
|
48
|
-
"website:
|
|
53
|
+
"test": "xo --fix && vitest run --coverage",
|
|
54
|
+
"website:build": "rimraf ./site/README.md ./site/dist && npx docula build -s ./site -o ./site/dist",
|
|
55
|
+
"website:serve": "rimraf ./site/README.md ./site/dist && npx docula serve -s ./site -o ./site/dist"
|
|
49
56
|
},
|
|
50
57
|
"dependencies": {
|
|
51
|
-
"
|
|
58
|
+
"cacheable": "^1.7.1",
|
|
59
|
+
"crypto": "^1.0.1",
|
|
60
|
+
"fs": "^0.0.1-security",
|
|
61
|
+
"html-react-parser": "^5.1.16",
|
|
62
|
+
"js-yaml": "^4.1.0",
|
|
63
|
+
"keyv": "^5.0.3",
|
|
52
64
|
"react": "^18.3.1",
|
|
53
65
|
"rehype-highlight": "^7.0.0",
|
|
54
|
-
"rehype-katex": "^7.0.
|
|
66
|
+
"rehype-katex": "^7.0.1",
|
|
55
67
|
"rehype-slug": "^6.0.0",
|
|
56
|
-
"rehype-stringify": "^10.0.
|
|
57
|
-
"remark-emoji": "^
|
|
68
|
+
"rehype-stringify": "^10.0.1",
|
|
69
|
+
"remark-emoji": "^5.0.1",
|
|
58
70
|
"remark-gfm": "^4.0.0",
|
|
59
71
|
"remark-math": "^6.0.0",
|
|
60
72
|
"remark-mdx": "^3.0.1",
|
|
61
73
|
"remark-parse": "^11.0.0",
|
|
62
|
-
"remark-rehype": "^11.1.
|
|
74
|
+
"remark-rehype": "^11.1.1",
|
|
63
75
|
"remark-toc": "^9.0.0",
|
|
64
|
-
"
|
|
65
|
-
"unified": "^11.0.4"
|
|
76
|
+
"unified": "^11.0.5"
|
|
66
77
|
},
|
|
67
78
|
"devDependencies": {
|
|
68
|
-
"@
|
|
69
|
-
"@types/
|
|
70
|
-
"@
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
79
|
+
"@keyv/sqlite": "^4.0.1",
|
|
80
|
+
"@types/js-yaml": "^4.0.9",
|
|
81
|
+
"@types/node": "^22.7.4",
|
|
82
|
+
"@types/react": "^18.3.10",
|
|
83
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
84
|
+
"docula": "^0.9.1",
|
|
85
|
+
"rimraf": "^6.0.1",
|
|
86
|
+
"ts-node": "^10.9.2",
|
|
87
|
+
"tsup": "^8.3.0",
|
|
88
|
+
"typescript": "^5.6.2",
|
|
89
|
+
"vitest": "^2.1.1",
|
|
90
|
+
"webpack": "^5.95.0",
|
|
91
|
+
"xo": "^0.59.3"
|
|
77
92
|
},
|
|
78
93
|
"xo": {
|
|
79
94
|
"ignores": [
|
|
@@ -81,6 +96,8 @@
|
|
|
81
96
|
]
|
|
82
97
|
},
|
|
83
98
|
"files": [
|
|
84
|
-
"dist"
|
|
99
|
+
"dist",
|
|
100
|
+
"README.md",
|
|
101
|
+
"LICENSE"
|
|
85
102
|
]
|
|
86
103
|
}
|