writr 2.0.2 โ†’ 3.0.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  ---
4
4
 
5
- ## Beautiful Website for Your Projects
5
+ ## Markdown Rendering Simplified
6
6
  [![Build](https://github.com/jaredwray/writr/actions/workflows/tests.yml/badge.svg)](https://github.com/jaredwray/writr/actions/workflows/tests.yml)
7
7
  [![GitHub license](https://img.shields.io/github/license/jaredwray/writr)](https://github.com/jaredwray/writr/blob/master/LICENSE)
8
8
  [![codecov](https://codecov.io/gh/jaredwray/writr/branch/master/graph/badge.svg?token=1YdMesM07X)](https://codecov.io/gh/jaredwray/writr)
@@ -12,113 +12,129 @@
12
12
  ## Table of Contents
13
13
  - [Features](#features)
14
14
  - [Getting Started](#getting-started)
15
- - [Using Your own Template](#using-your-own-template)
16
- - [Building Multiple Pages](#building-multiple-pages)
17
- - [Helper Functions for Markdown](#helper-functions-for-markdown)
18
- - [Code of Conduct and Contributing](#code-of-conduct-and-contributing)
19
- - [What Happened to it Generating a Blog](#what-happened-to-it-generating-a-blog)
20
15
  - [License - MIT](#license)
21
16
 
22
17
  ## Features
23
- * No configuration requrired. Just setup the folder structure with a logo, favicon, and css file.
24
- * Builds a static website that can be hosted anywhere.
25
- * For more complex projects easily add a `writr.config.js` or `writr.config.ts` file to customize the build process. With PRE and POST methods.
26
- * Support for single page with readme or multiple markdown pages in a docs folder.
27
- * Will generate a sitemap.xml and robots.txt for your site.
28
- * Uses Github release notes to generate a changelog / releases page.
29
- * Uses Github to show contributors and link to their profiles.
30
- * Simple search is provided by default out of the box.
18
+ * Takes the complexity of Remark and makes it easy to use.
19
+ * Up and Rendering in seconds with a simple API.
20
+ * Generates a Table of Contents for your markdown files (remark-toc).
21
+ * Slug generation for your markdown files (rehype-slug).
22
+ * Code Highlighting (rehype-highlight).
23
+ * Markdown to HTML (rehype-stringify).
24
+ * Github Flavor Markdown (remark-gfm).
25
+ * Emoji Support (remark-emoji).
26
+ * Generation of Keywords, Descriptions, and Translations using AI.
31
27
 
32
28
  ## Getting Started
33
29
 
34
30
  ## 1. Install Writr
35
31
 
36
- > npx writr init
32
+ ```bash
33
+ > npm install writr
34
+ ```
35
+
36
+ ## 2. Render from Markdown
37
+
38
+ ```javascript
39
+ import { Writr } from 'writr';
37
40
 
38
- This will create a folder called site with the following structure:
41
+ const writr = new Writr();
42
+ const markdown = `# Hello World ::-):\n\n This is a test.`;
39
43
 
44
+ const html = await writr.render(markdown); // <h1>Hello World ๐Ÿ™‚</h1><p>This is a test.</p>
40
45
  ```
41
- site
42
- โ”œโ”€โ”€โ”€site.css
43
- โ”œโ”€โ”€โ”€logo.png
44
- โ”œโ”€โ”€โ”€favicon.ico
45
- โ”œโ”€โ”€โ”€README.md
46
- โ”œโ”€โ”€โ”€writr.config.js
46
+ Its just that simple. Want to add some options? No problem.
47
+
48
+ ```javascript
49
+ import { Writr } from 'writr';
50
+ const writr = new Writr();
51
+ const markdown = `# Hello World ::-):\n\n This is a test.`;
52
+ const options = {
53
+ emoji: false
54
+ }
55
+ const html = await writr.render(markdown, options); // <h1>Hello World ::-):</h1><p>This is a test.</p>
47
56
  ```
48
- Note: for typescript do 'writr init --typescript'
49
57
 
50
- ## 2. Add your content
58
+ Want to render to a translation? No problem.
51
59
 
52
- Simply replace the logo, favicon, and css file with your own. The readme is your root project readme and you just need to at build time move it over to the site folder. If you have it at the root of the project and this is a folder inside just delete the README.md file in the site folder and writr will copy it over for you automatically.
60
+ ```javascript
61
+ import { Writr } from 'writr';
62
+ const writr = new Writr({ openai: 'your-api-key'});
63
+ const markdown = `# Hello World ::-):\n\n This is a test.`;
64
+ const langCode = 'es';
65
+ const html = await writr.renderTranslation(markdown, langCode, options); // <h1>Hola Mundo ๐Ÿ™‚</h1><p>Esta es una prueba.</p>
66
+ ```
53
67
 
54
- ## 3. Build your site
68
+ How about generating keywords and descriptions for your front matter?
55
69
 
56
- > npx writr
70
+ ```javascript
71
+ import { Writr } from 'writr';
72
+ const writr = new Writr({ openai: 'your-api-key'});
73
+ const markdown = `# Hello World ::-):\n\n This is a test.`;
74
+ const keywords = await writr.keywords(markdown); // ['Hello World', 'Test']
75
+ const description = await writr.description(markdown); // 'Hello World Test'
76
+ ```
57
77
 
58
- This will build your site and place it in the `dist` folder. You can then host it anywhere you like.
78
+ ## API
59
79
 
60
- ## Using Your own Template
80
+ ### `new Writr(options?: WritrOptions)`
61
81
 
62
- If you want to use your own template you can do so by adding a `writr.config.ts` file to the root of your project. This file will be used to configure the build process.
82
+ ```js
83
+ interface WritrOptions {
84
+ openai?: string; // openai api key (default: undefined)
85
+ emoji?: boolean; // emoji support (default: true)
86
+ toc?: boolean; // table of contents generation (default: true)
87
+ slug?: boolean; // slug generation (default: true)
88
+ highlight?: boolean; // code highlighting (default: true)
89
+ gfm?: boolean; // github flavor markdown (default: true)
90
+ }
91
+ ```
63
92
 
64
- or at the command line:
93
+ You can access the `WritrOptions` from the instance of Writr.
65
94
 
66
- > npx writr --template path/to/template
95
+ ```javascript
96
+ import { Writr, WritrOptions } from 'writr';
97
+ ```
67
98
 
68
- ## Building Multiple Pages
99
+ ### `.options`
69
100
 
70
- If you want to build multiple pages you can easily do that by adding in a `docs` folder to the root of the site folder. Inside of that folder you can add as many pages as you like. Each page will be a markdown file and it will generate a table of contents for you. Here is an example of what it looks like:
101
+ Accessing the default options for this instance of Writr.
71
102
 
72
- ```
73
- site
74
- โ”œโ”€โ”€โ”€site.css
75
- โ”œโ”€โ”€โ”€logo.png
76
- โ”œโ”€โ”€โ”€favicon.ico
77
- โ”œโ”€โ”€โ”€writr.config.ts
78
- โ”œโ”€โ”€โ”€docs
79
- โ”‚ โ”œโ”€โ”€โ”€getting-started.md
80
- โ”‚ โ”œโ”€โ”€โ”€contributing.md
81
- โ”‚ โ”œโ”€โ”€โ”€license.md
82
- โ”‚ โ”œโ”€โ”€โ”€code-of-conduct.md
83
- ```
103
+ ### `.render(markdown: string, options?: RenderOptions): Promise<string>`
84
104
 
85
- The `readme.md` file will be the root page and the rest will be added to the table of contents. If you want to control the title or order of the pages you can do so by setting the `title` and `order` properties in the front matter of the markdown file. Here is an example:
105
+ Rendering markdown to HTML. the options are based on RenderOptions. Which you can access from the Writr instance.
86
106
 
87
- ```md
88
- ---
89
- title: Getting Started
90
- order: 2
91
- ---
107
+ ```javascript
108
+ import { Writr, RenderOptions } from 'writr';
109
+
110
+ ## `RenderOptions`
111
+
112
+ ```js
113
+ interface RenderOptions {
114
+ emoji?: boolean; // emoji support
115
+ toc?: boolean; // table of contents generation
116
+ slug?: boolean; // slug generation
117
+ highlight?: boolean; // code highlighting
118
+ gfm?: boolean; // github flavor markdown
119
+ }
92
120
  ```
93
121
 
94
- ## Helper Functions for Markdown
122
+ ### `.renderTranslation(markdown: string, langCode: string, options?: RenderOptions): Promise<string>`
95
123
 
96
- Writr comes with some helper functions that you can use in your markdown files.
97
- * `writrHelpers.getFrontMatter(fileName)` - Gets the front matter of a markdown file.
98
- * `writrHelpers.setFrontMatter(fileName, frontMatter)` - Sets the front matter of a markdown file.
99
- * `writrHelpers.createDoc(source, destination, frontMatter?, contentFn[]?)` - Creates a markdown file with the specified front matter and content. The contentFn is a function that is executed on the original content of the file. This is useful if you want to remove content from the original file.
124
+ Rendering markdown to HTML. the options are based on RenderOptions. Which you can access from the Writr instance.
100
125
 
101
- ### Remove html content
102
126
 
103
- In some cases your markdown file will have html content in it such as the logo of your project or a badge. You can use the `wrtirHelpers.removeHtmlContent()` helper function to remove that content from the page. Here is an example:
127
+ ### `.keywords(markdown: string): Promise<string[]>`
104
128
 
105
- ### Get and Set the Front Matter of a Markdown File
129
+ AI Generation of Keywords that can be used for SEO on your HTML.
106
130
 
107
- You can use the `writrHelpers.getFrontMatter()` and `writrHelpers.setFrontMatter()` helper functions to get and set the front matter of a markdown file. Here is an example:
131
+ ### `.description(markdown: string): Promise<string>`
108
132
 
109
- ```js
110
- const frontMatter = writrHelpers.getFrontMatter('../readme.md');
111
- frontMatter.title = 'My Title';
112
- writrHelpers.setFrontMatter('../readme.md', frontMatter);
113
- ```
133
+ AI Generation of a Description that can be used for SEO on your HTML.
114
134
 
115
135
  ## Code of Conduct and Contributing
116
136
  [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing](CONTRIBUTING.md) guidelines.
117
137
 
118
- ## What Happened to it Generating a Blog
119
-
120
- The original version of writr was a blog generator. Since there are plenty of blog generators out there we made the decision to make it a static site generator for open source projects. This is something that we constantly need and we hope you find it useful as well.
121
-
122
138
  ## License
123
139
 
124
140
  MIT ยฉ [Jared Wray](https://jaredwray.com)
package/dist/writr.d.ts CHANGED
@@ -1,23 +1,25 @@
1
- /// <reference types="node" />
2
- /// <reference types="node" />
3
- import type http from 'node:http';
4
- import { WritrOptions } from './options.js';
5
- export default class Writr {
6
- private _options;
7
- private readonly _console;
8
- private _configFileModule;
9
- private _server;
1
+ import { Processor } from 'unified';
2
+ type WritrOptions = {
3
+ openai?: string;
4
+ emoji?: boolean;
5
+ toc?: boolean;
6
+ slug?: boolean;
7
+ highlight?: boolean;
8
+ gfm?: boolean;
9
+ };
10
+ type RenderOptions = {
11
+ emoji?: boolean;
12
+ toc?: boolean;
13
+ slug?: boolean;
14
+ highlight?: boolean;
15
+ gfm?: boolean;
16
+ };
17
+ declare class Writr {
18
+ engine: Processor<import("mdast").Root, import("mdast").Root, import("hast").Root, import("hast").Root, string>;
19
+ private readonly _options;
10
20
  constructor(options?: WritrOptions);
11
21
  get options(): WritrOptions;
12
- set options(value: WritrOptions);
13
- get server(): http.Server | undefined;
14
- get configFileModule(): any;
15
- checkForUpdates(): void;
16
- execute(process: NodeJS.Process): Promise<void>;
17
- isSinglePageWebsite(sitePath: string): boolean;
18
- generateInit(sitePath: string): void;
19
- getVersion(): string;
20
- loadConfigFile(sitePath: string): Promise<void>;
21
- serve(options: WritrOptions): Promise<void>;
22
+ render(markdown: string, options?: RenderOptions): Promise<string>;
23
+ private createProcessor;
22
24
  }
23
- export { WritrHelpers } from './helpers.js';
25
+ export { Writr, type WritrOptions, type RenderOptions };
package/dist/writr.js CHANGED
@@ -1,153 +1,76 @@
1
- import path from 'node:path';
2
- import process from 'node:process';
3
- import fs from 'fs-extra';
4
- import updateNotifier from 'update-notifier';
5
- import express from 'express';
6
- import { WritrOptions } from './options.js';
7
- import { WritrConsole } from './console.js';
8
- import { WritrBuilder } from './builder.js';
9
- import { MarkdownHelper } from './helpers/markdown.js';
10
- export default class Writr {
11
- _options = new WritrOptions();
12
- _console = new WritrConsole();
13
- _configFileModule = {};
14
- _server;
1
+ import { unified } from 'unified';
2
+ import remarkParse from 'remark-parse';
3
+ import remarkRehype from 'remark-rehype';
4
+ import rehypeSlug from 'rehype-slug';
5
+ import rehypeHighlight from 'rehype-highlight';
6
+ import rehypeStringify from 'rehype-stringify';
7
+ import remarkToc from 'remark-toc';
8
+ import remarkGfm from 'remark-gfm';
9
+ import remarkEmoji from 'remark-emoji';
10
+ class Writr {
11
+ engine = unified()
12
+ .use(remarkParse)
13
+ .use(remarkGfm) // Use GitHub Flavored Markdown
14
+ .use(remarkToc) // Add table of contents
15
+ .use(remarkEmoji) // Add emoji support
16
+ .use(remarkRehype) // Convert markdown to HTML
17
+ .use(rehypeSlug) // Add slugs to headings in HTML
18
+ .use(rehypeHighlight) // Apply syntax highlighting
19
+ .use(rehypeStringify); // Stringify HTML
20
+ _options = {
21
+ openai: undefined,
22
+ emoji: true,
23
+ toc: true,
24
+ slug: true,
25
+ highlight: true,
26
+ gfm: true,
27
+ };
15
28
  constructor(options) {
16
29
  if (options) {
17
- this._options = options;
30
+ this._options = { ...this._options, ...options };
31
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
32
+ this.engine = this.createProcessor(this._options);
18
33
  }
19
34
  }
20
35
  get options() {
21
36
  return this._options;
22
37
  }
23
- set options(value) {
24
- this._options = value;
25
- }
26
- get server() {
27
- return this._server;
28
- }
29
- get configFileModule() {
30
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
31
- return this._configFileModule;
32
- }
33
- checkForUpdates() {
34
- const packageJsonPath = path.join(process.cwd(), 'package.json');
35
- if (fs.existsSync(packageJsonPath)) {
36
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
37
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
38
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
39
- updateNotifier({ pkg: packageJson }).notify();
40
- }
41
- }
42
- async execute(process) {
43
- // Check for updates
44
- this.checkForUpdates();
45
- const consoleProcess = this._console.parseProcessArgv(process.argv);
46
- // Update options
47
- if (consoleProcess.args.sitePath) {
48
- this.options.sitePath = consoleProcess.args.sitePath;
49
- }
50
- // Load the Config File
51
- await this.loadConfigFile(this.options.sitePath);
52
- // Parse the config file
53
- if (this._configFileModule.options) {
54
- this.options.parseOptions(this._configFileModule.options);
55
- }
56
- // Run the onPrepare function
57
- if (this._configFileModule.onPrepare) {
58
- try {
59
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
60
- await this._configFileModule.onPrepare(this.options);
61
- }
62
- catch (error) {
63
- this._console.error(error.message);
38
+ async render(markdown, options) {
39
+ try {
40
+ let { engine } = this;
41
+ if (options) {
42
+ options = { ...this._options, ...options };
43
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
44
+ engine = this.createProcessor(options);
64
45
  }
46
+ const file = await engine.process(markdown);
47
+ return String(file);
65
48
  }
66
- if (consoleProcess.args.output) {
67
- this.options.outputPath = consoleProcess.args.output;
68
- }
69
- const engineConfig = {
70
- nodes: {
71
- fence: MarkdownHelper.fence(),
72
- },
73
- };
74
- switch (consoleProcess.command) {
75
- case 'init': {
76
- const isTypescript = fs.existsSync('./tsconfig.json') ?? false;
77
- this.generateInit(this.options.sitePath);
78
- break;
79
- }
80
- case 'help': {
81
- this._console.printHelp();
82
- break;
83
- }
84
- case 'version': {
85
- this._console.log(this.getVersion());
86
- break;
87
- }
88
- case 'serve': {
89
- const builder = new WritrBuilder(this.options, engineConfig);
90
- await builder.build();
91
- await this.serve(this.options);
92
- break;
93
- }
94
- default: {
95
- const builder = new WritrBuilder(this.options, engineConfig);
96
- await builder.build();
97
- break;
98
- }
49
+ catch (error) {
50
+ throw new Error(`Failed to render markdown: ${error.message}`);
99
51
  }
100
52
  }
101
- isSinglePageWebsite(sitePath) {
102
- const docsPath = `${sitePath}/docs`;
103
- if (!fs.existsSync(docsPath)) {
104
- return true;
53
+ createProcessor(options) {
54
+ const processor = unified().use(remarkParse);
55
+ if (options.gfm) {
56
+ processor.use(remarkGfm);
105
57
  }
106
- const files = fs.readdirSync(docsPath);
107
- return files.length === 0;
108
- }
109
- generateInit(sitePath) {
110
- // Check if the site path exists
111
- if (!fs.existsSync(sitePath)) {
112
- fs.mkdirSync(sitePath);
58
+ if (options.toc) {
59
+ processor.use(remarkToc, { heading: 'toc|table of contents' });
113
60
  }
114
- // Add the writr.config file based on js or ts
115
- const writrConfigFile = './init/writr.config.cjs';
116
- fs.copyFileSync(writrConfigFile, `${sitePath}/writr.config.cjs`);
117
- // Add in the image and favicon
118
- fs.copyFileSync('./init/logo.png', `${sitePath}/logo.png`);
119
- fs.copyFileSync('./init/favicon.svg', `${sitePath}/favicon.svg`);
120
- // Add in the variables file
121
- fs.copyFileSync('./init/variables.css', `${sitePath}/variables.css`);
122
- // Output the instructions
123
- this._console.log(`Writr initialized. Please update the ${writrConfigFile} file with your site information. In addition, you can replace the image, favicon, and stype the site with site.css file.`);
124
- }
125
- getVersion() {
126
- const packageJson = fs.readFileSync('./package.json', 'utf8');
127
- const packageObject = JSON.parse(packageJson);
128
- return packageObject.version;
129
- }
130
- async loadConfigFile(sitePath) {
131
- if (fs.existsSync(sitePath)) {
132
- const configFile = `${sitePath}/writr.config.cjs`;
133
- if (fs.existsSync(configFile)) {
134
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
135
- this._configFileModule = await import(configFile);
136
- }
61
+ if (options.emoji) {
62
+ processor.use(remarkEmoji);
137
63
  }
138
- }
139
- async serve(options) {
140
- if (this._server) {
141
- this._server.close();
64
+ processor.use(remarkRehype);
65
+ if (options.slug) {
66
+ processor.use(rehypeSlug);
67
+ }
68
+ if (options.highlight) {
69
+ processor.use(rehypeHighlight);
142
70
  }
143
- const app = express();
144
- const { port } = options;
145
- const { outputPath } = options;
146
- app.use(express.static(outputPath));
147
- this._server = app.listen(port, () => {
148
- this._console.log(`Writr listening at http://localhost:${port}`);
149
- });
71
+ processor.use(rehypeStringify);
72
+ return processor;
150
73
  }
151
74
  }
152
- export { WritrHelpers } from './helpers.js';
153
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd3JpdHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUNuQyxPQUFPLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDMUIsT0FBTyxjQUFjLE1BQU0saUJBQWlCLENBQUM7QUFDN0MsT0FBTyxPQUFPLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxjQUFjLENBQUM7QUFDMUMsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGNBQWMsQ0FBQztBQUMxQyxPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sRUFBQyxjQUFjLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUVyRCxNQUFNLENBQUMsT0FBTyxPQUFPLEtBQUs7SUFDakIsUUFBUSxHQUFpQixJQUFJLFlBQVksRUFBRSxDQUFDO0lBQ25DLFFBQVEsR0FBaUIsSUFBSSxZQUFZLEVBQUUsQ0FBQztJQUNyRCxpQkFBaUIsR0FBUSxFQUFFLENBQUM7SUFDNUIsT0FBTyxDQUEwQjtJQUV6QyxZQUFZLE9BQXNCO1FBQ2pDLElBQUksT0FBTyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQztRQUN6QixDQUFDO0lBQ0YsQ0FBQztJQUVELElBQVcsT0FBTztRQUNqQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdEIsQ0FBQztJQUVELElBQVcsT0FBTyxDQUFDLEtBQW1CO1FBQ3JDLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxJQUFXLE1BQU07UUFDaEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFXLGdCQUFnQjtRQUMxQiwrREFBK0Q7UUFDL0QsT0FBTyxJ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R0FBRyxHQUFHLE9BQU8sRUFBRSxDQUFDO1FBQ3RCLE1BQU0sRUFBQyxJQUFJLEVBQUMsR0FBRyxPQUFPLENBQUM7UUFDdkIsTUFBTSxFQUFDLFVBQVUsRUFBQyxHQUFHLE9BQU8sQ0FBQztRQUU3QixHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUVwQyxJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRTtZQUNwQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyx1Q0FBdUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNsRSxDQUFDLENBQUMsQ0FBQztJQUNKLENBQUM7Q0FDRDtBQUVELE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxjQUFjLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSBodHRwIGZyb20gJ25vZGU6aHR0cCc7XG5pbXBvcnQgcGF0aCBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcbmltcG9ydCBmcyBmcm9tICdmcy1leHRyYSc7XG5pbXBvcnQgdXBkYXRlTm90aWZpZXIgZnJvbSAndXBkYXRlLW5vdGlmaWVyJztcbmltcG9ydCBleHByZXNzIGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHtXcml0ck9wdGlvbnN9IGZyb20gJy4vb3B0aW9ucy5qcyc7XG5pbXBvcnQge1dyaXRyQ29uc29sZX0gZnJvbSAnLi9jb25zb2xlLmpzJztcbmltcG9ydCB7V3JpdHJCdWlsZGVyfSBmcm9tICcuL2J1aWxkZXIuanMnO1xuaW1wb3J0IHtNYXJrZG93bkhlbHBlcn0gZnJvbSAnLi9oZWxwZXJzL21hcmtkb3duLmpzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV3JpdHIge1xuXHRwcml2YXRlIF9vcHRpb25zOiBXcml0ck9wdGlvbnMgPSBuZXcgV3JpdHJPcHRpb25zKCk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX2NvbnNvbGU6IFdyaXRyQ29uc29sZSA9IG5ldyBXcml0ckNvbnNvbGUoKTtcblx0cHJpdmF0ZSBfY29uZmlnRmlsZU1vZHVsZTogYW55ID0ge307XG5cdHByaXZhdGUgX3NlcnZlcjogaHR0cC5TZXJ2ZXIgfCB1bmRlZmluZWQ7XG5cblx0Y29uc3RydWN0b3Iob3B0aW9ucz86IFdyaXRyT3B0aW9ucykge1xuXHRcdGlmIChvcHRpb25zKSB7XG5cdFx0XHR0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgZ2V0IG9wdGlvbnMoKTogV3JpdHJPcHRpb25zIHtcblx0XHRyZXR1cm4gdGhpcy5fb3B0aW9ucztcblx0fVxuXG5cdHB1YmxpYyBzZXQgb3B0aW9ucyh2YWx1ZTogV3JpdHJPcHRpb25zKSB7XG5cdFx0dGhpcy5fb3B0aW9ucyA9IHZhbHVlO1xuXHR9XG5cblx0cHVibGljIGdldCBzZXJ2ZXIoKTogaHR0cC5TZXJ2ZXIgfCB1bmRlZmluZWQge1xuXHRcdHJldHVybiB0aGlzLl9zZXJ2ZXI7XG5cdH1cblxuXHRwdWJsaWMgZ2V0IGNvbmZpZ0ZpbGVNb2R1bGUoKTogYW55IHtcblx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1yZXR1cm5cblx0XHRyZXR1cm4gdGhpcy5fY29uZmlnRmlsZU1vZHVsZTtcblx0fVxuXG5cdHB1YmxpYyBjaGVja0ZvclVwZGF0ZXMoKTogdm9pZCB7XG5cdFx0Y29uc3QgcGFja2FnZUpzb25QYXRoID0gcGF0aC5qb2luKHByb2Nlc3MuY3dkKCksICdwYWNrYWdlLmpzb24nKTtcblx0XHRpZiAoZnMuZXhpc3RzU3luYyhwYWNrYWdlSnNvblBhdGgpKSB7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50XG5cdFx0XHRjb25zdCBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCwgJ3V0ZjgnKSk7XG5cdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50XG5cdFx0XHR1cGRhdGVOb3RpZmllcih7cGtnOiBwYWNrYWdlSnNvbn0pLm5vdGlmeSgpO1xuXHRcdH1cblx0fVxuXG5cdHB1YmxpYyBhc3luYyBleGVjdXRlKHByb2Nlc3M6IE5vZGVKUy5Qcm9jZXNzKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Ly8gQ2hlY2sgZm9yIHVwZGF0ZXNcblx0XHR0aGlzLmNoZWNrRm9yVXBkYXRlcygpO1xuXG5cdFx0Y29uc3QgY29uc29sZVByb2Nlc3MgPSB0aGlzLl9jb25zb2xlLnBhcnNlUHJvY2Vzc0FyZ3YocHJvY2Vzcy5hcmd2KTtcblxuXHRcdC8vIFVwZGF0ZSBvcHRpb25zXG5cdFx0aWYgKGNvbnNvbGVQcm9jZXNzLmFyZ3Muc2l0ZVBhdGgpIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zaXRlUGF0aCA9IGNvbnNvbGVQcm9jZXNzLmFyZ3Muc2l0ZVBhdGg7XG5cdFx0fVxuXG5cdFx0Ly8gTG9hZCB0aGUgQ29uZmlnIEZpbGVcblx0XHRhd2FpdCB0aGlzLmxvYWRDb25maWdGaWxlKHRoaXMub3B0aW9ucy5zaXRlUGF0aCk7XG5cblx0XHQvLyBQYXJzZSB0aGUgY29uZmlnIGZpbGVcblx0XHRpZiAodGhpcy5fY29uZmlnRmlsZU1vZHVsZS5vcHRpb25zKSB7XG5cdFx0XHR0aGlzLm9wdGlvbnMucGFyc2VPcHRpb25zKHRoaXMuX2NvbmZpZ0ZpbGVNb2R1bGUub3B0aW9ucyBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KTtcblx0XHR9XG5cblx0XHQvLyBSdW4gdGhlIG9uUHJlcGFyZSBmdW5jdGlvblxuXHRcdGlmICh0aGlzLl9jb25maWdGaWxlTW9kdWxlLm9uUHJlcGFyZSkge1xuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtY2FsbFxuXHRcdFx0XHRhd2FpdCB0aGlzLl9jb25maWdGaWxlTW9kdWxlLm9uUHJlcGFyZSh0aGlzLm9wdGlvbnMpO1xuXHRcdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdFx0dGhpcy5fY29uc29sZS5lcnJvcigoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2UpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmIChjb25zb2xlUHJvY2Vzcy5hcmdzLm91dHB1dCkge1xuXHRcdFx0dGhpcy5vcHRpb25zLm91dHB1dFBhdGggPSBjb25zb2xlUHJvY2Vzcy5hcmdzLm91dHB1dDtcblx0XHR9XG5cblx0XHRjb25zdCBlbmdpbmVDb25maWcgPSB7XG5cdFx0XHRub2Rlczoge1xuXHRcdFx0XHRmZW5jZTogTWFya2Rvd25IZWxwZXIuZmVuY2UoKSxcblx0XHRcdH0sXG5cdFx0fTtcblxuXHRcdHN3aXRjaCAoY29uc29sZVByb2Nlc3MuY29tbWFuZCkge1xuXHRcdFx0Y2FzZSAnaW5pdCc6IHtcblx0XHRcdFx0Y29uc3QgaXNUeXBlc2NyaXB0ID0gZnMuZXhpc3RzU3luYygnLi90c2NvbmZpZy5qc29uJykgPz8gZmFsc2U7XG5cdFx0XHRcdHRoaXMuZ2VuZXJhdGVJbml0KHRoaXMub3B0aW9ucy5zaXRlUGF0aCk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRjYXNlICdoZWxwJzoge1xuXHRcdFx0XHR0aGlzLl9jb25zb2xlLnByaW50SGVscCgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0Y2FzZSAndmVyc2lvbic6IHtcblx0XHRcdFx0dGhpcy5fY29uc29sZS5sb2codGhpcy5nZXRWZXJzaW9uKCkpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblxuXHRcdFx0Y2FzZSAnc2VydmUnOiB7XG5cdFx0XHRcdGNvbnN0IGJ1aWxkZXIgPSBuZXcgV3JpdHJCdWlsZGVyKHRoaXMub3B0aW9ucywgZW5naW5lQ29uZmlnKTtcblx0XHRcdFx0YXdhaXQgYnVpbGRlci5idWlsZCgpO1xuXHRcdFx0XHRhd2FpdCB0aGlzLnNlcnZlKHRoaXMub3B0aW9ucyk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXG5cdFx0XHRkZWZhdWx0OiB7XG5cdFx0XHRcdGNvbnN0IGJ1aWxkZXIgPSBuZXcgV3JpdHJCdWlsZGVyKHRoaXMub3B0aW9ucywgZW5naW5lQ29uZmlnKTtcblx0XHRcdFx0YXdhaXQgYnVpbGRlci5idWlsZCgpO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgaXNTaW5nbGVQYWdlV2Vic2l0ZShzaXRlUGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG5cdFx0Y29uc3QgZG9jc1BhdGggPSBgJHtzaXRlUGF0aH0vZG9jc2A7XG5cdFx0aWYgKCFmcy5leGlzdHNTeW5jKGRvY3NQYXRoKSkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXG5cdFx0Y29uc3QgZmlsZXMgPSBmcy5yZWFkZGlyU3luYyhkb2NzUGF0aCk7XG5cdFx0cmV0dXJuIGZpbGVzLmxlbmd0aCA9PT0gMDtcblx0fVxuXG5cdHB1YmxpYyBnZW5lcmF0ZUluaXQoc2l0ZVBhdGg6IHN0cmluZyk6IHZvaWQge1xuXHRcdC8vIENoZWNrIGlmIHRoZSBzaXRlIHBhdGggZXhpc3RzXG5cdFx0aWYgKCFmcy5leGlzdHNTeW5jKHNpdGVQYXRoKSkge1xuXHRcdFx0ZnMubWtkaXJTeW5jKHNpdGVQYXRoKTtcblx0XHR9XG5cblx0XHQvLyBBZGQgdGhlIHdyaXRyLmNvbmZpZyBmaWxlIGJhc2VkIG9uIGpzIG9yIHRzXG5cdFx0Y29uc3Qgd3JpdHJDb25maWdGaWxlID0gJy4vaW5pdC93cml0ci5jb25maWcuY2pzJztcblx0XHRmcy5jb3B5RmlsZVN5bmMod3JpdHJDb25maWdGaWxlLCBgJHtzaXRlUGF0aH0vd3JpdHIuY29uZmlnLmNqc2ApO1xuXG5cdFx0Ly8gQWRkIGluIHRoZSBpbWFnZSBhbmQgZmF2aWNvblxuXHRcdGZzLmNvcHlGaWxlU3luYygnLi9pbml0L2xvZ28ucG5nJywgYCR7c2l0ZVBhdGh9L2xvZ28ucG5nYCk7XG5cdFx0ZnMuY29weUZpbGVTeW5jKCcuL2luaXQvZmF2aWNvbi5zdmcnLCBgJHtzaXRlUGF0aH0vZmF2aWNvbi5zdmdgKTtcblxuXHRcdC8vIEFkZCBpbiB0aGUgdmFyaWFibGVzIGZpbGVcblx0XHRmcy5jb3B5RmlsZVN5bmMoJy4vaW5pdC92YXJpYWJsZXMuY3NzJywgYCR7c2l0ZVBhdGh9L3ZhcmlhYmxlcy5jc3NgKTtcblxuXHRcdC8vIE91dHB1dCB0aGUgaW5zdHJ1Y3Rpb25zXG5cdFx0dGhpcy5fY29uc29sZS5sb2coYFdyaXRyIGluaXRpYWxpemVkLiBQbGVhc2UgdXBkYXRlIHRoZSAke3dyaXRyQ29uZmlnRmlsZX0gZmlsZSB3aXRoIHlvdXIgc2l0ZSBpbmZvcm1hdGlvbi4gSW4gYWRkaXRpb24sIHlvdSBjYW4gcmVwbGFjZSB0aGUgaW1hZ2UsIGZhdmljb24sIGFuZCBzdHlwZSB0aGUgc2l0ZSB3aXRoIHNpdGUuY3NzIGZpbGUuYCk7XG5cdH1cblxuXHRwdWJsaWMgZ2V0VmVyc2lvbigpOiBzdHJpbmcge1xuXHRcdGNvbnN0IHBhY2thZ2VKc29uID0gZnMucmVhZEZpbGVTeW5jKCcuL3BhY2thZ2UuanNvbicsICd1dGY4Jyk7XG5cdFx0Y29uc3QgcGFja2FnZU9iamVjdCA9IEpTT04ucGFyc2UocGFja2FnZUpzb24pIGFzIHt2ZXJzaW9uOiBzdHJpbmd9O1xuXHRcdHJldHVybiBwYWNrYWdlT2JqZWN0LnZlcnNpb247XG5cdH1cblxuXHRwdWJsaWMgYXN5bmMgbG9hZENvbmZpZ0ZpbGUoc2l0ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGlmIChmcy5leGlzdHNTeW5jKHNpdGVQYXRoKSkge1xuXHRcdFx0Y29uc3QgY29uZmlnRmlsZSA9IGAke3NpdGVQYXRofS93cml0ci5jb25maWcuY2pzYDtcblx0XHRcdGlmIChmcy5leGlzdHNTeW5jKGNvbmZpZ0ZpbGUpKSB7XG5cdFx0XHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnRcblx0XHRcdFx0dGhpcy5fY29uZmlnRmlsZU1vZHVsZSA9IGF3YWl0IGltcG9ydChjb25maWdGaWxlKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgYXN5bmMgc2VydmUob3B0aW9uczogV3JpdHJPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuX3NlcnZlcikge1xuXHRcdFx0dGhpcy5fc2VydmVyLmNsb3NlKCk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgYXBwID0gZXhwcmVzcygpO1xuXHRcdGNvbnN0IHtwb3J0fSA9IG9wdGlvbnM7XG5cdFx0Y29uc3Qge291dHB1dFBhdGh9ID0gb3B0aW9ucztcblxuXHRcdGFwcC51c2UoZXhwcmVzcy5zdGF0aWMob3V0cHV0UGF0aCkpO1xuXG5cdFx0dGhpcy5fc2VydmVyID0gYXBwLmxpc3Rlbihwb3J0LCAoKSA9PiB7XG5cdFx0XHR0aGlzLl9jb25zb2xlLmxvZyhgV3JpdHIgbGlzdGVuaW5nIGF0IGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWApO1xuXHRcdH0pO1xuXHR9XG59XG5cbmV4cG9ydCB7V3JpdHJIZWxwZXJzfSBmcm9tICcuL2hlbHBlcnMuanMnO1xuIl19
75
+ export { Writr };
76
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JpdHIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvd3JpdHIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLE9BQU8sRUFBWSxNQUFNLFNBQVMsQ0FBQztBQUMzQyxPQUFPLFdBQVcsTUFBTSxjQUFjLENBQUM7QUFDdkMsT0FBTyxZQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sVUFBVSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLGVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLGVBQWUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvQyxPQUFPLFNBQVMsTUFBTSxZQUFZLENBQUM7QUFDbkMsT0FBTyxTQUFTLE1BQU0sWUFBWSxDQUFDO0FBQ25DLE9BQU8sV0FBVyxNQUFNLGNBQWMsQ0FBQztBQW1CdkMsTUFBTSxLQUFLO0lBQ0gsTUFBTSxHQUFHLE9BQU8sRUFBRTtTQUN2QixHQUFHLENBQUMsV0FBVyxDQUFDO1NBQ2hCLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQywrQkFBK0I7U0FDOUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLHdCQUF3QjtTQUN2QyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsb0JBQW9CO1NBQ3JDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQywyQkFBMkI7U0FDN0MsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLGdDQUFnQztTQUNoRCxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsNEJBQTRCO1NBQ2pELEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLGlCQUFpQjtJQUV4QixRQUFRLEdBQWlCO1FBQ3pDLE1BQU0sRUFBRSxTQUFTO1FBQ2pCLEtBQUssRUFBRSxJQUFJO1FBQ1gsR0FBRyxFQUFFLElBQUk7UUFDVCxJQUFJLEVBQUUsSUFBSTtRQUNWLFNBQVMsRUFBRSxJQUFJO1FBQ2YsR0FBRyxFQUFFLElBQUk7S0FDVCxDQUFDO0lBRUYsWUFBWSxPQUFzQjtRQUNqQyxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLE9BQU8sRUFBQyxDQUFDO1lBQy9DLG1FQUFtRTtZQUNuRSxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ25ELENBQUM7SUFDRixDQUFDO0lBRUQsSUFBVyxPQUFPO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN0QixDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFnQixFQUFFLE9BQXVCO1FBQ3JELElBQUksQ0FBQztZQUNKLElBQUksRUFBQyxNQUFNLEVBQUMsR0FBRyxJQUFJLENBQUM7WUFDcEIsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDYixPQUFPLEdBQUcsRUFBQyxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxPQUFPLEVBQUMsQ0FBQztnQkFDekMsbUVBQW1FO2dCQUNuRSxNQUFNLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4QyxDQUFDO1lBRUQsTUFBTSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzVDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQStCLEtBQWUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLENBQUM7SUFDRixDQUFDO0lBRU8sZUFBZSxDQUFDLE9BQXFDO1FBQzVELE1BQU0sU0FBUyxHQUFHLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUU3QyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNqQixTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFCLENBQUM7UUFFRCxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNqQixTQUFTLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxFQUFDLE9BQU8sRUFBRSx1QkFBdUIsRUFBQyxDQUFDLENBQUM7UUFDOUQsQ0FBQztRQUVELElBQUksT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ25CLFNBQVMsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUIsQ0FBQztRQUVELFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFNUIsSUFBSSxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMzQixDQUFDO1FBRUQsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDdkIsU0FBUyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNoQyxDQUFDO1FBRUQsU0FBUyxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUUvQixPQUFPLFNBQVMsQ0FBQztJQUNsQixDQUFDO0NBQ0Q7QUFFRCxPQUFPLEVBQUMsS0FBSyxFQUF3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHt1bmlmaWVkLCBQcm9jZXNzb3J9IGZyb20gJ3VuaWZpZWQnO1xuaW1wb3J0IHJlbWFya1BhcnNlIGZyb20gJ3JlbWFyay1wYXJzZSc7XG5pbXBvcnQgcmVtYXJrUmVoeXBlIGZyb20gJ3JlbWFyay1yZWh5cGUnO1xuaW1wb3J0IHJlaHlwZVNsdWcgZnJvbSAncmVoeXBlLXNsdWcnO1xuaW1wb3J0IHJlaHlwZUhpZ2hsaWdodCBmcm9tICdyZWh5cGUtaGlnaGxpZ2h0JztcbmltcG9ydCByZWh5cGVTdHJpbmdpZnkgZnJvbSAncmVoeXBlLXN0cmluZ2lmeSc7XG5pbXBvcnQgcmVtYXJrVG9jIGZyb20gJ3JlbWFyay10b2MnO1xuaW1wb3J0IHJlbWFya0dmbSBmcm9tICdyZW1hcmstZ2ZtJztcbmltcG9ydCByZW1hcmtFbW9qaSBmcm9tICdyZW1hcmstZW1vamknO1xuXG50eXBlIFdyaXRyT3B0aW9ucyA9IHtcblx0b3BlbmFpPzogc3RyaW5nOyAvLyBPcGVuYWkgYXBpIGtleSAoZGVmYXVsdDogdW5kZWZpbmVkKVxuXHRlbW9qaT86IGJvb2xlYW47IC8vIEVtb2ppIHN1cHBvcnQgKGRlZmF1bHQ6IHRydWUpXG5cdHRvYz86IGJvb2xlYW47IC8vIFRhYmxlIG9mIGNvbnRlbnRzIGdlbmVyYXRpb24gKGRlZmF1bHQ6IHRydWUpXG5cdHNsdWc/OiBib29sZWFuOyAvLyBTbHVnIGdlbmVyYXRpb24gKGRlZmF1bHQ6IHRydWUpXG5cdGhpZ2hsaWdodD86IGJvb2xlYW47IC8vIENvZGUgaGlnaGxpZ2h0aW5nIChkZWZhdWx0OiB0cnVlKVxuXHRnZm0/OiBib29sZWFuOyAvLyBHaXRodWIgZmxhdm9yIG1hcmtkb3duIChkZWZhdWx0OiB0cnVlKVxufTtcblxudHlwZSBSZW5kZXJPcHRpb25zID0ge1xuXHRlbW9qaT86IGJvb2xlYW47IC8vIEVtb2ppIHN1cHBvcnQgKGRlZmF1bHQ6IHRydWUpXG5cdHRvYz86IGJvb2xlYW47IC8vIFRhYmxlIG9mIGNvbnRlbnRzIGdlbmVyYXRpb24gKGRlZmF1bHQ6IHRydWUpXG5cdHNsdWc/OiBib29sZWFuOyAvLyBTbHVnIGdlbmVyYXRpb24gKGRlZmF1bHQ6IHRydWUpXG5cdGhpZ2hsaWdodD86IGJvb2xlYW47IC8vIENvZGUgaGlnaGxpZ2h0aW5nIChkZWZhdWx0OiB0cnVlKVxuXHRnZm0/OiBib29sZWFuOyAvLyBHaXRodWIgZmxhdm9yIG1hcmtkb3duIChkZWZhdWx0OiB0cnVlKVxufTtcblxuY2xhc3MgV3JpdHIge1xuXHRwdWJsaWMgZW5naW5lID0gdW5pZmllZCgpXG5cdFx0LnVzZShyZW1hcmtQYXJzZSlcblx0XHQudXNlKHJlbWFya0dmbSkgLy8gVXNlIEdpdEh1YiBGbGF2b3JlZCBNYXJrZG93blxuXHRcdC51c2UocmVtYXJrVG9jKSAvLyBBZGQgdGFibGUgb2YgY29udGVudHNcblx0XHQudXNlKHJlbWFya0Vtb2ppKSAvLyBBZGQgZW1vamkgc3VwcG9ydFxuXHRcdC51c2UocmVtYXJrUmVoeXBlKSAvLyBDb252ZXJ0IG1hcmtkb3duIHRvIEhUTUxcblx0XHQudXNlKHJlaHlwZVNsdWcpIC8vIEFkZCBzbHVncyB0byBoZWFkaW5ncyBpbiBIVE1MXG5cdFx0LnVzZShyZWh5cGVIaWdobGlnaHQpIC8vIEFwcGx5IHN5bnRheCBoaWdobGlnaHRpbmdcblx0XHQudXNlKHJlaHlwZVN0cmluZ2lmeSk7IC8vIFN0cmluZ2lmeSBIVE1MXG5cblx0cHJpdmF0ZSByZWFkb25seSBfb3B0aW9uczogV3JpdHJPcHRpb25zID0ge1xuXHRcdG9wZW5haTogdW5kZWZpbmVkLFxuXHRcdGVtb2ppOiB0cnVlLFxuXHRcdHRvYzogdHJ1ZSxcblx0XHRzbHVnOiB0cnVlLFxuXHRcdGhpZ2hsaWdodDogdHJ1ZSxcblx0XHRnZm06IHRydWUsXG5cdH07XG5cblx0Y29uc3RydWN0b3Iob3B0aW9ucz86IFdyaXRyT3B0aW9ucykge1xuXHRcdGlmIChvcHRpb25zKSB7XG5cdFx0XHR0aGlzLl9vcHRpb25zID0gey4uLnRoaXMuX29wdGlvbnMsIC4uLm9wdGlvbnN9O1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXNzaWdubWVudFxuXHRcdFx0dGhpcy5lbmdpbmUgPSB0aGlzLmNyZWF0ZVByb2Nlc3Nvcih0aGlzLl9vcHRpb25zKTtcblx0XHR9XG5cdH1cblxuXHRwdWJsaWMgZ2V0IG9wdGlvbnMoKTogV3JpdHJPcHRpb25zIHtcblx0XHRyZXR1cm4gdGhpcy5fb3B0aW9ucztcblx0fVxuXG5cdGFzeW5jIHJlbmRlcihtYXJrZG93bjogc3RyaW5nLCBvcHRpb25zPzogUmVuZGVyT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7XG5cdFx0dHJ5IHtcblx0XHRcdGxldCB7ZW5naW5lfSA9IHRoaXM7XG5cdFx0XHRpZiAob3B0aW9ucykge1xuXHRcdFx0XHRvcHRpb25zID0gey4uLnRoaXMuX29wdGlvbnMsIC4uLm9wdGlvbnN9O1xuXHRcdFx0XHQvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1hc3NpZ25tZW50XG5cdFx0XHRcdGVuZ2luZSA9IHRoaXMuY3JlYXRlUHJvY2Vzc29yKG9wdGlvbnMpO1xuXHRcdFx0fVxuXG5cdFx0XHRjb25zdCBmaWxlID0gYXdhaXQgZW5naW5lLnByb2Nlc3MobWFya2Rvd24pO1xuXHRcdFx0cmV0dXJuIFN0cmluZyhmaWxlKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gcmVuZGVyIG1hcmtkb3duOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcblx0XHR9XG5cdH1cblxuXHRwcml2YXRlIGNyZWF0ZVByb2Nlc3NvcihvcHRpb25zOiBSZW5kZXJPcHRpb25zIHwgV3JpdHJPcHRpb25zKTogYW55IHtcblx0XHRjb25zdCBwcm9jZXNzb3IgPSB1bmlmaWVkKCkudXNlKHJlbWFya1BhcnNlKTtcblxuXHRcdGlmIChvcHRpb25zLmdmbSkge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZW1hcmtHZm0pO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLnRvYykge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZW1hcmtUb2MsIHtoZWFkaW5nOiAndG9jfHRhYmxlIG9mIGNvbnRlbnRzJ30pO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmVtb2ppKSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlbWFya0Vtb2ppKTtcblx0XHR9XG5cblx0XHRwcm9jZXNzb3IudXNlKHJlbWFya1JlaHlwZSk7XG5cblx0XHRpZiAob3B0aW9ucy5zbHVnKSB7XG5cdFx0XHRwcm9jZXNzb3IudXNlKHJlaHlwZVNsdWcpO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLmhpZ2hsaWdodCkge1xuXHRcdFx0cHJvY2Vzc29yLnVzZShyZWh5cGVIaWdobGlnaHQpO1xuXHRcdH1cblxuXHRcdHByb2Nlc3Nvci51c2UocmVoeXBlU3RyaW5naWZ5KTtcblxuXHRcdHJldHVybiBwcm9jZXNzb3I7XG5cdH1cbn1cblxuZXhwb3J0IHtXcml0ciwgdHlwZSBXcml0ck9wdGlvbnMsIHR5cGUgUmVuZGVyT3B0aW9uc307XG5cbiJdfQ==
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "writr",
3
- "version": "2.0.2",
4
- "description": "Beautiful Website for Your Projects",
3
+ "version": "3.0.0",
4
+ "description": "Markdown Rendering Simplified",
5
5
  "type": "module",
6
6
  "exports": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -12,69 +12,65 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "keywords": [
15
- "static-site-generator",
16
- "static-site",
17
- "open source",
18
- "ssg",
19
- "documentation",
20
- "website",
21
- "templates",
22
- "generator",
23
- "framework",
24
- "writr",
25
- "writer",
26
- "html",
27
15
  "markdown",
28
- "handlebars"
16
+ "html",
17
+ "renderer",
18
+ "markdown-to-html",
19
+ "toc",
20
+ "table-of-contents",
21
+ "emoji",
22
+ "syntax-highlighting",
23
+ "markdown-processor",
24
+ "github-flavored-markdown",
25
+ "gfm",
26
+ "remark-plugin",
27
+ "rehype-plugin",
28
+ "markdown-editor",
29
+ "content-management",
30
+ "documentation-tool",
31
+ "blogging",
32
+ "markdown-extension",
33
+ "seo-friendly",
34
+ "markdown-anchors",
35
+ "remark",
36
+ "rehype"
29
37
  ],
30
38
  "scripts": {
31
- "clean": "rimraf ./dist ./coverage ./node_modules ./package-lock.json ./yarn.lock ./site/README.md",
39
+ "clean": "rimraf ./dist ./coverage ./node_modules ./package-lock.json ./yarn.lock ./site/README.md ./site-output",
32
40
  "build": "rimraf ./dist && tsc",
33
- "build-site": "rimraf ./site/README.md && node bin/writr.mjs build -s ./site -o ./dist/site-output",
41
+ "site-build": "rimraf ./site/README.md ./site-output && npx docula build -s ./site -o ./site-output",
42
+ "site-serve": "rimraf ./site/README.md ./site-output && npx docula serve -s ./site -o ./site-output",
34
43
  "test": "xo --fix && vitest run --coverage",
35
- "serve": "rimraf ./site/README.md && node bin/writr.mjs serve -s ./site -o ./dist/site-output",
36
44
  "prepare": "yarn run build"
37
45
  },
38
- "bin": {
39
- "writr": "./bin/writr.mjs"
40
- },
41
46
  "dependencies": {
42
- "@markdoc/markdoc": "^0.4.0",
43
- "axios": "^1.6.2",
44
- "ecto": "^2.4.1",
45
- "express": "^4.18.2",
46
- "feed": "^4.2.2",
47
- "fs-extra": "^11.2.0",
48
- "gray-matter": "^4.0.3",
49
- "js-yaml": "^4.1.0",
50
- "keyv": "^4.5.4",
47
+ "rehype-highlight": "^7.0.0",
48
+ "rehype-slug": "^6.0.0",
49
+ "rehype-stringify": "^10.0.0",
50
+ "remark-emoji": "^4.0.1",
51
+ "remark-gfm": "^4.0.0",
52
+ "remark-parse": "^11.0.0",
53
+ "remark-rehype": "^11.1.0",
54
+ "remark-toc": "^9.0.0",
51
55
  "ts-node": "^10.9.2",
52
- "update-notifier": "^7.0.0"
56
+ "unified": "^11.0.4"
53
57
  },
54
58
  "devDependencies": {
55
- "@types/express": "^4.17.21",
56
- "@types/fs-extra": "^11.0.4",
57
- "@types/js-yaml": "^4.0.9",
58
59
  "@types/node": "^20.10.5",
59
- "@types/update-notifier": "^6.0.8",
60
60
  "@vitest/coverage-v8": "^1.1.0",
61
+ "docula": "^0.4.0",
61
62
  "rimraf": "^5.0.5",
62
63
  "typescript": "^5.3.3",
63
64
  "vitest": "^1.1.0",
64
- "webpack": "^5.89.0",
65
+ "webpack": "^5.90.3",
65
66
  "xo": "^0.56.0"
66
67
  },
67
68
  "xo": {
68
69
  "ignores": [
69
- "writr.config.*",
70
- "vitest.config.mjs",
71
- "bin/writr.js"
70
+ "docula.config.*"
72
71
  ]
73
72
  },
74
73
  "files": [
75
- "dist",
76
- "init",
77
- "template",
78
- "bin"
74
+ "dist"
79
75
  ]
80
76
  }
package/bin/writr.mjs DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ts-node
2
-
3
- import * as process from 'node:process';
4
- import Writr from '../dist/writr.js';
5
-
6
- const writr = new Writr();
7
-
8
- await writr.execute(process);