@promptlycms/prompts 0.5.0 → 0.6.0-canary.af507c4

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
@@ -171,6 +171,13 @@ const output = formatComposer({
171
171
  });
172
172
  ```
173
173
 
174
+ Prompt results are treated as text by default. Newlines in strings or `{ text }`
175
+ results are preserved as `<br>` tags when the composer output is assembled. If
176
+ text prompt output is placed in its own rich-text paragraph, the SDK also keeps
177
+ the visible paragraph gap in email-safe HTML. If a prompt result already
178
+ contains trusted HTML, pass `{ html: '<p>...</p>' }` to `formatComposer()` to
179
+ insert it without newline conversion.
180
+
174
181
  Batch fetch multiple composers in parallel:
175
182
 
176
183
  ```typescript
@@ -198,6 +205,9 @@ for (const segment of composer.segments) {
198
205
 
199
206
  Variable references inside an `html_block` (e.g. `<span data-variable-ref data-field-path="country">`) are interpolated normally during `formatComposer()` / `compose()`. Embedded prompt references inside an `html_block` are passed through opaquely — they aren't resolved as named prompts.
200
207
 
208
+ HTML blocks are otherwise left raw, including whitespace, comments, and empty
209
+ paragraphs.
210
+
201
211
  ## Model auto-detection
202
212
 
203
213
  The SDK automatically resolves models configured in the CMS to the correct AI SDK provider based on the model name prefix:
package/dist/index.cjs CHANGED
@@ -186,6 +186,31 @@ var toCamelCase = (name) => name.replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.
186
186
  var VARIABLE_REF_REGEX = /<span[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*\sdata-field-path="([^"]+)"[^>]*><\/span>/g;
187
187
  var VARIABLE_REF_ALT_REGEX = /<span[^>]*\sdata-field-path="([^"]+)"[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*><\/span>/g;
188
188
  var MUSTACHE_REGEX = /\{\{(\w[\w.]*)\}\}/g;
