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 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
- **prose-writer** fixes this:
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
- .fill({ language: 'TypeScript', framework: 'React' });
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 multiLine = write('First line').write('Second line').toString();
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 a blank line between paragraphs:
273
+ Adding an extra blank line between paragraphs:
232
274
 
233
275
  ```typescript
234
- const multiParagraph = write('Paragraph 1').write().write('Paragraph 2').toString();
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. Returns `this` for chaining.
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 Templates and Variations
1418
+ ## Prompt Variations
1406
1419
 
1407
- Use `fill()` for variable interpolation and `clone()` to create prompt variations:
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,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),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),K=/^\s|\s$/.test(F)?` ${F} `:F;return`${J}${K}${J}`},P=(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"),N=J?G:Z(G),K=P(H);return z(`[${N}](${K})`)},L=(F,H)=>{let{value:G,isTrusted:J}=q(F,"both"),N=J?G:Z(G),K=P(H);return z(`![${N}](${K})`)},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(`
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(`![${K}](${N})`)},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:N,isTrusted:K}=q(J,"end");if(this.safeMode&&!K)return Z(N);return N}).join(" ");if(this.parts.length===0&&H.length===0)return this;let G=this.padding;return this.parts.push(G+H+`
9
- `),this}nextLine(){return this._skipNextPadding=!0,this}unorderedList(...F){if(F.length===1&&typeof F[0]==="function"){let{builder:J,getItems:N}=this.createListBuilder();F[0](J);let O=N().map((Y)=>{if(Y instanceof Q)return Y.toString().trimEnd().split(`
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:N,isTrusted:K}=q(J);return`- ${this.safeMode&&!K?Z(N):N}`}).join(`
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:N,getItems:K}=this.createListBuilder();F[0](N);let O=1,_=K().map(($)=>{if($ instanceof Q)return $.toString().trimEnd().split(`
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((N)=>{if(N instanceof Q)return N.toString().trimEnd().split(`
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:K,isTrusted:O}=q(N),Y=this.safeMode&&!O?Z(K):K;return`${H++}. ${Y}`}).join(`
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:N}=this.createListBuilder();F[0](J);let O=N().map((Y)=>{if(Y instanceof Q)return Y.toString().trimEnd().split(`
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 N="[ ] ",K=this.createChildWriter().write(J).toString().trimEnd();return N+K}).map((J)=>`- ${J}`).join(`
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
- `),K=[`[!${F.toUpperCase()}]`,...J].map((O)=>`> ${O}`).join(`
39
- `);return this.parts.push(`${this.padding}${K}
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((N)=>{let{value:K,isTrusted:O}=q(N);if(this.safeMode&&!O)return Z(K);return K}).join(" ");return this.parts.push(`${this.padding}${G} ${J}
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:N}=q(G);if(this.safeMode&&!N)return Z(J);return J}).map((G)=>`> ${G}`).join(`
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:V,code:B,inline:h,link:M,strike:I,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:N}=q(H);if(this.safeMode&&!N)G=k(J);else G=J}return this.parts.push(`${this.padding}<${F}>
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}fill(F){let G=this.toString().replace(/\{\{(\w+)\}\}/g,(J,N)=>{let K=F[N];if(K===void 0)return J;return this.safeMode?Z(K):K});return new Q(G,{safe:this.safeMode})}section(F,H,G=2){let J=this.createChildWriter();H(J.enhanced);let N="#".repeat(G),K=this.safeMode?Z(F):F;return this.parts.push(`${this.padding}${N} ${K}
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(" | ")} |`,N=`| ${F.map(()=>"---").join(" | ")} |`,K=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(`
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:N=2,tag:K}=H;if(J)this.heading(N,J);if(K){let O=this.createChildWriter();if(G==="json")O.json(F);else O.yaml(F);return this.tag(K,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):V(F);return this.parts.push(this.padding+H+`
69
- `),this}strike(F){let H=this.safeMode?j(F):I(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):M(F,H);return this.parts.push(this.padding+G+`
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,K])=>{let O=this.toYamlString(K,H+1);if(typeof K==="object"&&K!==null&&!Array.isArray(K))return`${G}${N}:
76
- ${O}`;if(Array.isArray(K))return`${G}${N}:
77
- ${O}`;return`${G}${N}: ${O}`}).join(`
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(K){let O=K instanceof Error?K.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(K){let O=K instanceof Error?K.message:"Invalid YAML string";throw new R(F,[{path:"$",message:`Invalid YAML string: ${O}`}],G.label)}let N=G.validate({format:F,data:J,schema:G.schema});if(N.valid)return;throw new R(F,N.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(`
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 N=G?"[x] ":"[ ] ",K=this.createChildWriter().write(...J).toString().trimEnd();return F.push(N+K),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:V,code:this.safeMode?A:B,inline:this.safeMode?A:h,strike:this.safeMode?j:I,link:this.safeMode?E:M,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}static fromTemplate(F){return new Q(F)}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)},template:(G)=>{if(F)return H().write(z(G));return H().write(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}**`,V=(F)=>`*${F instanceof Q?F.toString().trim():F}*`,B=(F)=>`\`${F instanceof Q?F.toString().trim():F}\``,h=B,I=(F)=>`~~${F instanceof Q?F.toString().trim():F}~~`,M=(F,H)=>`[${F instanceof Q?F.toString().trim():F}](${H})`,C=(F,H)=>`![${F instanceof Q?F.toString().trim():F}](${H})`;export{x as write,Q as ProseWriter};
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)=>`![${F instanceof Q?F.toString().trim():F}](${H})`;export{x as write,Q as ProseWriter};
94
94
 
95
- //# debugId=ECE9ECE86506912164756E2164756E21
95
+ //# debugId=D534BE926E580A2464756E2164756E21