prose-writer 0.1.1 → 0.1.2
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 +72 -94
- package/dist/index.js +27 -27
- package/dist/index.js.map +3 -3
- package/dist/markdown.js +28 -28
- package/dist/markdown.js.map +3 -3
- package/dist/prose-writer.d.ts +0 -16
- package/dist/safe.d.ts +0 -1
- package/dist/safe.js +28 -28
- package/dist/safe.js.map +3 -3
- package/dist/validation.js +27 -27
- package/dist/validation.js.map +3 -3
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
A zero-dependency, chainable TypeScript library for building formatted text and markdown strings. Perfect for constructing LLM prompts, generating documentation, or any scenario where you need to programmatically build structured text.
|
|
4
4
|
|
|
5
|
+
## In one sentence
|
|
6
|
+
|
|
7
|
+
Prose Writer is a fluent builder for producing markdown-friendly strings without template literal sprawl.
|
|
8
|
+
|
|
9
|
+
## When to use it
|
|
10
|
+
|
|
11
|
+
- You need readable, composable prompt or document builders in code
|
|
12
|
+
- You want conditionals, loops, and reusable pieces without `.map().join()` or manual concatenation
|
|
13
|
+
- You need safe handling of untrusted input or structured output sections (JSON/YAML)
|
|
14
|
+
|
|
15
|
+
## How it works (3 steps)
|
|
16
|
+
|
|
17
|
+
1. `write()` creates a builder (optionally with initial text).
|
|
18
|
+
2. Chain block helpers like `.section()`, `.list()`, `.tag()`, `.codeblock()`, `.json()`.
|
|
19
|
+
3. Call `.toString()` or `String(writer)` to get the final text.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { write } from 'prose-writer';
|
|
23
|
+
|
|
24
|
+
const prompt = write('You are a helpful assistant.')
|
|
25
|
+
.section('Guidelines', (w) => w.list('Be concise', 'Cite sources'))
|
|
26
|
+
.tag('input', userText)
|
|
27
|
+
.toString();
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Each `write()` call ends with a newline, so chained calls become separate paragraphs (a blank line between). To keep content on the same line, pass multiple strings to a single `write()` call. Most block helpers add blank lines around themselves so the output reads like markdown paragraphs. Use `write()` with no args to insert an extra blank line.
|
|
31
|
+
|
|
5
32
|
## Why Prose Writer?
|
|
6
33
|
|
|
7
34
|
Building prompts for LLMs in code is _painful_. You end up with wild stuff like this.
|
|
@@ -23,7 +50,27 @@ ${context}
|
|
|
23
50
|
|
|
24
51
|
Template literals become unreadable. String concatenation is worse. And when you need conditionals, variables, or reusable pieces? Good luck.
|
|
25
52
|
|
|
26
|
-
|
|
53
|
+
Compared to concatenating arrays of strings, Prose Writer keeps structure and spacing inside the builder instead of scattering `join()` logic, manual newlines, and nested maps across your code. Compared to giant template strings, it avoids brittle whitespace and makes conditional or reusable sections readable and composable.
|
|
54
|
+
|
|
55
|
+
Array concatenation version:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
const prompt = [
|
|
59
|
+
`You are a ${role}.`,
|
|
60
|
+
'',
|
|
61
|
+
'## Guidelines',
|
|
62
|
+
...guidelines.map((g) => `- ${g}`),
|
|
63
|
+
'',
|
|
64
|
+
'## Examples',
|
|
65
|
+
...examples.map((ex, i) => `### Example ${i + 1}\n${ex}`),
|
|
66
|
+
'',
|
|
67
|
+
'<context>',
|
|
68
|
+
context,
|
|
69
|
+
'</context>',
|
|
70
|
+
].join('\n');
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Prose Writer version:
|
|
27
74
|
|
|
28
75
|
```typescript
|
|
29
76
|
const prompt = write(`You are a ${role}.`)
|
|
@@ -42,7 +89,6 @@ const prompt = write(`You are a ${role}.`)
|
|
|
42
89
|
- **Composable** - Build prompts from reusable pieces with `.append()` and `.clone()`
|
|
43
90
|
- **Logical grouping** - Use `.with(builder)` to group related operations
|
|
44
91
|
- **Conditional logic** - Add sections conditionally with `.when(condition, builder)`
|
|
45
|
-
- **Template variables** - Use `{{placeholders}}` and `.fill()` for dynamic content
|
|
46
92
|
- **LLM-optimized** - Built-in `.tag()` for XML delimiters (Claude loves these), `.json()` and `.yaml()` for structured output instructions
|
|
47
93
|
- **Batch operations** - Iterate with `.each()` instead of awkward `.map().join()` chains
|
|
48
94
|
- **Token awareness** - Estimate prompt size with `.tokens()`
|
|
@@ -66,6 +112,9 @@ const outputFormat = write('').definitions({
|
|
|
66
112
|
suggestions: 'Recommended improvements',
|
|
67
113
|
});
|
|
68
114
|
|
|
115
|
+
const language = 'TypeScript';
|
|
116
|
+
const framework = 'React';
|
|
117
|
+
|
|
69
118
|
// Build the prompt
|
|
70
119
|
const reviewPrompt = write('')
|
|
71
120
|
.append(codeReviewPersona)
|
|
@@ -79,7 +128,8 @@ const reviewPrompt = write('')
|
|
|
79
128
|
.when(strictMode, (w) => w.write('Be extremely thorough. Miss nothing.'))
|
|
80
129
|
.section('Output Format', (w) => w.append(outputFormat))
|
|
81
130
|
.tag('code', userCode)
|
|
82
|
-
.
|
|
131
|
+
.write('Language:', language)
|
|
132
|
+
.write('Framework:', framework);
|
|
83
133
|
```
|
|
84
134
|
|
|
85
135
|
Stop fighting with template strings. Start writing prompts that are readable, maintainable, and composable.
|
|
@@ -182,17 +232,8 @@ Creates a `ProseWriter` that escapes untrusted input. Safe mode:
|
|
|
182
232
|
- Wraps inline code with a backtick fence that can't be broken by user input
|
|
183
233
|
|
|
184
234
|
Use this when inserting user-generated content. To intentionally include raw Markdown, pass a `ProseWriter` instance or call `.raw()` to bypass escaping.
|
|
185
|
-
In safe mode, `fill()` also escapes variable values.
|
|
186
|
-
If your template string is trusted (authored by you), use `write.safe.template(...)` to prevent the template itself from being escaped.
|
|
187
235
|
You can also import a safe-first writer: `import { write } from 'prose-writer/safe'`.
|
|
188
236
|
|
|
189
|
-
```typescript
|
|
190
|
-
const prompt = write.safe
|
|
191
|
-
.template('You are {{role}}!')
|
|
192
|
-
.fill({ role: userRole })
|
|
193
|
-
.toString();
|
|
194
|
-
```
|
|
195
|
-
|
|
196
237
|
```typescript
|
|
197
238
|
const prompt = write
|
|
198
239
|
.safe('User input:', userInput)
|
|
@@ -218,20 +259,21 @@ Hello **World**
|
|
|
218
259
|
```
|
|
219
260
|
|
|
220
261
|
```typescript
|
|
221
|
-
const
|
|
262
|
+
const multiParagraph = write('First line').write('Second line').toString();
|
|
222
263
|
```
|
|
223
264
|
|
|
224
265
|
Output:
|
|
225
266
|
|
|
226
267
|
```markdown
|
|
227
268
|
First line
|
|
269
|
+
|
|
228
270
|
Second line
|
|
229
271
|
```
|
|
230
272
|
|
|
231
|
-
Adding
|
|
273
|
+
Adding an extra blank line between paragraphs:
|
|
232
274
|
|
|
233
275
|
```typescript
|
|
234
|
-
const
|
|
276
|
+
const spacedParagraphs = write('Paragraph 1').write().write('Paragraph 2').toString();
|
|
235
277
|
```
|
|
236
278
|
|
|
237
279
|
Output:
|
|
@@ -244,7 +286,7 @@ Paragraph 2
|
|
|
244
286
|
|
|
245
287
|
### `.write(...content: string[])`
|
|
246
288
|
|
|
247
|
-
Appends content to the prose. Multiple arguments are joined with a space, and a newline is added at the end.
|
|
289
|
+
Appends content to the prose. Multiple arguments are joined with a space, and a newline is added at the end. Each chained call starts a new paragraph (blank line), so use a single `write()` call when you want one line.
|
|
248
290
|
|
|
249
291
|
```typescript
|
|
250
292
|
write('User:').write('Hello', 'Assistant').toString();
|
|
@@ -257,6 +299,18 @@ User:
|
|
|
257
299
|
Hello Assistant
|
|
258
300
|
```
|
|
259
301
|
|
|
302
|
+
Same line by passing multiple strings:
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
write('User:', 'Hello', 'Assistant').toString();
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Output:
|
|
309
|
+
|
|
310
|
+
```markdown
|
|
311
|
+
User: Hello Assistant
|
|
312
|
+
```
|
|
313
|
+
|
|
260
314
|
### Inline Utilities
|
|
261
315
|
|
|
262
316
|
The following utilities return formatted strings and can be used within `write()` calls or anywhere else.
|
|
@@ -287,21 +341,6 @@ write(
|
|
|
287
341
|
|
|
288
342
|
Obviously, you can just write regular Markdown here as well.
|
|
289
343
|
|
|
290
|
-
### `.nextLine()`
|
|
291
|
-
|
|
292
|
-
Prevents the next block element or `write()` call from adding a paragraph break. Useful for placing content on consecutive lines.
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
write('Line 1').nextLine().write('Line 2').toString();
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
Output:
|
|
299
|
-
|
|
300
|
-
```markdown
|
|
301
|
-
Line 1
|
|
302
|
-
Line 2
|
|
303
|
-
```
|
|
304
|
-
|
|
305
344
|
### `.unorderedList(...items: string[] | number[] | boolean[] | ProseWriter[])`
|
|
306
345
|
|
|
307
346
|
### `.list(...items: string[] | number[] | boolean[] | ProseWriter[])`
|
|
@@ -785,21 +824,6 @@ Output:
|
|
|
785
824
|
Use the `calculateTotal` function.
|
|
786
825
|
```
|
|
787
826
|
|
|
788
|
-
### `.fill(variables: Record<string, string>)`
|
|
789
|
-
|
|
790
|
-
Replaces template variables in the format `{{variableName}}` with provided values. Returns a new `ProseWriter` with the substitutions applied (does not modify the original).
|
|
791
|
-
|
|
792
|
-
```typescript
|
|
793
|
-
const template = write('Hello, {{name}}! Welcome to {{place}}.');
|
|
794
|
-
const result = template.fill({ name: 'Alice', place: 'Wonderland' }).toString();
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
Output:
|
|
798
|
-
|
|
799
|
-
```markdown
|
|
800
|
-
Hello, Alice! Welcome to Wonderland.
|
|
801
|
-
```
|
|
802
|
-
|
|
803
827
|
### `.section(name: string, builder: (writer) => void, level?: 1-6)`
|
|
804
828
|
|
|
805
829
|
Creates a semantic section with a heading and content built by the builder function. The optional `level` parameter defaults to 2.
|
|
@@ -1265,17 +1289,6 @@ const conclusion = write('').heading(2, 'Conclusion').write('Summary');
|
|
|
1265
1289
|
const document = ProseWriter.join(intro, body, conclusion);
|
|
1266
1290
|
```
|
|
1267
1291
|
|
|
1268
|
-
### `ProseWriter.fromTemplate(template: string)`
|
|
1269
|
-
|
|
1270
|
-
Static method that creates a ProseWriter from a template string.
|
|
1271
|
-
|
|
1272
|
-
```typescript
|
|
1273
|
-
const prompt = ProseWriter.fromTemplate('Hello {{name}}, your role is {{role}}.').fill({
|
|
1274
|
-
name: 'Alice',
|
|
1275
|
-
role: 'developer',
|
|
1276
|
-
});
|
|
1277
|
-
```
|
|
1278
|
-
|
|
1279
1292
|
### `.toString()`
|
|
1280
1293
|
|
|
1281
1294
|
Converts the accumulated prose to a string.
|
|
@@ -1402,48 +1415,13 @@ const userPrompt = write('Please review the following code:')
|
|
|
1402
1415
|
.toString();
|
|
1403
1416
|
```
|
|
1404
1417
|
|
|
1405
|
-
## Prompt
|
|
1418
|
+
## Prompt Variations
|
|
1406
1419
|
|
|
1407
|
-
Use `
|
|
1420
|
+
Use `clone()` to create variations without mutating the original prompt:
|
|
1408
1421
|
|
|
1409
1422
|
```typescript
|
|
1410
1423
|
import { write } from 'prose-writer';
|
|
1411
1424
|
|
|
1412
|
-
// Create a reusable template
|
|
1413
|
-
const promptTemplate = write('You are a {{role}}.')
|
|
1414
|
-
.section('Task', (w) => {
|
|
1415
|
-
w.write('Help the user with {{task}}.');
|
|
1416
|
-
})
|
|
1417
|
-
.section('Guidelines', (w) => {
|
|
1418
|
-
w.list('Be {{style}}', 'Focus on {{focus}}');
|
|
1419
|
-
})
|
|
1420
|
-
.section('Output', (w) => {
|
|
1421
|
-
w.table(
|
|
1422
|
-
['Format', 'When to use'],
|
|
1423
|
-
[
|
|
1424
|
-
['Code blocks', 'For code examples'],
|
|
1425
|
-
['Bullet points', 'For lists of items'],
|
|
1426
|
-
['Tables', 'For structured data'],
|
|
1427
|
-
],
|
|
1428
|
-
);
|
|
1429
|
-
});
|
|
1430
|
-
|
|
1431
|
-
// Create variations for different use cases
|
|
1432
|
-
const codeReviewPrompt = promptTemplate.fill({
|
|
1433
|
-
role: 'senior software engineer',
|
|
1434
|
-
task: 'code review',
|
|
1435
|
-
style: 'thorough and constructive',
|
|
1436
|
-
focus: 'code quality and best practices',
|
|
1437
|
-
});
|
|
1438
|
-
|
|
1439
|
-
const debuggingPrompt = promptTemplate.fill({
|
|
1440
|
-
role: 'debugging expert',
|
|
1441
|
-
task: 'finding and fixing bugs',
|
|
1442
|
-
style: 'systematic and methodical',
|
|
1443
|
-
focus: 'root cause analysis',
|
|
1444
|
-
});
|
|
1445
|
-
|
|
1446
|
-
// Or use clone() for structural variations
|
|
1447
1425
|
const basePrompt = write('You are an AI assistant.').section('Core Guidelines', (w) => {
|
|
1448
1426
|
w.list('Be helpful', 'Be accurate');
|
|
1449
1427
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
class T{value;constructor(F){this.value=F}toString(){return this.value}valueOf(){return this.value}}var k=(F)=>F.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"),S=(F)=>{if(/^\s*#{1,6}\s/.test(F))return F.replace(/^(\s*)(#{1,6})/,"$1\\$2");if(/^\s*>/.test(F))return F.replace(/^(\s*)>/,"$1\\>");if(/^\s*([-+*])\s/.test(F))return F.replace(/^(\s*)([-+*])/,"$1\\$2");if(/^\s*\d+\.\s/.test(F))return F.replace(/^(\s*)(\d+)\./,"$1$2\\.");return F},Z=(F)=>{return k(F).replace(/([\\`*_~()|!])/g,"\\$1").replace(/\[/g,"\\[").replace(/\]/g,"\\]").split(`
|
|
3
3
|
`).map((G)=>S(G)).join(`
|
|
4
|
-
`)},W=(F)=>{let H=F.match(/`+/g),G=(H?Math.max(...H.map((O)=>O.length)):0)+1,J="`".repeat(G),
|
|
4
|
+
`)},W=(F)=>{let H=F.match(/`+/g),G=(H?Math.max(...H.map((O)=>O.length)):0)+1,J="`".repeat(G),N=/^\s|\s$/.test(F)?` ${F} `:F;return`${J}${N}${J}`},h=(F)=>{return encodeURI(F).replace(/[()]/g,"\\$&")},q=(F,H="none")=>{if(F instanceof T)return{value:F.toString(),isTrusted:!0};if(F instanceof Q){let G=F.toString();if(H==="end")return{value:G.trimEnd(),isTrusted:!0};if(H==="both")return{value:G.trim(),isTrusted:!0};return{value:G,isTrusted:!0}}return{value:String(F),isTrusted:!1}},b=(F)=>{let{value:H,isTrusted:G}=q(F,"both");return G?H:Z(H)},z=(F)=>new T(F),X=(F)=>z(`**${b(F)}**`),D=(F)=>z(`*${b(F)}*`),j=(F)=>z(`~~${b(F)}~~`),A=(F)=>{let{value:H}=q(F,"both");return z(W(H))},E=(F,H)=>{let{value:G,isTrusted:J}=q(F,"both"),K=J?G:Z(G),N=h(H);return z(`[${K}](${N})`)},L=(F,H)=>{let{value:G,isTrusted:J}=q(F,"both"),K=J?G:Z(G),N=h(H);return z(``)},v=(F)=>{if(F.length===0)return"No validation issues were provided.";return F.map((H,G)=>{let J=H.path?`${H.path}: `:"";return`${G+1}. ${J}${H.message}`}).join(`
|
|
5
5
|
`)};class R extends Error{format;issues;constructor(F,H,G){let J=G??`${F.toUpperCase()} validation failed`;super(`${J}
|
|
6
6
|
${v(H)}`);this.name="ValidationError",this.format=F,this.issues=H}}var p=(F)=>{return({format:H,data:G,schema:J})=>{if(H!=="json"||J===void 0)return{valid:!0};return F(J,G)}},m=(F)=>{return(H)=>F(H)};class Q{parts=[];_skipNextPadding=!1;safeMode;constructor(F,H={}){if(this.safeMode=H.safe??!1,F!==void 0)this.parts.push(F.endsWith(`
|
|
7
7
|
`)?F:F+`
|
|
8
|
-
`)}createChildWriter(){return new Q(void 0,{safe:this.safeMode})}write(...F){let H=F.map((J)=>{let{value:
|
|
9
|
-
`),this}
|
|
8
|
+
`)}createChildWriter(){return new Q(void 0,{safe:this.safeMode})}write(...F){let H=F.map((J)=>{let{value:K,isTrusted:N}=q(J,"end");if(this.safeMode&&!N)return Z(K);return K}).join(" ");if(this.parts.length===0&&H.length===0)return this;let G=this.padding;return this.parts.push(G+H+`
|
|
9
|
+
`),this}unorderedList(...F){if(F.length===1&&typeof F[0]==="function"){let{builder:J,getItems:K}=this.createListBuilder();F[0](J);let O=K().map((Y)=>{if(Y instanceof Q)return Y.toString().trimEnd().split(`
|
|
10
10
|
`).map((_)=>` ${_}`).join(`
|
|
11
11
|
`);return`- ${Y}`}).join(`
|
|
12
12
|
`);return this.parts.push(`${this.padding}${O}
|
|
13
13
|
|
|
14
14
|
`),this}let G=F.map((J)=>{if(J instanceof Q)return J.toString().trimEnd().split(`
|
|
15
15
|
`).map((Y)=>` ${Y}`).join(`
|
|
16
|
-
`);let{value:
|
|
16
|
+
`);let{value:K,isTrusted:N}=q(J);return`- ${this.safeMode&&!N?Z(K):K}`}).join(`
|
|
17
17
|
`);return this.parts.push(`${this.padding}${G}
|
|
18
18
|
|
|
19
|
-
`),this}list(...F){if(F.length===1&&typeof F[0]==="function")return this.unorderedList(F[0]);return this.unorderedList(...F)}orderedList(...F){if(F.length===1&&typeof F[0]==="function"){let{builder:
|
|
19
|
+
`),this}list(...F){if(F.length===1&&typeof F[0]==="function")return this.unorderedList(F[0]);return this.unorderedList(...F)}orderedList(...F){if(F.length===1&&typeof F[0]==="function"){let{builder:K,getItems:N}=this.createListBuilder();F[0](K);let O=1,_=N().map(($)=>{if($ instanceof Q)return $.toString().trimEnd().split(`
|
|
20
20
|
`).map((U)=>` ${U}`).join(`
|
|
21
21
|
`);return`${O++}. ${$}`}).join(`
|
|
22
22
|
`);return this.parts.push(`${this.padding}${_}
|
|
23
23
|
|
|
24
|
-
`),this}let H=1,J=F.map((
|
|
24
|
+
`),this}let H=1,J=F.map((K)=>{if(K instanceof Q)return K.toString().trimEnd().split(`
|
|
25
25
|
`).map((_)=>` ${_}`).join(`
|
|
26
|
-
`);let{value:
|
|
26
|
+
`);let{value:N,isTrusted:O}=q(K),Y=this.safeMode&&!O?Z(N):N;return`${H++}. ${Y}`}).join(`
|
|
27
27
|
`);return this.parts.push(`${this.padding}${J}
|
|
28
28
|
|
|
29
|
-
`),this}tasks(...F){if(F.length===1&&typeof F[0]==="function"){let{builder:J,getItems:
|
|
29
|
+
`),this}tasks(...F){if(F.length===1&&typeof F[0]==="function"){let{builder:J,getItems:K}=this.createListBuilder();F[0](J);let O=K().map((Y)=>{if(Y instanceof Q)return Y.toString().trimEnd().split(`
|
|
30
30
|
`).map((_)=>` ${_}`).join(`
|
|
31
31
|
`);return`- ${Y}`}).join(`
|
|
32
32
|
`);return this.parts.push(`${this.padding}${O}
|
|
33
33
|
|
|
34
|
-
`),this}let G=F.map((J)=>{if(Array.isArray(J)&&J.length===2&&typeof J[1]==="boolean"){let[O,Y]=J,_=Y?"[x] ":"[ ] ",$=this.createChildWriter().write(O).toString().trimEnd();return _+$}let
|
|
34
|
+
`),this}let G=F.map((J)=>{if(Array.isArray(J)&&J.length===2&&typeof J[1]==="boolean"){let[O,Y]=J,_=Y?"[x] ":"[ ] ",$=this.createChildWriter().write(O).toString().trimEnd();return _+$}let K="[ ] ",N=this.createChildWriter().write(J).toString().trimEnd();return K+N}).map((J)=>`- ${J}`).join(`
|
|
35
35
|
`);return this.parts.push(`${this.padding}${G}
|
|
36
36
|
|
|
37
37
|
`),this}callout(F,H){let G;if(typeof H==="function"){let O=this.createChildWriter();H(O.enhanced),G=O.toString().trimEnd()}else{let{value:O,isTrusted:Y}=q(H);G=this.safeMode&&!Y?Z(O):O}let J=G.split(`
|
|
38
|
-
`),
|
|
39
|
-
`);return this.parts.push(`${this.padding}${
|
|
38
|
+
`),N=[`[!${F.toUpperCase()}]`,...J].map((O)=>`> ${O}`).join(`
|
|
39
|
+
`);return this.parts.push(`${this.padding}${N}
|
|
40
40
|
|
|
41
|
-
`),this}heading(F,...H){let G="#".repeat(F),J=H.map((
|
|
41
|
+
`),this}heading(F,...H){let G="#".repeat(F),J=H.map((K)=>{let{value:N,isTrusted:O}=q(K);if(this.safeMode&&!O)return Z(N);return N}).join(" ");return this.parts.push(`${this.padding}${G} ${J}
|
|
42
42
|
|
|
43
|
-
`),this}blockquote(...F){let H=F.map((G)=>{let{value:J,isTrusted:
|
|
43
|
+
`),this}blockquote(...F){let H=F.map((G)=>{let{value:J,isTrusted:K}=q(G);if(this.safeMode&&!K)return Z(J);return J}).map((G)=>`> ${G}`).join(`
|
|
44
44
|
>
|
|
45
45
|
`);return this.parts.push(`${this.padding}${H}
|
|
46
46
|
|
|
@@ -50,31 +50,31 @@ ${G}
|
|
|
50
50
|
|
|
51
51
|
`),this}get separator(){return this.parts.push(`${this.padding}---
|
|
52
52
|
|
|
53
|
-
`),this}json(F,H={}){this.validateOutput("json",F,H);let G=typeof F==="string"?F:JSON.stringify(F,null,2);return this.codeblock("json",G)}append(F){let H=F.toString();if(H.length>0)this.parts.push(this.padding+H);return this}get enhanced(){let F=this.safeMode?{bold:X,italic:D,code:A,inline:A,link:E,strike:j,image:L}:{bold:y,italic:
|
|
53
|
+
`),this}json(F,H={}){this.validateOutput("json",F,H);let G=typeof F==="string"?F:JSON.stringify(F,null,2);return this.codeblock("json",G)}append(F){let H=F.toString();if(H.length>0)this.parts.push(this.padding+H);return this}get enhanced(){let F=this.safeMode?{bold:X,italic:D,code:A,inline:A,link:E,strike:j,image:L}:{bold:y,italic:M,code:B,inline:P,link:I,strike:V,image:C};return new Proxy(this,{get(H,G){if(typeof G==="string"&&G in F)return F[G];let J=Reflect.get(H,G,H);if(typeof J==="function")return J.bind(H);return J}})}when(F,H){if(F)H(this.enhanced);return this}with(F){return F(this.enhanced),this}tag(F,H){let G;if(typeof H==="function"){let J=this.createChildWriter();H(J.enhanced),G=J.toString()}else{let{value:J,isTrusted:K}=q(H);if(this.safeMode&&!K)G=k(J);else G=J}return this.parts.push(`${this.padding}<${F}>
|
|
54
54
|
${G.trimEnd()}
|
|
55
55
|
</${F}>
|
|
56
56
|
`),this}code(F){let H=this.safeMode?A(F):B(F);return this.parts.push(this.padding+H+`
|
|
57
|
-
`),this}
|
|
57
|
+
`),this}section(F,H,G=2){let J=this.createChildWriter();H(J.enhanced);let K="#".repeat(G),N=this.safeMode?Z(F):F;return this.parts.push(`${this.padding}${K} ${N}
|
|
58
58
|
|
|
59
|
-
${J.toString()}`),this}clone(){let F=new Q(void 0,{safe:this.safeMode});return F.parts=[...this.parts],F}table(F,H){let J=`| ${(this.safeMode?F.map((O)=>Z(O)):F).join(" | ")} |`,
|
|
59
|
+
${J.toString()}`),this}clone(){let F=new Q(void 0,{safe:this.safeMode});return F.parts=[...this.parts],F}table(F,H){let J=`| ${(this.safeMode?F.map((O)=>Z(O)):F).join(" | ")} |`,K=`| ${F.map(()=>"---").join(" | ")} |`,N=H.map((O)=>{return`| ${(Array.isArray(O)?O.map((_)=>{let $=String(_??"");return this.safeMode?Z($):$}):F.map((_)=>{let $=O[_];if($ instanceof Q)return $.toPlainText();let U=String($??"");return this.safeMode?Z(U):U})).join(" | ")} |`}).join(`
|
|
60
60
|
`);return this.parts.push(`${this.padding}${J}
|
|
61
|
-
${N}
|
|
62
61
|
${K}
|
|
62
|
+
${N}
|
|
63
63
|
|
|
64
64
|
`),this}definitions(F){let H=Object.entries(F).map(([G,J])=>{if(this.safeMode)return`${X(G)}: ${Z(J)}`;return`**${G}**: ${J}`}).join(`
|
|
65
65
|
`);return this.parts.push(`${this.padding}${H}
|
|
66
66
|
|
|
67
|
-
`),this}schema(F,H={}){let{format:G="json",title:J,level:
|
|
68
|
-
`),this}italic(F){let H=this.safeMode?D(F):
|
|
69
|
-
`),this}strike(F){let H=this.safeMode?j(F):
|
|
70
|
-
`),this}raw(F){return this.parts.push(F),this}link(F,H){let G=this.safeMode?E(F,H):
|
|
67
|
+
`),this}schema(F,H={}){let{format:G="json",title:J,level:K=2,tag:N}=H;if(J)this.heading(K,J);if(N){let O=this.createChildWriter();if(G==="json")O.json(F);else O.yaml(F);return this.tag(N,O)}if(G==="json")return this.json(F);return this.yaml(F)}bold(F){let H=this.safeMode?X(F):y(F);return this.parts.push(this.padding+H+`
|
|
68
|
+
`),this}italic(F){let H=this.safeMode?D(F):M(F);return this.parts.push(this.padding+H+`
|
|
69
|
+
`),this}strike(F){let H=this.safeMode?j(F):V(F);return this.parts.push(this.padding+H+`
|
|
70
|
+
`),this}raw(F){return this.parts.push(F),this}link(F,H){let G=this.safeMode?E(F,H):I(F,H);return this.parts.push(this.padding+G+`
|
|
71
71
|
`),this}image(F,H){let G=this.safeMode?L(F,H):C(F,H);return this.parts.push(this.padding+G+`
|
|
72
72
|
`),this}comment(F){return this.parts.push(`${this.padding}<!-- ${F} -->
|
|
73
73
|
|
|
74
74
|
`),this}yaml(F,H={}){this.validateOutput("yaml",F,H);let G=typeof F==="string"?F:this.toYamlString(F);return this.codeblock("yaml",G)}toYamlString(F,H=0){let G=" ".repeat(H);if(F===null||F===void 0)return"null";if(typeof F==="string"){if(/[:\n#"']/.test(F)||F==="")return`"${F.replace(/"/g,"\\\"")}"`;return F}if(typeof F==="number"||typeof F==="boolean")return String(F);if(Array.isArray(F)){if(F.length===0)return"[]";return F.map((J)=>`${G}- ${this.toYamlString(J,H+1)}`).join(`
|
|
75
|
-
`)}if(typeof F==="object"){let J=Object.entries(F);if(J.length===0)return"{}";return J.map(([N
|
|
76
|
-
${O}`;if(Array.isArray(
|
|
77
|
-
${O}`;return`${G}${
|
|
75
|
+
`)}if(typeof F==="object"){let J=Object.entries(F);if(J.length===0)return"{}";return J.map(([K,N])=>{let O=this.toYamlString(N,H+1);if(typeof N==="object"&&N!==null&&!Array.isArray(N))return`${G}${K}:
|
|
76
|
+
${O}`;if(Array.isArray(N))return`${G}${K}:
|
|
77
|
+
${O}`;return`${G}${K}: ${O}`}).join(`
|
|
78
78
|
`)}return JSON.stringify(F)??"null"}delimit(F,H,G){let J=G instanceof Q?G.toString():G;return this.parts.push(`${this.padding}${F}
|
|
79
79
|
${J}
|
|
80
80
|
${H}
|
|
@@ -84,12 +84,12 @@ ${H}
|
|
|
84
84
|
`).slice(1,-1).join(`
|
|
85
85
|
`)}),F=F.replace(/`([^`]+)`/g,"$1"),F=F.replace(/^#{1,6}\s+(.*)$/gm,"$1"),F=F.replace(/\*\*([^*]+)\*\*/g,"$1"),F=F.replace(/\*([^*]+)\*/g,"$1"),F=F.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),F=F.replace(/^>\s?/gm,""),F=F.replace(/^---$/gm,""),F=F.replace(/^[-*]\s+/gm,""),F=F.replace(/^\d+\.\s+/gm,""),F=F.replace(/<[^>]+>/g,""),F=F.replace(/\|/g," "),F=F.replace(/^[\s-]+$/gm,""),F=F.replace(/ {2,}/g," "),F=F.replace(/\n{3,}/g,`
|
|
86
86
|
|
|
87
|
-
`),F.trim()}validateOutput(F,H,G){if(!G.validate)return;let J=H;if(F==="json"&&typeof H==="string")try{J=JSON.parse(H)}catch(
|
|
87
|
+
`),F.trim()}validateOutput(F,H,G){if(!G.validate)return;let J=H;if(F==="json"&&typeof H==="string")try{J=JSON.parse(H)}catch(N){let O=N instanceof Error?N.message:"Invalid JSON string";throw new R(F,[{path:"$",message:`Invalid JSON string: ${O}`}],G.label)}if(F==="yaml"&&typeof H==="string"&&G.parseYaml)try{J=G.parseYaml(H)}catch(N){let O=N instanceof Error?N.message:"Invalid YAML string";throw new R(F,[{path:"$",message:`Invalid YAML string: ${O}`}],G.label)}let K=G.validate({format:F,data:J,schema:G.schema});if(K.valid)return;throw new R(F,K.issues??[],G.label)}get padding(){if(this._skipNextPadding||this.parts.length===0)return this._skipNextPadding=!1,"";let F=this.parts[this.parts.length-1];if(F.endsWith(`
|
|
88
88
|
|
|
89
89
|
`))return"";if(F.endsWith(`
|
|
90
90
|
`))return`
|
|
91
91
|
`;return`
|
|
92
92
|
|
|
93
|
-
`}createListBuilder(){let F=[],H={item:(...G)=>{return F.push(this.createChildWriter().write(...G).toString().trimEnd()),H},task:(G,...J)=>{let
|
|
93
|
+
`}createListBuilder(){let F=[],H={item:(...G)=>{return F.push(this.createChildWriter().write(...G).toString().trimEnd()),H},task:(G,...J)=>{let K=G?"[x] ":"[ ] ",N=this.createChildWriter().write(...J).toString().trimEnd();return F.push(K+N),H},todo:(...G)=>H.task(!1,...G),done:(...G)=>H.task(!0,...G),unorderedList:(...G)=>{let J=this.createChildWriter();if(G.length===1&&typeof G[0]==="function")J.unorderedList(G[0]);else J.unorderedList(...G);return F.push(J),H},list:(...G)=>{let J=this.createChildWriter();if(G.length===1&&typeof G[0]==="function")J.list(G[0]);else J.list(...G);return F.push(J),H},orderedList:(...G)=>{let J=this.createChildWriter();if(G.length===1&&typeof G[0]==="function")J.orderedList(G[0]);else J.orderedList(...G);return F.push(J),H},comment:(G)=>{let J=this.createChildWriter();return J.comment(G),F.push(J),H},bold:this.safeMode?X:y,italic:this.safeMode?D:M,code:this.safeMode?A:B,inline:this.safeMode?A:P,strike:this.safeMode?j:V,link:this.safeMode?E:I,image:this.safeMode?L:C};return{builder:H,getItems:()=>F}}static empty(){return new Q}static join(...F){let H=new Q;for(let G of F)H.parts.push(G.toString());return H}toString(){return this.parts.join("")}[Symbol.toPrimitive](F){if(F==="number")return Number.NaN;return this.toString()}get[Symbol.toStringTag](){return"ProseWriter"}}var w=(F)=>{let H=()=>new Q(void 0,{safe:F});return Object.assign((...G)=>{return H().write(...G)},{with:(G)=>{return H().with(G)},unorderedList:(...G)=>{let J=H();if(G.length===1&&typeof G[0]==="function")return J.unorderedList(G[0]);return J.unorderedList(...G)},list:(...G)=>{let J=H();if(G.length===1&&typeof G[0]==="function")return J.list(G[0]);return J.list(...G)},orderedList:(...G)=>{let J=H();if(G.length===1&&typeof G[0]==="function")return J.orderedList(G[0]);return J.orderedList(...G)},tasks:(...G)=>{let J=H();if(G.length===1&&typeof G[0]==="function")return J.tasks(G[0]);return J.tasks(...G)},callout:(G,J)=>{return H().callout(G,J)},schema:(G,J)=>{return H().schema(G,J)}})},f=w(!0),x=Object.assign(w(!1),{safe:f}),y=(F)=>`**${F instanceof Q?F.toString().trim():F}**`,M=(F)=>`*${F instanceof Q?F.toString().trim():F}*`,B=(F)=>`\`${F instanceof Q?F.toString().trim():F}\``,P=B,V=(F)=>`~~${F instanceof Q?F.toString().trim():F}~~`,I=(F,H)=>`[${F instanceof Q?F.toString().trim():F}](${H})`,C=(F,H)=>``;export{x as write,Q as ProseWriter};
|
|
94
94
|
|
|
95
|
-
//# debugId=
|
|
95
|
+
//# debugId=D534BE926E580A2464756E2164756E21
|