189
+ var EMPTY_PARAGRAPH_REGEX = /<p(\s[^>]*)?>\s*<\/p>/gi;
190
+ var preserveEmptyParagraphs = (content) => content.replace(
191
+ EMPTY_PARAGRAPH_REGEX,
192
+ (_, attributes) => `<p${attributes ?? ""}><br></p>`
193
+ );
194
+ var preserveTextLineBreaks = (content) => content.replace(/\r\n?/g, "\n").replaceAll("\n", "<br>");
195
+ var isHtmlFormatInput = (input) => typeof input === "object" && input !== null && "html" in input;
196
+ var formatComposerInput = (input) => {
197
+ if (typeof input === "string") {
198
+ return preserveTextLineBreaks(input);
199
+ }
200
+ if (isHtmlFormatInput(input)) {
201
+ return input.html;
202
+ }
203
+ return preserveTextLineBreaks(input.text);
204
+ };
205
+ var STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX = /<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
206
+ var STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX = /^\s*<\/p>/i;
207
+ var EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX = /<p(?:\s[^>]*)?>\s*<br\s*\/?>\s*<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
208
+ var shouldPrefixStandalonePromptText = (previous, next) => {
209
+ if (previous?.type !== "static" || next?.type !== "static") {
210
+ return false;
211
+ }
212
+ return STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX.test(previous.content) && STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX.test(next.content) && !EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX.test(previous.content);
213
+ };
189
214
  var interpolateStaticSegment = (content, input) => {
190
215
  let result = content;
191
216
  result = result.replace(
@@ -271,7 +296,9 @@ var createPromptlyClient = (config) => {
271
296
  if (segment.type === "static") {
272
297
  processedSegments.push({
273
298
  type: "static",
274
- content: interpolateStaticSegment(segment.content, input)
299
+ content: preserveEmptyParagraphs(
300
+ interpolateStaticSegment(segment.content, input)
301
+ )
275
302
  });
276
303
  continue;
277
304
  }
@@ -303,7 +330,7 @@ var createPromptlyClient = (config) => {
303
330
  }
304
331
  const formatComposer = (results) => {
305
332
  const parts = [];
306
- for (const seg of processedSegments) {
333
+ for (const [index, seg] of processedSegments.entries()) {
307
334
  if (seg.type === "static") {
308
335
  parts.push(seg.content);
309
336
  continue;
@@ -312,7 +339,12 @@ var createPromptlyClient = (config) => {
312
339
  if (val === void 0) {
313
340
  continue;
314
341
  }
315
- parts.push(typeof val === "string" ? val : val.text);
342
+ const formattedInput = formatComposerInput(val);
343
+ const prefix = isHtmlFormatInput(val) || !shouldPrefixStandalonePromptText(
344
+ processedSegments[index - 1],
345
+ processedSegments[index + 1]
346
+ ) ? "" : "<br>";
347
+ parts.push(`${prefix}${formattedInput}`);
316
348
  }
317
349
  return parts.join("");
318
350
  };
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DaIU82yN.cjs';
2
- export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerHtmlBlockSegment, e as ComposerId, f as ComposerInputFor, g as ComposerPrompt, h as ComposerPromptMap, i as ComposerPromptNamesFor, j as ComposerPromptSegment, k as ComposerRequest, l as ComposerResponse, m as ComposerResult, n as ComposerSegment, o as ComposerStaticSegment, p as ComposerVariableMap, q as ComposerVersion, r as ErrorResponse, F as FormatInput, G as GetComposerOptions, s as GetOptions, t as PromptConfig, u as PromptId, v as PromptMessage, w as PromptRequest, x as PromptResponse, y as PromptResult, z as PromptVariableMap, A as PromptVersion, B as PublishedVersion, S as SchemaField, D as SchemaFieldParams, V as ValidationRule } from './types-DaIU82yN.cjs';
1
+ import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-BStQVsgZ.cjs';
2
+ export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerHtmlBlockSegment, e as ComposerId, f as ComposerInputFor, g as ComposerPrompt, h as ComposerPromptMap, i as ComposerPromptNamesFor, j as ComposerPromptSegment, k as ComposerRequest, l as ComposerResponse, m as ComposerResult, n as ComposerSegment, o as ComposerStaticSegment, p as ComposerVariableMap, q as ComposerVersion, r as ErrorResponse, F as FormatInput, G as GetComposerOptions, s as GetOptions, t as PromptConfig, u as PromptId, v as PromptMessage, w as PromptRequest, x as PromptResponse, y as PromptResult, z as PromptVariableMap, A as PromptVersion, B as PublishedVersion, S as SchemaField, D as SchemaFieldParams, V as ValidationRule } from './types-BStQVsgZ.cjs';
3
3
  import 'ai';
4
4
 
5
5
  declare const getSdkModelId: (modelId: string) => string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-DaIU82yN.js';
2
- export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerHtmlBlockSegment, e as ComposerId, f as ComposerInputFor, g as ComposerPrompt, h as ComposerPromptMap, i as ComposerPromptNamesFor, j as ComposerPromptSegment, k as ComposerRequest, l as ComposerResponse, m as ComposerResult, n as ComposerSegment, o as ComposerStaticSegment, p as ComposerVariableMap, q as ComposerVersion, r as ErrorResponse, F as FormatInput, G as GetComposerOptions, s as GetOptions, t as PromptConfig, u as PromptId, v as PromptMessage, w as PromptRequest, x as PromptResponse, y as PromptResult, z as PromptVariableMap, A as PromptVersion, B as PublishedVersion, S as SchemaField, D as SchemaFieldParams, V as ValidationRule } from './types-DaIU82yN.js';
1
+ import { P as PromptlyClientConfig, a as PromptlyClient, E as ErrorCode } from './types-BStQVsgZ.js';
2
+ export { C as ComposerConfig, b as ComposerFormatFn, c as ComposerGenerateFn, d as ComposerHtmlBlockSegment, e as ComposerId, f as ComposerInputFor, g as ComposerPrompt, h as ComposerPromptMap, i as ComposerPromptNamesFor, j as ComposerPromptSegment, k as ComposerRequest, l as ComposerResponse, m as ComposerResult, n as ComposerSegment, o as ComposerStaticSegment, p as ComposerVariableMap, q as ComposerVersion, r as ErrorResponse, F as FormatInput, G as GetComposerOptions, s as GetOptions, t as PromptConfig, u as PromptId, v as PromptMessage, w as PromptRequest, x as PromptResponse, y as PromptResult, z as PromptVariableMap, A as PromptVersion, B as PublishedVersion, S as SchemaField, D as SchemaFieldParams, V as ValidationRule } from './types-BStQVsgZ.js';
3
3
  import 'ai';
4
4
 
5
5
  declare const getSdkModelId: (modelId: string) => string;
package/dist/index.js CHANGED
@@ -145,6 +145,31 @@ var toCamelCase = (name) => name.replace(/[^a-zA-Z0-9]+(.)/g, (_, char) => char.
145
145
  var VARIABLE_REF_REGEX = /<span[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*\sdata-field-path="([^"]+)"[^>]*><\/span>/g;
146
146
  var VARIABLE_REF_ALT_REGEX = /<span[^>]*\sdata-field-path="([^"]+)"[^>]*\sdata-variable-ref(?:="[^"]*")?[^>]*><\/span>/g;
147
147
  var MUSTACHE_REGEX = /\{\{(\w[\w.]*)\}\}/g;
148
+ var EMPTY_PARAGRAPH_REGEX = /<p(\s[^>]*)?>\s*<\/p>/gi;
149
+ var preserveEmptyParagraphs = (content) => content.replace(
150
+ EMPTY_PARAGRAPH_REGEX,
151
+ (_, attributes) => `<p${attributes ?? ""}><br></p>`
152
+ );
153
+ var preserveTextLineBreaks = (content) => content.replace(/\r\n?/g, "\n").replaceAll("\n", "<br>");
154
+ var isHtmlFormatInput = (input) => typeof input === "object" && input !== null && "html" in input;
155
+ var formatComposerInput = (input) => {
156
+ if (typeof input === "string") {
157
+ return preserveTextLineBreaks(input);
158
+ }
159
+ if (isHtmlFormatInput(input)) {
160
+ return input.html;
161
+ }
162
+ return preserveTextLineBreaks(input.text);
163
+ };
164
+ var STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX = /<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
165
+ var STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX = /^\s*<\/p>/i;
166
+ var EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX = /<p(?:\s[^>]*)?>\s*<br\s*\/?>\s*<\/p>\s*<p(?:\s[^>]*)?>\s*$/i;
167
+ var shouldPrefixStandalonePromptText = (previous, next) => {
168
+ if (previous?.type !== "static" || next?.type !== "static") {
169
+ return false;
170
+ }
171
+ return STANDALONE_PROMPT_OPEN_PARAGRAPH_REGEX.test(previous.content) && STANDALONE_PROMPT_CLOSE_PARAGRAPH_REGEX.test(next.content) && !EXPLICIT_SPACER_BEFORE_OPEN_PARAGRAPH_REGEX.test(previous.content);
172
+ };
148
173
  var interpolateStaticSegment = (content, input) => {
149
174
  let result = content;
150
175
  result = result.replace(
@@ -230,7 +255,9 @@ var createPromptlyClient = (config) => {
230
255
  if (segment.type === "static") {
231
256
  processedSegments.push({
232
257
  type: "static",
233
- content: interpolateStaticSegment(segment.content, input)
258
+ content: preserveEmptyParagraphs(
259
+ interpolateStaticSegment(segment.content, input)
260
+ )
234
261
  });
235
262
  continue;
236
263
  }
@@ -262,7 +289,7 @@ var createPromptlyClient = (config) => {
262
289
  }
263
290
  const formatComposer = (results) => {
264
291
  const parts = [];
265
- for (const seg of processedSegments) {
292
+ for (const [index, seg] of processedSegments.entries()) {
266
293
  if (seg.type === "static") {
267
294
  parts.push(seg.content);
268
295
  continue;
@@ -271,7 +298,12 @@ var createPromptlyClient = (config) => {
271
298
  if (val === void 0) {
272
299
  continue;
273
300
  }
274
- parts.push(typeof val === "string" ? val : val.text);
301
+ const formattedInput = formatComposerInput(val);
302
+ const prefix = isHtmlFormatInput(val) || !shouldPrefixStandalonePromptText(
303
+ processedSegments[index - 1],
304
+ processedSegments[index + 1]
305
+ ) ? "" : "<br>";
306
+ parts.push(`${prefix}${formattedInput}`);
275
307
  }
276
308
  return parts.join("");
277
309
  };
package/dist/schema.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { S as SchemaField } from './types-DaIU82yN.cjs';
2
+ import { S as SchemaField } from './types-BStQVsgZ.cjs';
3
3
  import 'ai';
4
4
 
5
5
  declare const buildFieldSchema: (field: SchemaField) => z.ZodTypeAny;
package/dist/schema.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { S as SchemaField } from './types-DaIU82yN.js';
2
+ import { S as SchemaField } from './types-BStQVsgZ.js';
3
3
  import 'ai';
4
4
 
5
5
  declare const buildFieldSchema: (field: SchemaField) => z.ZodTypeAny;
@@ -147,10 +147,10 @@ type ComposerPrompt = {
147
147
  };
148
148
  type FormatInput = {
149
149
  text: string;
150
+ } | {
151
+ html: string;
150
152
  } | string;
151
- type ComposerGenerateFn = (prompt: ComposerPrompt) => Promise<{
152
- text: string;
153
- } | string>;
153
+ type ComposerGenerateFn = (prompt: ComposerPrompt) => Promise<FormatInput>;
154
154
  type ComposerFormatFn<Names extends string = string> = (results: Record<Names, FormatInput>) => string;
155
155
  type ComposerResult<Names extends string = string> = {
156
156
  composerId: string;
@@ -147,10 +147,10 @@ type ComposerPrompt = {
147
147
  };
148
148
  type FormatInput = {
149
149
  text: string;
150
+ } | {
151
+ html: string;
150
152
  } | string;
151
- type ComposerGenerateFn = (prompt: ComposerPrompt) => Promise<{
152
- text: string;
153
- } | string>;
153
+ type ComposerGenerateFn = (prompt: ComposerPrompt) => Promise<FormatInput>;
154
154
  type ComposerFormatFn<Names extends string = string> = (results: Record<Names, FormatInput>) => string;
155
155
  type ComposerResult<Names extends string = string> = {
156
156
  composerId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptlycms/prompts",
3
- "version": "0.5.0",
3
+ "version": "0.6.0-canary.af507c4",
4
4
  "description": "TypeScript SDK for Promptly CMS — fetch prompts, build Zod schemas, generate typed code",
5
5
  "type": "module",
6
6
  "exports": {