@hardlydifficult/document-generator 1.0.1

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 ADDED
@@ -0,0 +1,130 @@
1
+ # @hardlydifficult/document-generator
2
+
3
+ Platform-agnostic document builder with chainable API. Build rich documents once, output to multiple formats.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @hardlydifficult/document-generator
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import { doc, toMarkdown, toPlainText } from '@hardlydifficult/document-generator';
15
+
16
+ const document = doc()
17
+ .header("Weekly Report")
18
+ .text("Summary of this week's **key highlights**.")
19
+ .list(["Completed feature A", "Fixed bug B", "Started project C"])
20
+ .divider()
21
+ .link("View details", "https://example.com")
22
+ .context("Generated on 2025-01-15");
23
+
24
+ // Output as markdown
25
+ console.log(toMarkdown(document.getBlocks()));
26
+
27
+ // Output as plain text
28
+ console.log(toPlainText(document.getBlocks()));
29
+ ```
30
+
31
+ ## API
32
+
33
+ ### `doc()` / `new Document()`
34
+
35
+ Create a new document builder. All methods are chainable.
36
+
37
+ ### Chainable Methods
38
+
39
+ | Method | Description |
40
+ |--------|-------------|
41
+ | `.header(text)` | Add a header/title |
42
+ | `.text(content)` | Add text paragraph (supports **bold**, *italic*, ~~strike~~) |
43
+ | `.list(items)` | Add a bulleted list |
44
+ | `.divider()` | Add a horizontal divider |
45
+ | `.context(text)` | Add footer/context text |
46
+ | `.link(text, url)` | Add a hyperlink |
47
+ | `.code(content)` | Add code (auto-detects inline vs multiline) |
48
+ | `.image(url, alt?)` | Add an image |
49
+
50
+ ### `document.getBlocks(): Block[]`
51
+
52
+ Get the internal block representation for custom processing.
53
+
54
+ ## Inline Markdown Support
55
+
56
+ Text blocks support standard inline markdown that gets auto-converted per platform:
57
+
58
+ ```typescript
59
+ doc().text('This has **bold**, *italic*, and ~~strikethrough~~ text.');
60
+ ```
61
+
62
+ - Standard markdown: `**bold**`, `*italic*`, `~~strike~~`
63
+ - Slack: Converted to `*bold*`, `_italic_`, `~strike~`
64
+ - Discord: Uses standard markdown (no conversion needed)
65
+ - Plain text: Formatting stripped
66
+
67
+ **Note:** Use `.code()` and `.link()` methods for code and links—not markdown syntax.
68
+
69
+ ## Code Blocks
70
+
71
+ The `.code()` method auto-detects format:
72
+
73
+ ```typescript
74
+ // Single line → inline code
75
+ doc().code('const x = 1'); // → `const x = 1`
76
+
77
+ // Multiline → code block
78
+ doc().code('const x = 1;\nconst y = 2;');
79
+ // → ```
80
+ // const x = 1;
81
+ // const y = 2;
82
+ // ```
83
+ ```
84
+
85
+ ## Outputters
86
+
87
+ ### `toMarkdown(blocks): string`
88
+
89
+ Convert to standard markdown format.
90
+
91
+ ### `toPlainText(blocks): string`
92
+
93
+ Convert to plain text, stripping all formatting.
94
+
95
+ ## Block Types
96
+
97
+ Internal block types for custom processing:
98
+
99
+ ```typescript
100
+ type Block =
101
+ | { type: 'header'; text: string }
102
+ | { type: 'text'; content: string }
103
+ | { type: 'list'; items: string[] }
104
+ | { type: 'divider' }
105
+ | { type: 'context'; text: string }
106
+ | { type: 'link'; text: string; url: string }
107
+ | { type: 'code'; content: string; multiline: boolean }
108
+ | { type: 'image'; url: string; alt?: string };
109
+ ```
110
+
111
+ ## Integration with @hardlydifficult/chat
112
+
113
+ Documents integrate seamlessly with the chat package for Slack and Discord:
114
+
115
+ ```typescript
116
+ import { doc } from '@hardlydifficult/document-generator';
117
+ import { createChatClient } from '@hardlydifficult/chat';
118
+
119
+ const client = createChatClient({ type: 'slack' });
120
+ const channel = await client.connect(channelId);
121
+
122
+ const report = doc()
123
+ .header("Daily Metrics")
124
+ .text("Here are today's **key numbers**:")
125
+ .list(["Users: 1,234", "Revenue: $5,678", "Errors: 0"])
126
+ .context("Generated automatically");
127
+
128
+ // Automatically converted to Slack Block Kit
129
+ await channel.postMessage(report);
130
+ ```
@@ -0,0 +1,17 @@
1
+ import type { Block } from './types.js';
2
+ export declare class Document {
3
+ private blocks;
4
+ header(text: string): this;
5
+ text(content: string): this;
6
+ list(items: string[]): this;
7
+ divider(): this;
8
+ context(text: string): this;
9
+ link(text: string, url: string): this;
10
+ code(content: string): this;
11
+ image(url: string, alt?: string): this;
12
+ getBlocks(): Block[];
13
+ toMarkdown(): string;
14
+ toPlainText(): string;
15
+ }
16
+ export declare function doc(): Document;
17
+ //# sourceMappingURL=Document.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Document.d.ts","sourceRoot":"","sources":["../src/Document.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EASN,MAAM,YAAY,CAAC;AAIpB,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAe;IAE7B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAS1B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAS3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAS3B,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAS3B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAUrC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAW3B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAUtC,SAAS,IAAI,KAAK,EAAE;IAIpB,UAAU,IAAI,MAAM;IAIpB,WAAW,IAAI,MAAM;CAGtB;AAED,wBAAgB,GAAG,IAAI,QAAQ,CAE9B"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Document = void 0;
4
+ exports.doc = doc;
5
+ const markdown_js_1 = require("./outputters/markdown.js");
6
+ const plainText_js_1 = require("./outputters/plainText.js");
7
+ class Document {
8
+ blocks = [];
9
+ header(text) {
10
+ const block = {
11
+ type: 'header',
12
+ text,
13
+ };
14
+ this.blocks.push(block);
15
+ return this;
16
+ }
17
+ text(content) {
18
+ const block = {
19
+ type: 'text',
20
+ content,
21
+ };
22
+ this.blocks.push(block);
23
+ return this;
24
+ }
25
+ list(items) {
26
+ const block = {
27
+ type: 'list',
28
+ items,
29
+ };
30
+ this.blocks.push(block);
31
+ return this;
32
+ }
33
+ divider() {
34
+ const block = {
35
+ type: 'divider',
36
+ };
37
+ this.blocks.push(block);
38
+ return this;
39
+ }
40
+ context(text) {
41
+ const block = {
42
+ type: 'context',
43
+ text,
44
+ };
45
+ this.blocks.push(block);
46
+ return this;
47
+ }
48
+ link(text, url) {
49
+ const block = {
50
+ type: 'link',
51
+ text,
52
+ url,
53
+ };
54
+ this.blocks.push(block);
55
+ return this;
56
+ }
57
+ code(content) {
58
+ const multiline = content.includes('\n');
59
+ const block = {
60
+ type: 'code',
61
+ content,
62
+ multiline,
63
+ };
64
+ this.blocks.push(block);
65
+ return this;
66
+ }
67
+ image(url, alt) {
68
+ const block = {
69
+ type: 'image',
70
+ url,
71
+ alt,
72
+ };
73
+ this.blocks.push(block);
74
+ return this;
75
+ }
76
+ getBlocks() {
77
+ return this.blocks;
78
+ }
79
+ toMarkdown() {
80
+ return (0, markdown_js_1.toMarkdown)(this.blocks);
81
+ }
82
+ toPlainText() {
83
+ return (0, plainText_js_1.toPlainText)(this.blocks);
84
+ }
85
+ }
86
+ exports.Document = Document;
87
+ function doc() {
88
+ return new Document();
89
+ }
90
+ //# sourceMappingURL=Document.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Document.js","sourceRoot":"","sources":["../src/Document.ts"],"names":[],"mappings":";;;AAyGA,kBAEC;AAhGD,0DAAwE;AACxE,4DAA2E;AAE3E,MAAa,QAAQ;IACX,MAAM,GAAY,EAAE,CAAC;IAE7B,MAAM,CAAC,IAAY;QACjB,MAAM,KAAK,GAAgB;YACzB,IAAI,EAAE,QAAQ;YACd,IAAI;SACL,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,MAAM,KAAK,GAAc;YACvB,IAAI,EAAE,MAAM;YACZ,OAAO;SACR,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,KAAe;QAClB,MAAM,KAAK,GAAc;YACvB,IAAI,EAAE,MAAM;YACZ,KAAK;SACN,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,MAAM,KAAK,GAAiB;YAC1B,IAAI,EAAE,SAAS;SAChB,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,MAAM,KAAK,GAAiB;YAC1B,IAAI,EAAE,SAAS;YACf,IAAI;SACL,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,IAAY,EAAE,GAAW;QAC5B,MAAM,KAAK,GAAc;YACvB,IAAI,EAAE,MAAM;YACZ,IAAI;YACJ,GAAG;SACJ,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC,OAAe;QAClB,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,KAAK,GAAc;YACvB,IAAI,EAAE,MAAM;YACZ,OAAO;YACP,SAAS;SACV,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,GAAY;QAC7B,MAAM,KAAK,GAAe;YACxB,IAAI,EAAE,OAAO;YACb,GAAG;YACH,GAAG;SACJ,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,UAAU;QACR,OAAO,IAAA,wBAAc,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,WAAW;QACT,OAAO,IAAA,0BAAe,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;CACF;AAzFD,4BAyFC;AAED,SAAgB,GAAG;IACjB,OAAO,IAAI,QAAQ,EAAE,CAAC;AACxB,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { Document, doc } from './Document.js';
2
+ export type { Block, HeaderBlock, TextBlock, ListBlock, DividerBlock, ContextBlock, LinkBlock, CodeBlock, ImageBlock, Platform, } from './types.js';
3
+ export { toMarkdown } from './outputters/markdown.js';
4
+ export { toPlainText } from './outputters/plainText.js';
5
+ export { convertMarkdown, stripMarkdown } from './markdownConverter.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAG9C,YAAY,EACV,KAAK,EACL,WAAW,EACX,SAAS,EACT,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,QAAQ,GACT,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stripMarkdown = exports.convertMarkdown = exports.toPlainText = exports.toMarkdown = exports.doc = exports.Document = void 0;
4
+ // Main classes and factory
5
+ var Document_js_1 = require("./Document.js");
6
+ Object.defineProperty(exports, "Document", { enumerable: true, get: function () { return Document_js_1.Document; } });
7
+ Object.defineProperty(exports, "doc", { enumerable: true, get: function () { return Document_js_1.doc; } });
8
+ // Outputters (for direct use)
9
+ var markdown_js_1 = require("./outputters/markdown.js");
10
+ Object.defineProperty(exports, "toMarkdown", { enumerable: true, get: function () { return markdown_js_1.toMarkdown; } });
11
+ var plainText_js_1 = require("./outputters/plainText.js");
12
+ Object.defineProperty(exports, "toPlainText", { enumerable: true, get: function () { return plainText_js_1.toPlainText; } });
13
+ // Markdown converter (for custom outputters)
14
+ var markdownConverter_js_1 = require("./markdownConverter.js");
15
+ Object.defineProperty(exports, "convertMarkdown", { enumerable: true, get: function () { return markdownConverter_js_1.convertMarkdown; } });
16
+ Object.defineProperty(exports, "stripMarkdown", { enumerable: true, get: function () { return markdownConverter_js_1.stripMarkdown; } });
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2BAA2B;AAC3B,6CAA8C;AAArC,uGAAA,QAAQ,OAAA;AAAE,kGAAA,GAAG,OAAA;AAgBtB,8BAA8B;AAC9B,wDAAsD;AAA7C,yGAAA,UAAU,OAAA;AACnB,0DAAwD;AAA/C,2GAAA,WAAW,OAAA;AAEpB,6CAA6C;AAC7C,+DAAwE;AAA/D,uHAAA,eAAe,OAAA;AAAE,qHAAA,aAAa,OAAA"}
@@ -0,0 +1,17 @@
1
+ import type { Platform } from './types.js';
2
+ /**
3
+ * Converts inline markdown formatting to the target platform format.
4
+ *
5
+ * Handles:
6
+ * - Bold: `**text**` → platform-specific bold
7
+ * - Italic: `*text*` → platform-specific italic
8
+ * - Strikethrough: `~~text~~` → platform-specific strike
9
+ *
10
+ * Processing order: bold → italic → strikethrough (to avoid matching `**` as italic)
11
+ */
12
+ export declare function convertMarkdown(text: string, platform: Platform): string;
13
+ /**
14
+ * Removes all markdown formatting from text, returning plain text.
15
+ */
16
+ export declare function stripMarkdown(text: string): string;
17
+ //# sourceMappingURL=markdownConverter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdownConverter.d.ts","sourceRoot":"","sources":["../src/markdownConverter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,MAAM,CA8DxE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAalD"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertMarkdown = convertMarkdown;
4
+ exports.stripMarkdown = stripMarkdown;
5
+ /**
6
+ * Converts inline markdown formatting to the target platform format.
7
+ *
8
+ * Handles:
9
+ * - Bold: `**text**` → platform-specific bold
10
+ * - Italic: `*text*` → platform-specific italic
11
+ * - Strikethrough: `~~text~~` → platform-specific strike
12
+ *
13
+ * Processing order: bold → italic → strikethrough (to avoid matching `**` as italic)
14
+ */
15
+ function convertMarkdown(text, platform) {
16
+ if (platform === 'plaintext') {
17
+ return stripMarkdown(text);
18
+ }
19
+ let result = text;
20
+ const placeholders = new Map();
21
+ let placeholderIndex = 0;
22
+ // Process bold first: **text** (before italic to avoid matching ** as italic)
23
+ // Use placeholder to prevent italic regex from matching converted bold
24
+ result = result.replace(/\*\*(.+?)\*\*/g, (_match, content) => {
25
+ const placeholder = `__BOLD_PLACEHOLDER_${String(placeholderIndex++)}__`;
26
+ let replacement;
27
+ switch (platform) {
28
+ case 'markdown':
29
+ case 'discord':
30
+ replacement = `**${content}**`;
31
+ break;
32
+ case 'slack':
33
+ replacement = `*${content}*`;
34
+ break;
35
+ default:
36
+ replacement = content;
37
+ }
38
+ placeholders.set(placeholder, replacement);
39
+ return placeholder;
40
+ });
41
+ // Process italic: *text* (but not **text**)
42
+ // Use negative lookbehind/lookahead to ensure single asterisk
43
+ result = result.replace(/(?<!\*)\*([^*]+?)\*(?!\*)/g, (_match, content) => {
44
+ switch (platform) {
45
+ case 'markdown':
46
+ case 'discord':
47
+ return `*${content}*`;
48
+ case 'slack':
49
+ return `_${content}_`;
50
+ default:
51
+ return content;
52
+ }
53
+ });
54
+ // Process strikethrough: ~~text~~
55
+ result = result.replace(/~~(.+?)~~/g, (_match, content) => {
56
+ switch (platform) {
57
+ case 'markdown':
58
+ case 'discord':
59
+ return `~~${content}~~`;
60
+ case 'slack':
61
+ return `~${content}~`;
62
+ default:
63
+ return content;
64
+ }
65
+ });
66
+ // Replace placeholders with final bold format
67
+ for (const [placeholder, replacement] of placeholders) {
68
+ result = result.replace(placeholder, replacement);
69
+ }
70
+ return result;
71
+ }
72
+ /**
73
+ * Removes all markdown formatting from text, returning plain text.
74
+ */
75
+ function stripMarkdown(text) {
76
+ let result = text;
77
+ // Remove bold: **text** → text
78
+ result = result.replace(/\*\*(.+?)\*\*/g, '$1');
79
+ // Remove italic: *text* → text (but not **text**)
80
+ result = result.replace(/(?<!\*)\*([^*]+?)\*(?!\*)/g, '$1');
81
+ // Remove strikethrough: ~~text~~ → text
82
+ result = result.replace(/~~(.+?)~~/g, '$1');
83
+ return result;
84
+ }
85
+ //# sourceMappingURL=markdownConverter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdownConverter.js","sourceRoot":"","sources":["../src/markdownConverter.ts"],"names":[],"mappings":";;AAYA,0CA8DC;AAKD,sCAaC;AA1FD;;;;;;;;;GASG;AACH,SAAgB,eAAe,CAAC,IAAY,EAAE,QAAkB;IAC9D,IAAI,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC7B,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,IAAI,gBAAgB,GAAG,CAAC,CAAC;IAEzB,8EAA8E;IAC9E,uEAAuE;IACvE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,MAAM,EAAE,OAAe,EAAE,EAAE;QACpE,MAAM,WAAW,GAAG,sBAAsB,MAAM,CAAC,gBAAgB,EAAE,CAAC,IAAI,CAAC;QACzE,IAAI,WAAmB,CAAC;QACxB,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,UAAU,CAAC;YAChB,KAAK,SAAS;gBACZ,WAAW,GAAG,KAAK,OAAO,IAAI,CAAC;gBAC/B,MAAM;YACR,KAAK,OAAO;gBACV,WAAW,GAAG,IAAI,OAAO,GAAG,CAAC;gBAC7B,MAAM;YACR;gBACE,WAAW,GAAG,OAAO,CAAC;QAC1B,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QAC3C,OAAO,WAAW,CAAC;IACrB,CAAC,CAAC,CAAC;IAEH,4CAA4C;IAC5C,8DAA8D;IAC9D,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC,MAAc,EAAE,OAAe,EAAE,EAAE;QACxF,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,UAAU,CAAC;YAChB,KAAK,SAAS;gBACZ,OAAO,IAAI,OAAO,GAAG,CAAC;YACxB,KAAK,OAAO;gBACV,OAAO,IAAI,OAAO,GAAG,CAAC;YACxB;gBACE,OAAO,OAAO,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,kCAAkC;IAClC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,MAAc,EAAE,OAAe,EAAE,EAAE;QACxE,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,UAAU,CAAC;YAChB,KAAK,SAAS;gBACZ,OAAO,KAAK,OAAO,IAAI,CAAC;YAC1B,KAAK,OAAO;gBACV,OAAO,IAAI,OAAO,GAAG,CAAC;YACxB;gBACE,OAAO,OAAO,CAAC;QACnB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,8CAA8C;IAC9C,KAAK,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,IAAI,YAAY,EAAE,CAAC;QACtD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,IAAY;IACxC,IAAI,MAAM,GAAG,IAAI,CAAC;IAElB,+BAA+B;IAC/B,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAEhD,kDAAkD;IAClD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAC;IAE5D,wCAAwC;IACxC,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAE5C,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { toMarkdown } from './markdown.js';
2
+ export { toPlainText } from './plainText.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/outputters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toPlainText = exports.toMarkdown = void 0;
4
+ var markdown_js_1 = require("./markdown.js");
5
+ Object.defineProperty(exports, "toMarkdown", { enumerable: true, get: function () { return markdown_js_1.toMarkdown; } });
6
+ var plainText_js_1 = require("./plainText.js");
7
+ Object.defineProperty(exports, "toPlainText", { enumerable: true, get: function () { return plainText_js_1.toPlainText; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/outputters/index.ts"],"names":[],"mappings":";;;AAAA,6CAA2C;AAAlC,yGAAA,UAAU,OAAA;AACnB,+CAA6C;AAApC,2GAAA,WAAW,OAAA"}
@@ -0,0 +1,3 @@
1
+ import type { Block } from '../types.js';
2
+ export declare function toMarkdown(blocks: Block[]): string;
3
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/outputters/markdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,wBAAgB,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAsClD"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toMarkdown = toMarkdown;
4
+ function toMarkdown(blocks) {
5
+ return blocks
6
+ .map((block) => {
7
+ switch (block.type) {
8
+ case 'header':
9
+ return `# ${block.text}\n\n`;
10
+ case 'text':
11
+ return `${block.content}\n\n`;
12
+ case 'list':
13
+ return `${block.items.map((item) => `- ${item}`).join('\n')}\n\n`;
14
+ case 'divider':
15
+ return `---\n\n`;
16
+ case 'context':
17
+ return `*${block.text}*\n\n`;
18
+ case 'link':
19
+ return `[${block.text}](${block.url})\n\n`;
20
+ case 'code':
21
+ if (block.multiline) {
22
+ return `\`\`\`\n${block.content}\n\`\`\`\n\n`;
23
+ }
24
+ return `\`${block.content}\`\n\n`;
25
+ case 'image': {
26
+ const alt = block.alt ?? block.url;
27
+ return `![${alt}](${block.url})\n\n`;
28
+ }
29
+ default:
30
+ return '';
31
+ }
32
+ })
33
+ .join('');
34
+ }
35
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/outputters/markdown.ts"],"names":[],"mappings":";;AAEA,gCAsCC;AAtCD,SAAgB,UAAU,CAAC,MAAe;IACxC,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,QAAQ;gBACX,OAAO,KAAK,KAAK,CAAC,IAAI,MAAM,CAAC;YAE/B,KAAK,MAAM;gBACT,OAAO,GAAG,KAAK,CAAC,OAAO,MAAM,CAAC;YAEhC,KAAK,MAAM;gBACT,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAEpE,KAAK,SAAS;gBACZ,OAAO,SAAS,CAAC;YAEnB,KAAK,SAAS;gBACZ,OAAO,IAAI,KAAK,CAAC,IAAI,OAAO,CAAC;YAE/B,KAAK,MAAM;gBACT,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,GAAG,OAAO,CAAC;YAE7C,KAAK,MAAM;gBACT,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;oBACpB,OAAO,WAAW,KAAK,CAAC,OAAO,cAAc,CAAC;gBAChD,CAAC;gBACD,OAAO,KAAK,KAAK,CAAC,OAAO,QAAQ,CAAC;YAEpC,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC;gBACnC,OAAO,KAAK,GAAG,KAAK,KAAK,CAAC,GAAG,OAAO,CAAC;YACvC,CAAC;YAED;gBACE,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Block } from '../types.js';
2
+ export declare function toPlainText(blocks: Block[]): string;
3
+ //# sourceMappingURL=plainText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plainText.d.ts","sourceRoot":"","sources":["../../src/outputters/plainText.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGzC,wBAAgB,WAAW,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAmCnD"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toPlainText = toPlainText;
4
+ const markdownConverter_js_1 = require("../markdownConverter.js");
5
+ function toPlainText(blocks) {
6
+ return blocks
7
+ .map((block) => {
8
+ switch (block.type) {
9
+ case 'header':
10
+ return `${block.text.toUpperCase()}\n\n`;
11
+ case 'text':
12
+ return `${(0, markdownConverter_js_1.stripMarkdown)(block.content)}\n\n`;
13
+ case 'list':
14
+ return `${block.items.map((item) => `• ${(0, markdownConverter_js_1.stripMarkdown)(item)}`).join('\n')}\n\n`;
15
+ case 'divider':
16
+ return `────────────────\n\n`;
17
+ case 'context':
18
+ return `${(0, markdownConverter_js_1.stripMarkdown)(block.text)}\n\n`;
19
+ case 'link':
20
+ return `${block.text} (${block.url})\n\n`;
21
+ case 'code':
22
+ return `${block.content}\n\n`;
23
+ case 'image': {
24
+ const alt = block.alt ?? block.url;
25
+ return `[Image: ${alt}]\n\n`;
26
+ }
27
+ default:
28
+ return '';
29
+ }
30
+ })
31
+ .join('');
32
+ }
33
+ //# sourceMappingURL=plainText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plainText.js","sourceRoot":"","sources":["../../src/outputters/plainText.ts"],"names":[],"mappings":";;AAGA,kCAmCC;AArCD,kEAAwD;AAExD,SAAgB,WAAW,CAAC,MAAe;IACzC,OAAO,MAAM;SACV,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;QACb,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACnB,KAAK,QAAQ;gBACX,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;YAE3C,KAAK,MAAM;gBACT,OAAO,GAAG,IAAA,oCAAa,EAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAE/C,KAAK,MAAM;gBACT,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAA,oCAAa,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAEnF,KAAK,SAAS;gBACZ,OAAO,sBAAsB,CAAC;YAEhC,KAAK,SAAS;gBACZ,OAAO,GAAG,IAAA,oCAAa,EAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;YAE5C,KAAK,MAAM;gBACT,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,GAAG,OAAO,CAAC;YAE5C,KAAK,MAAM;gBACT,OAAO,GAAG,KAAK,CAAC,OAAO,MAAM,CAAC;YAEhC,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC;gBACnC,OAAO,WAAW,GAAG,OAAO,CAAC;YAC/B,CAAC;YAED;gBACE,OAAO,EAAE,CAAC;QACd,CAAC;IACH,CAAC,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,37 @@
1
+ export type Platform = 'markdown' | 'slack' | 'discord' | 'plaintext';
2
+ export type Block = HeaderBlock | TextBlock | ListBlock | DividerBlock | ContextBlock | LinkBlock | CodeBlock | ImageBlock;
3
+ export interface HeaderBlock {
4
+ type: 'header';
5
+ text: string;
6
+ }
7
+ export interface TextBlock {
8
+ type: 'text';
9
+ content: string;
10
+ }
11
+ export interface ListBlock {
12
+ type: 'list';
13
+ items: string[];
14
+ }
15
+ export interface DividerBlock {
16
+ type: 'divider';
17
+ }
18
+ export interface ContextBlock {
19
+ type: 'context';
20
+ text: string;
21
+ }
22
+ export interface LinkBlock {
23
+ type: 'link';
24
+ text: string;
25
+ url: string;
26
+ }
27
+ export interface CodeBlock {
28
+ type: 'code';
29
+ content: string;
30
+ multiline: boolean;
31
+ }
32
+ export interface ImageBlock {
33
+ type: 'image';
34
+ url: string;
35
+ alt?: string;
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;AAEtE,MAAM,MAAM,KAAK,GACb,WAAW,GACX,SAAS,GACT,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,SAAS,GACT,SAAS,GACT,UAAU,CAAC;AAEf,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;CACd"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@hardlydifficult/document-generator",
3
+ "version": "1.0.1",
4
+ "main": "./dist/index.js",
5
+ "types": "./dist/index.d.ts",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "test": "vitest run",
12
+ "test:watch": "vitest",
13
+ "clean": "rm -rf dist",
14
+ "lint": "tsc --noEmit"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "5.8.3",
18
+ "@types/node": "20.19.31",
19
+ "vitest": "1.6.1"
20
+ }
21
+ }