storybook-addon-playwright 5.4.2 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -27,13 +27,20 @@ interface CreateScreenshotTitlePromptOptions {
27
27
  * @default false
28
28
  */
29
29
  includeStoryId?: boolean;
30
+ /**
31
+ * Additional instructions for the output format, appended to the prompt's output contract section.
32
+ *
33
+ * @default 'Return only the generated title as string, without any additional text or formatting.'
34
+ */
35
+ outputPrompt?: string | string[];
30
36
  }
37
+ type PartialContext = Partial<GenerateScreenshotTitleInput>;
31
38
  /**
32
39
  * Creates a strict prompt for LLMs to generate a screenshot title from Storybook data.
33
40
  *
34
41
  * The prompt enforces JSON-only output in the form:
35
42
  * `{"title":"..."}`.
36
43
  */
37
- declare function createScreenshotTitlePrompt(data: GenerateScreenshotTitleInput, options?: CreateScreenshotTitlePromptOptions): string;
44
+ declare function createScreenshotTitlePrompt(context: PartialContext, options?: CreateScreenshotTitlePromptOptions): string;
38
45
 
39
46
  export { type CreateScreenshotTitlePromptOptions, createScreenshotTitlePrompt };
@@ -27,13 +27,20 @@ interface CreateScreenshotTitlePromptOptions {
27
27
  * @default false
28
28
  */
29
29
  includeStoryId?: boolean;
30
+ /**
31
+ * Additional instructions for the output format, appended to the prompt's output contract section.
32
+ *
33
+ * @default 'Return only the generated title as string, without any additional text or formatting.'
34
+ */
35
+ outputPrompt?: string | string[];
30
36
  }
37
+ type PartialContext = Partial<GenerateScreenshotTitleInput>;
31
38
  /**
32
39
  * Creates a strict prompt for LLMs to generate a screenshot title from Storybook data.
33
40
  *
34
41
  * The prompt enforces JSON-only output in the form:
35
42
  * `{"title":"..."}`.
36
43
  */
37
- declare function createScreenshotTitlePrompt(data: GenerateScreenshotTitleInput, options?: CreateScreenshotTitlePromptOptions): string;
44
+ declare function createScreenshotTitlePrompt(context: PartialContext, options?: CreateScreenshotTitlePromptOptions): string;
38
45
 
39
46
  export { type CreateScreenshotTitlePromptOptions, createScreenshotTitlePrompt };
package/dist/ai/index.js CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var r={fallbackTitle:"Should render correctly.",includeBrowserType:true,includeStoryId:false,maxTitleLength:80},i=2,l=10;function s(e={}){let o=Number.isFinite(e.maxTitleLength)?Math.max(l,Math.floor(e.maxTitleLength)):r.maxTitleLength;return {fallbackTitle:typeof e.fallbackTitle=="string"&&e.fallbackTitle.trim()?e.fallbackTitle.trim():r.fallbackTitle,includeBrowserType:e.includeBrowserType??r.includeBrowserType,includeStoryId:e.includeStoryId??r.includeStoryId,maxTitleLength:o}}function a(e,o){let t=s(o),n=JSON.stringify(e,null,i);return ["You are a screenshot title generator for Storybook Playwright.","Your goal is to read the input JSON and produce one clear screenshot title.","","Follow this process internally before writing the final answer:","1) Parse INPUT_JSON as JSON.","2) Review every top-level and nested field and understand what each field says about the screenshot context.","3) Decide the most important details for naming this screenshot.","4) Build a short, human-friendly title.","","Field guide:","- story.name: story display name.","- story.title: Storybook group/title path.","- story.changedArgs: args changed from defaults; high-priority signal for title.","- story.initialArgs: default args for the story; use for context only.","- story.argTypes: arg metadata; use only when it clarifies changedArgs.","- story.parameters: Storybook-level metadata; only use if it impacts screenshot meaning.","- story.filePath: source story file path.","- story.id: unique Storybook story id.","- browser.type: browser engine (chromium, firefox, webkit).","- browser.options: browser/device options such as viewport and device profile.","- screenshotOptions: screenshot behavior options that may change output meaning.","","Title rules:",`- Maximum length: ${t.maxTitleLength} characters.`,`- ${t.includeBrowserType?"Include browser type only when it adds useful context.":"Do not include browser type in the title."}`,`- ${t.includeStoryId?"You may include story.id when needed for uniqueness.":"Do not include story.id unless no other unique context exists."}`,"- Prefer changedArgs details when present.","- Avoid filler words and generic phrases.","- Title must be plain text (no markdown, no quotes around the full title).","","Output contract (strict):","- Return JSON only.","- Return exactly one object with exactly one key: title.",'- Shape: {"title":"<generated title>"}',`- If context is insufficient, use fallback title: ${JSON.stringify(t.fallbackTitle)}`,"","INPUT_JSON:",n].join(`
2
- `)}exports.createScreenshotTitlePrompt=a;//# sourceMappingURL=index.js.map
1
+ 'use strict';var n={fallbackTitle:"Should render correctly.",includeBrowserType:true,includeStoryId:false,maxTitleLength:80,outputPrompt:"Return only the generated title as string, without any additional text or formatting."},u=2,c=10,d={changedArgs:"The specific arguments that have been changed from their default values for this story; these are high-priority signals for understanding what is unique about this screenshot.",initialArgs:"The default arguments for the story, which can provide context but are less important than changedArgs for title generation.",argTypes:"Metadata about the story arguments, which should only be used if it clarifies the meaning of changedArgs.",name:"The display name of the story, often concise and descriptive.",title:"The hierarchical path of the story in Storybook, which may include groupings and can provide context about the component and its variations.",parameters:"Additional metadata at the Storybook level, which should only be considered if it impacts the meaning of the screenshot.",filePath:"The file path to the source story, which may provide context about the component or feature being tested.",id:"The unique identifier for the Storybook story, which should only be included in the title if no other unique context exists."},p={type:"The type of browser engine used (e.g., chromium, firefox, webkit), which should be included in the title only when it adds useful context.",options:"Options related to the browser or device, such as viewport size and device profile, which may influence the meaning of the screenshot."},f="Behavior options for taking the screenshot that may change its meaning or context.",l={story:d,browser:p,screenshotOptions:f};function h(e,r){return e[r]!==void 0}function m(e={}){let r=Number.isFinite(e.maxTitleLength)?Math.max(c,Math.floor(e.maxTitleLength)):n.maxTitleLength,t=(Array.isArray(e.outputPrompt)?e.outputPrompt:typeof e.outputPrompt=="string"?[e.outputPrompt]:[n.outputPrompt]).map(o=>o.trim()).map(o=>"- "+o);return {fallbackTitle:typeof e.fallbackTitle=="string"&&e.fallbackTitle.trim()?e.fallbackTitle.trim():n.fallbackTitle,includeBrowserType:e.includeBrowserType??n.includeBrowserType,includeStoryId:e.includeStoryId??n.includeStoryId,maxTitleLength:r,outputPrompt:t}}function y(e,r){let t=m(r),o=JSON.stringify(e,null,u),i=["Field guide:"];return h(e,"story")&&e.story&&i.push(...Object.entries(l.story).map(([s,a])=>`- story.${s}: ${a}`)),h(e,"browser")&&e.browser&&i.push(...Object.entries(l.browser).map(([s,a])=>`- browser.${s}: ${a}`)),h(e,"screenshotOptions")&&e.screenshotOptions&&i.push(`- screenshotOptions: ${l.screenshotOptions}`),i.push(""),["You are a screenshot title generator for Storybook Playwright.","Your goal is to read the input JSON and produce one clear screenshot title.","","Follow this process internally before writing the final answer:","1) Parse INPUT_JSON as JSON.","2) Review every top-level and nested field and understand what each field says about the screenshot context.","3) Decide the most important details for naming this screenshot.","4) Build a short, human-friendly title.","",...i,"Title rules:",`- Maximum length: ${t.maxTitleLength} characters.`,`- ${t.includeBrowserType?"Include browser type only when it adds useful context.":"Do not include browser type in the title."}`,`- ${t.includeStoryId?"You may include story.id when needed for uniqueness.":"Do not include story.id unless no other unique context exists."}`,"- Prefer changedArgs details when present.","- Avoid filler words and generic phrases.","- Title must be plain text (no markdown, no quotes around the full title).","","Output contract (strict):",...t.outputPrompt,`- If context is insufficient, use fallback title: ${JSON.stringify(t.fallbackTitle)}`,"","INPUT_JSON:",o].join(`
2
+ `)}exports.createScreenshotTitlePrompt=y;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ai/generate-screenshot-title-prompt.ts"],"names":["DEFAULT_OPTIONS","INPUT_JSON_INDENT","MIN_TITLE_LENGTH","normalizeOptions","options","maxTitleLength","createScreenshotTitlePrompt","data","resolved","inputJson"],"mappings":"aAgCA,IAAMA,CAAAA,CAAgE,CACpE,aAAA,CAAe,0BAAA,CACf,mBAAoB,IAAA,CACpB,cAAA,CAAgB,KAAA,CAChB,cAAA,CAAgB,EAClB,CAAA,CAEMC,CAAAA,CAAoB,CAAA,CACpBC,EAAmB,EAAA,CAEzB,SAASC,CAAAA,CACPC,CAAAA,CAA8C,EAAC,CACD,CAC9C,IAAMC,EAAiB,MAAA,CAAO,QAAA,CAASD,CAAAA,CAAQ,cAAc,EACzD,IAAA,CAAK,GAAA,CAAIF,CAAAA,CAAkB,IAAA,CAAK,MAAME,CAAAA,CAAQ,cAAwB,CAAC,CAAA,CACvEJ,CAAAA,CAAgB,cAAA,CAEpB,OAAO,CACL,cACE,OAAOI,CAAAA,CAAQ,aAAA,EAAkB,QAAA,EAAYA,EAAQ,aAAA,CAAc,IAAA,EAAK,CACpEA,CAAAA,CAAQ,cAAc,IAAA,EAAK,CAC3BJ,CAAAA,CAAgB,aAAA,CACtB,kBAAA,CAAoBI,CAAAA,CAAQ,kBAAA,EAAsBJ,CAAAA,CAAgB,mBAClE,cAAA,CAAgBI,CAAAA,CAAQ,cAAA,EAAkBJ,CAAAA,CAAgB,eAC1D,cAAA,CAAAK,CACF,CACF,CAQO,SAASC,CAAAA,CACdC,CAAAA,CACAH,CAAAA,CACQ,CACR,IAAMI,CAAAA,CAAWL,CAAAA,CAAiBC,CAAO,EACnCK,CAAAA,CAAY,IAAA,CAAK,SAAA,CAAUF,CAAAA,CAAM,KAAMN,CAAiB,CAAA,CAE9D,OAAO,CACL,iEACA,6EAAA,CACA,EAAA,CACA,iEAAA,CACA,8BAAA,CACA,8GAAA,CACA,kEAAA,CACA,yCAAA,CACA,EAAA,CACA,eACA,mCAAA,CACA,4CAAA,CACA,kFAAA,CACA,wEAAA,CACA,0EACA,0FAAA,CACA,2CAAA,CACA,wCAAA,CACA,6DAAA,CACA,iFACA,kFAAA,CACA,EAAA,CACA,cAAA,CACA,CAAA,kBAAA,EAAqBO,CAAAA,CAAS,cAAc,CAAA,YAAA,CAAA,CAC5C,CAAA,EAAA,EAAKA,EAAS,kBAAA,CAAqB,wDAAA,CAA2D,2CAA2C,CAAA,CAAA,CACzI,KAAKA,CAAAA,CAAS,cAAA,CAAiB,sDAAA,CAAyD,gEAAgE,GACxJ,4CAAA,CACA,2CAAA,CACA,4EAAA,CACA,EAAA,CACA,2BAAA,CACA,qBAAA,CACA,0DAAA,CACA,wCAAA,CACA,qDAAqD,IAAA,CAAK,SAAA,CAAUA,CAAAA,CAAS,aAAa,CAAC,CAAA,CAAA,CAC3F,EAAA,CACA,aAAA,CACAC,CACF,EAAE,IAAA,CAAK;AAAA,CAAI,CACb","file":"index.js","sourcesContent":["import type { GenerateScreenshotTitleInput } from '../schema';\n\nexport interface CreateScreenshotTitlePromptOptions {\n /**\n * Maximum number of characters allowed in the returned title.\n *\n * @default 80\n */\n maxTitleLength?: number;\n\n /**\n * Fallback title the model should use when input is too sparse.\n *\n * @default 'Should render correctly.'\n */\n fallbackTitle?: string;\n\n /**\n * Whether the generated title should include the browser type when useful.\n *\n * @default true\n */\n includeBrowserType?: boolean;\n\n /**\n * Whether the generated title can include the story id.\n *\n * @default false\n */\n includeStoryId?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<CreateScreenshotTitlePromptOptions> = {\n fallbackTitle: 'Should render correctly.',\n includeBrowserType: true,\n includeStoryId: false,\n maxTitleLength: 80,\n};\n\nconst INPUT_JSON_INDENT = 2;\nconst MIN_TITLE_LENGTH = 10;\n\nfunction normalizeOptions(\n options: CreateScreenshotTitlePromptOptions = {},\n): Required<CreateScreenshotTitlePromptOptions> {\n const maxTitleLength = Number.isFinite(options.maxTitleLength)\n ? Math.max(MIN_TITLE_LENGTH, Math.floor(options.maxTitleLength as number))\n : DEFAULT_OPTIONS.maxTitleLength;\n\n return {\n fallbackTitle:\n typeof options.fallbackTitle === 'string' && options.fallbackTitle.trim()\n ? options.fallbackTitle.trim()\n : DEFAULT_OPTIONS.fallbackTitle,\n includeBrowserType: options.includeBrowserType ?? DEFAULT_OPTIONS.includeBrowserType,\n includeStoryId: options.includeStoryId ?? DEFAULT_OPTIONS.includeStoryId,\n maxTitleLength,\n };\n}\n\n/**\n * Creates a strict prompt for LLMs to generate a screenshot title from Storybook data.\n *\n * The prompt enforces JSON-only output in the form:\n * `{\"title\":\"...\"}`.\n */\nexport function createScreenshotTitlePrompt(\n data: GenerateScreenshotTitleInput,\n options?: CreateScreenshotTitlePromptOptions,\n): string {\n const resolved = normalizeOptions(options);\n const inputJson = JSON.stringify(data, null, INPUT_JSON_INDENT);\n\n return [\n 'You are a screenshot title generator for Storybook Playwright.',\n 'Your goal is to read the input JSON and produce one clear screenshot title.',\n '',\n 'Follow this process internally before writing the final answer:',\n '1) Parse INPUT_JSON as JSON.',\n '2) Review every top-level and nested field and understand what each field says about the screenshot context.',\n '3) Decide the most important details for naming this screenshot.',\n '4) Build a short, human-friendly title.',\n '',\n 'Field guide:',\n '- story.name: story display name.',\n '- story.title: Storybook group/title path.',\n '- story.changedArgs: args changed from defaults; high-priority signal for title.',\n '- story.initialArgs: default args for the story; use for context only.',\n '- story.argTypes: arg metadata; use only when it clarifies changedArgs.',\n '- story.parameters: Storybook-level metadata; only use if it impacts screenshot meaning.',\n '- story.filePath: source story file path.',\n '- story.id: unique Storybook story id.',\n '- browser.type: browser engine (chromium, firefox, webkit).',\n '- browser.options: browser/device options such as viewport and device profile.',\n '- screenshotOptions: screenshot behavior options that may change output meaning.',\n '',\n 'Title rules:',\n `- Maximum length: ${resolved.maxTitleLength} characters.`,\n `- ${resolved.includeBrowserType ? 'Include browser type only when it adds useful context.' : 'Do not include browser type in the title.'}`,\n `- ${resolved.includeStoryId ? 'You may include story.id when needed for uniqueness.' : 'Do not include story.id unless no other unique context exists.'}`,\n '- Prefer changedArgs details when present.',\n '- Avoid filler words and generic phrases.',\n '- Title must be plain text (no markdown, no quotes around the full title).',\n '',\n 'Output contract (strict):',\n '- Return JSON only.',\n '- Return exactly one object with exactly one key: title.',\n '- Shape: {\"title\":\"<generated title>\"}',\n `- If context is insufficient, use fallback title: ${JSON.stringify(resolved.fallbackTitle)}`,\n '',\n 'INPUT_JSON:',\n inputJson,\n ].join('\\n');\n}\n"]}
1
+ {"version":3,"sources":["../../src/ai/generate-screenshot-title-prompt.ts"],"names":["DEFAULT_OPTIONS","INPUT_JSON_INDENT","MIN_TITLE_LENGTH","storyGuide","browserGuide","screenshotOptionsGuide","fieldGuide","hasOwnDefinedValue","value","key","normalizeOptions","options","maxTitleLength","outputPrompt","instruction","x","createScreenshotTitlePrompt","context","resolved","inputJson","fieldGuideSections","description"],"mappings":"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","file":"index.js","sourcesContent":["import type { GenerateScreenshotTitleInput } from '../schema';\n\nexport interface CreateScreenshotTitlePromptOptions {\n /**\n * Maximum number of characters allowed in the returned title.\n *\n * @default 80\n */\n maxTitleLength?: number;\n\n /**\n * Fallback title the model should use when input is too sparse.\n *\n * @default 'Should render correctly.'\n */\n fallbackTitle?: string;\n\n /**\n * Whether the generated title should include the browser type when useful.\n *\n * @default true\n */\n includeBrowserType?: boolean;\n\n /**\n * Whether the generated title can include the story id.\n *\n * @default false\n */\n includeStoryId?: boolean;\n\n /**\n * Additional instructions for the output format, appended to the prompt's output contract section.\n *\n * @default 'Return only the generated title as string, without any additional text or formatting.'\n */\n outputPrompt?: string | string[];\n}\n\ntype PartialContext = Partial<GenerateScreenshotTitleInput>;\n\ntype ScreenshotTitleFieldGuide = {\n story: Record<keyof GenerateScreenshotTitleInput['story'], string>;\n browser: Record<keyof GenerateScreenshotTitleInput['browser'], string>;\n screenshotOptions: string;\n};\n\nconst DEFAULT_OPTIONS: Required<CreateScreenshotTitlePromptOptions> = {\n fallbackTitle: 'Should render correctly.',\n includeBrowserType: true,\n includeStoryId: false,\n maxTitleLength: 80,\n outputPrompt:\n 'Return only the generated title as string, without any additional text or formatting.',\n};\n\nconst INPUT_JSON_INDENT = 2;\nconst MIN_TITLE_LENGTH = 10;\n\nconst storyGuide = {\n changedArgs:\n 'The specific arguments that have been changed from their default values for this story; these are high-priority signals for understanding what is unique about this screenshot.',\n initialArgs:\n 'The default arguments for the story, which can provide context but are less important than changedArgs for title generation.',\n argTypes:\n 'Metadata about the story arguments, which should only be used if it clarifies the meaning of changedArgs.',\n name: 'The display name of the story, often concise and descriptive.',\n title:\n 'The hierarchical path of the story in Storybook, which may include groupings and can provide context about the component and its variations.',\n parameters:\n 'Additional metadata at the Storybook level, which should only be considered if it impacts the meaning of the screenshot.',\n filePath:\n 'The file path to the source story, which may provide context about the component or feature being tested.',\n id: 'The unique identifier for the Storybook story, which should only be included in the title if no other unique context exists.',\n} satisfies ScreenshotTitleFieldGuide['story'];\n\nconst browserGuide = {\n type: 'The type of browser engine used (e.g., chromium, firefox, webkit), which should be included in the title only when it adds useful context.',\n options:\n 'Options related to the browser or device, such as viewport size and device profile, which may influence the meaning of the screenshot.',\n} satisfies ScreenshotTitleFieldGuide['browser'];\n\nconst screenshotOptionsGuide =\n 'Behavior options for taking the screenshot that may change its meaning or context.';\n\nconst fieldGuide: ScreenshotTitleFieldGuide = {\n story: storyGuide,\n browser: browserGuide,\n screenshotOptions: screenshotOptionsGuide,\n};\n\nfunction hasOwnDefinedValue<T extends object, K extends keyof T>(\n value: T,\n key: K,\n): boolean {\n return value[key] !== undefined;\n}\n\nfunction normalizeOptions(\n options: CreateScreenshotTitlePromptOptions = {},\n): Required<CreateScreenshotTitlePromptOptions> {\n const maxTitleLength = Number.isFinite(options.maxTitleLength)\n ? Math.max(MIN_TITLE_LENGTH, Math.floor(options.maxTitleLength as number))\n : DEFAULT_OPTIONS.maxTitleLength;\n\n const outputPrompt = (\n Array.isArray(options.outputPrompt)\n ? options.outputPrompt\n : typeof options.outputPrompt === 'string'\n ? [options.outputPrompt]\n : [DEFAULT_OPTIONS.outputPrompt]\n )\n .map((instruction) => (instruction as string).trim())\n .map((x) => '- ' + x);\n\n return {\n fallbackTitle:\n typeof options.fallbackTitle === 'string' && options.fallbackTitle.trim()\n ? options.fallbackTitle.trim()\n : DEFAULT_OPTIONS.fallbackTitle,\n includeBrowserType: options.includeBrowserType ?? DEFAULT_OPTIONS.includeBrowserType,\n includeStoryId: options.includeStoryId ?? DEFAULT_OPTIONS.includeStoryId,\n maxTitleLength,\n outputPrompt: outputPrompt,\n };\n}\n\n/**\n * Creates a strict prompt for LLMs to generate a screenshot title from Storybook data.\n *\n * The prompt enforces JSON-only output in the form:\n * `{\"title\":\"...\"}`.\n */\nexport function createScreenshotTitlePrompt(\n context: PartialContext,\n options?: CreateScreenshotTitlePromptOptions,\n): string {\n const resolved = normalizeOptions(options);\n const inputJson = JSON.stringify(context, null, INPUT_JSON_INDENT);\n const fieldGuideSections: string[] = ['Field guide:'];\n\n if (hasOwnDefinedValue(context, 'story') && context.story) {\n fieldGuideSections.push(\n ...Object.entries(fieldGuide.story).map(\n ([key, description]) => `- story.${key}: ${description}`,\n ),\n );\n }\n\n if (hasOwnDefinedValue(context, 'browser') && context.browser) {\n fieldGuideSections.push(\n ...Object.entries(fieldGuide.browser).map(\n ([key, description]) => `- browser.${key}: ${description}`,\n ),\n );\n }\n\n if (hasOwnDefinedValue(context, 'screenshotOptions') && context.screenshotOptions) {\n fieldGuideSections.push(`- screenshotOptions: ${fieldGuide.screenshotOptions}`);\n }\n\n fieldGuideSections.push('');\n\n return [\n 'You are a screenshot title generator for Storybook Playwright.',\n 'Your goal is to read the input JSON and produce one clear screenshot title.',\n '',\n 'Follow this process internally before writing the final answer:',\n '1) Parse INPUT_JSON as JSON.',\n '2) Review every top-level and nested field and understand what each field says about the screenshot context.',\n '3) Decide the most important details for naming this screenshot.',\n '4) Build a short, human-friendly title.',\n '',\n ...fieldGuideSections,\n 'Title rules:',\n `- Maximum length: ${resolved.maxTitleLength} characters.`,\n `- ${resolved.includeBrowserType ? 'Include browser type only when it adds useful context.' : 'Do not include browser type in the title.'}`,\n `- ${resolved.includeStoryId ? 'You may include story.id when needed for uniqueness.' : 'Do not include story.id unless no other unique context exists.'}`,\n '- Prefer changedArgs details when present.',\n '- Avoid filler words and generic phrases.',\n '- Title must be plain text (no markdown, no quotes around the full title).',\n '',\n 'Output contract (strict):',\n ...resolved.outputPrompt,\n `- If context is insufficient, use fallback title: ${JSON.stringify(resolved.fallbackTitle)}`,\n '',\n 'INPUT_JSON:',\n inputJson,\n ].join('\\n');\n}\n"]}
package/dist/ai/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- var r={fallbackTitle:"Should render correctly.",includeBrowserType:true,includeStoryId:false,maxTitleLength:80},i=2,l=10;function s(e={}){let o=Number.isFinite(e.maxTitleLength)?Math.max(l,Math.floor(e.maxTitleLength)):r.maxTitleLength;return {fallbackTitle:typeof e.fallbackTitle=="string"&&e.fallbackTitle.trim()?e.fallbackTitle.trim():r.fallbackTitle,includeBrowserType:e.includeBrowserType??r.includeBrowserType,includeStoryId:e.includeStoryId??r.includeStoryId,maxTitleLength:o}}function a(e,o){let t=s(o),n=JSON.stringify(e,null,i);return ["You are a screenshot title generator for Storybook Playwright.","Your goal is to read the input JSON and produce one clear screenshot title.","","Follow this process internally before writing the final answer:","1) Parse INPUT_JSON as JSON.","2) Review every top-level and nested field and understand what each field says about the screenshot context.","3) Decide the most important details for naming this screenshot.","4) Build a short, human-friendly title.","","Field guide:","- story.name: story display name.","- story.title: Storybook group/title path.","- story.changedArgs: args changed from defaults; high-priority signal for title.","- story.initialArgs: default args for the story; use for context only.","- story.argTypes: arg metadata; use only when it clarifies changedArgs.","- story.parameters: Storybook-level metadata; only use if it impacts screenshot meaning.","- story.filePath: source story file path.","- story.id: unique Storybook story id.","- browser.type: browser engine (chromium, firefox, webkit).","- browser.options: browser/device options such as viewport and device profile.","- screenshotOptions: screenshot behavior options that may change output meaning.","","Title rules:",`- Maximum length: ${t.maxTitleLength} characters.`,`- ${t.includeBrowserType?"Include browser type only when it adds useful context.":"Do not include browser type in the title."}`,`- ${t.includeStoryId?"You may include story.id when needed for uniqueness.":"Do not include story.id unless no other unique context exists."}`,"- Prefer changedArgs details when present.","- Avoid filler words and generic phrases.","- Title must be plain text (no markdown, no quotes around the full title).","","Output contract (strict):","- Return JSON only.","- Return exactly one object with exactly one key: title.",'- Shape: {"title":"<generated title>"}',`- If context is insufficient, use fallback title: ${JSON.stringify(t.fallbackTitle)}`,"","INPUT_JSON:",n].join(`
2
- `)}export{a as createScreenshotTitlePrompt};//# sourceMappingURL=index.mjs.map
1
+ var n={fallbackTitle:"Should render correctly.",includeBrowserType:true,includeStoryId:false,maxTitleLength:80,outputPrompt:"Return only the generated title as string, without any additional text or formatting."},u=2,c=10,d={changedArgs:"The specific arguments that have been changed from their default values for this story; these are high-priority signals for understanding what is unique about this screenshot.",initialArgs:"The default arguments for the story, which can provide context but are less important than changedArgs for title generation.",argTypes:"Metadata about the story arguments, which should only be used if it clarifies the meaning of changedArgs.",name:"The display name of the story, often concise and descriptive.",title:"The hierarchical path of the story in Storybook, which may include groupings and can provide context about the component and its variations.",parameters:"Additional metadata at the Storybook level, which should only be considered if it impacts the meaning of the screenshot.",filePath:"The file path to the source story, which may provide context about the component or feature being tested.",id:"The unique identifier for the Storybook story, which should only be included in the title if no other unique context exists."},p={type:"The type of browser engine used (e.g., chromium, firefox, webkit), which should be included in the title only when it adds useful context.",options:"Options related to the browser or device, such as viewport size and device profile, which may influence the meaning of the screenshot."},f="Behavior options for taking the screenshot that may change its meaning or context.",l={story:d,browser:p,screenshotOptions:f};function h(e,r){return e[r]!==void 0}function m(e={}){let r=Number.isFinite(e.maxTitleLength)?Math.max(c,Math.floor(e.maxTitleLength)):n.maxTitleLength,t=(Array.isArray(e.outputPrompt)?e.outputPrompt:typeof e.outputPrompt=="string"?[e.outputPrompt]:[n.outputPrompt]).map(o=>o.trim()).map(o=>"- "+o);return {fallbackTitle:typeof e.fallbackTitle=="string"&&e.fallbackTitle.trim()?e.fallbackTitle.trim():n.fallbackTitle,includeBrowserType:e.includeBrowserType??n.includeBrowserType,includeStoryId:e.includeStoryId??n.includeStoryId,maxTitleLength:r,outputPrompt:t}}function y(e,r){let t=m(r),o=JSON.stringify(e,null,u),i=["Field guide:"];return h(e,"story")&&e.story&&i.push(...Object.entries(l.story).map(([s,a])=>`- story.${s}: ${a}`)),h(e,"browser")&&e.browser&&i.push(...Object.entries(l.browser).map(([s,a])=>`- browser.${s}: ${a}`)),h(e,"screenshotOptions")&&e.screenshotOptions&&i.push(`- screenshotOptions: ${l.screenshotOptions}`),i.push(""),["You are a screenshot title generator for Storybook Playwright.","Your goal is to read the input JSON and produce one clear screenshot title.","","Follow this process internally before writing the final answer:","1) Parse INPUT_JSON as JSON.","2) Review every top-level and nested field and understand what each field says about the screenshot context.","3) Decide the most important details for naming this screenshot.","4) Build a short, human-friendly title.","",...i,"Title rules:",`- Maximum length: ${t.maxTitleLength} characters.`,`- ${t.includeBrowserType?"Include browser type only when it adds useful context.":"Do not include browser type in the title."}`,`- ${t.includeStoryId?"You may include story.id when needed for uniqueness.":"Do not include story.id unless no other unique context exists."}`,"- Prefer changedArgs details when present.","- Avoid filler words and generic phrases.","- Title must be plain text (no markdown, no quotes around the full title).","","Output contract (strict):",...t.outputPrompt,`- If context is insufficient, use fallback title: ${JSON.stringify(t.fallbackTitle)}`,"","INPUT_JSON:",o].join(`
2
+ `)}export{y as createScreenshotTitlePrompt};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ai/generate-screenshot-title-prompt.ts"],"names":["DEFAULT_OPTIONS","INPUT_JSON_INDENT","MIN_TITLE_LENGTH","normalizeOptions","options","maxTitleLength","createScreenshotTitlePrompt","data","resolved","inputJson"],"mappings":"AAgCA,IAAMA,CAAAA,CAAgE,CACpE,aAAA,CAAe,0BAAA,CACf,mBAAoB,IAAA,CACpB,cAAA,CAAgB,KAAA,CAChB,cAAA,CAAgB,EAClB,CAAA,CAEMC,CAAAA,CAAoB,CAAA,CACpBC,EAAmB,EAAA,CAEzB,SAASC,CAAAA,CACPC,CAAAA,CAA8C,EAAC,CACD,CAC9C,IAAMC,EAAiB,MAAA,CAAO,QAAA,CAASD,CAAAA,CAAQ,cAAc,EACzD,IAAA,CAAK,GAAA,CAAIF,CAAAA,CAAkB,IAAA,CAAK,MAAME,CAAAA,CAAQ,cAAwB,CAAC,CAAA,CACvEJ,CAAAA,CAAgB,cAAA,CAEpB,OAAO,CACL,cACE,OAAOI,CAAAA,CAAQ,aAAA,EAAkB,QAAA,EAAYA,EAAQ,aAAA,CAAc,IAAA,EAAK,CACpEA,CAAAA,CAAQ,cAAc,IAAA,EAAK,CAC3BJ,CAAAA,CAAgB,aAAA,CACtB,kBAAA,CAAoBI,CAAAA,CAAQ,kBAAA,EAAsBJ,CAAAA,CAAgB,mBAClE,cAAA,CAAgBI,CAAAA,CAAQ,cAAA,EAAkBJ,CAAAA,CAAgB,eAC1D,cAAA,CAAAK,CACF,CACF,CAQO,SAASC,CAAAA,CACdC,CAAAA,CACAH,CAAAA,CACQ,CACR,IAAMI,CAAAA,CAAWL,CAAAA,CAAiBC,CAAO,EACnCK,CAAAA,CAAY,IAAA,CAAK,SAAA,CAAUF,CAAAA,CAAM,KAAMN,CAAiB,CAAA,CAE9D,OAAO,CACL,iEACA,6EAAA,CACA,EAAA,CACA,iEAAA,CACA,8BAAA,CACA,8GAAA,CACA,kEAAA,CACA,yCAAA,CACA,EAAA,CACA,eACA,mCAAA,CACA,4CAAA,CACA,kFAAA,CACA,wEAAA,CACA,0EACA,0FAAA,CACA,2CAAA,CACA,wCAAA,CACA,6DAAA,CACA,iFACA,kFAAA,CACA,EAAA,CACA,cAAA,CACA,CAAA,kBAAA,EAAqBO,CAAAA,CAAS,cAAc,CAAA,YAAA,CAAA,CAC5C,CAAA,EAAA,EAAKA,EAAS,kBAAA,CAAqB,wDAAA,CAA2D,2CAA2C,CAAA,CAAA,CACzI,KAAKA,CAAAA,CAAS,cAAA,CAAiB,sDAAA,CAAyD,gEAAgE,GACxJ,4CAAA,CACA,2CAAA,CACA,4EAAA,CACA,EAAA,CACA,2BAAA,CACA,qBAAA,CACA,0DAAA,CACA,wCAAA,CACA,qDAAqD,IAAA,CAAK,SAAA,CAAUA,CAAAA,CAAS,aAAa,CAAC,CAAA,CAAA,CAC3F,EAAA,CACA,aAAA,CACAC,CACF,EAAE,IAAA,CAAK;AAAA,CAAI,CACb","file":"index.mjs","sourcesContent":["import type { GenerateScreenshotTitleInput } from '../schema';\n\nexport interface CreateScreenshotTitlePromptOptions {\n /**\n * Maximum number of characters allowed in the returned title.\n *\n * @default 80\n */\n maxTitleLength?: number;\n\n /**\n * Fallback title the model should use when input is too sparse.\n *\n * @default 'Should render correctly.'\n */\n fallbackTitle?: string;\n\n /**\n * Whether the generated title should include the browser type when useful.\n *\n * @default true\n */\n includeBrowserType?: boolean;\n\n /**\n * Whether the generated title can include the story id.\n *\n * @default false\n */\n includeStoryId?: boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<CreateScreenshotTitlePromptOptions> = {\n fallbackTitle: 'Should render correctly.',\n includeBrowserType: true,\n includeStoryId: false,\n maxTitleLength: 80,\n};\n\nconst INPUT_JSON_INDENT = 2;\nconst MIN_TITLE_LENGTH = 10;\n\nfunction normalizeOptions(\n options: CreateScreenshotTitlePromptOptions = {},\n): Required<CreateScreenshotTitlePromptOptions> {\n const maxTitleLength = Number.isFinite(options.maxTitleLength)\n ? Math.max(MIN_TITLE_LENGTH, Math.floor(options.maxTitleLength as number))\n : DEFAULT_OPTIONS.maxTitleLength;\n\n return {\n fallbackTitle:\n typeof options.fallbackTitle === 'string' && options.fallbackTitle.trim()\n ? options.fallbackTitle.trim()\n : DEFAULT_OPTIONS.fallbackTitle,\n includeBrowserType: options.includeBrowserType ?? DEFAULT_OPTIONS.includeBrowserType,\n includeStoryId: options.includeStoryId ?? DEFAULT_OPTIONS.includeStoryId,\n maxTitleLength,\n };\n}\n\n/**\n * Creates a strict prompt for LLMs to generate a screenshot title from Storybook data.\n *\n * The prompt enforces JSON-only output in the form:\n * `{\"title\":\"...\"}`.\n */\nexport function createScreenshotTitlePrompt(\n data: GenerateScreenshotTitleInput,\n options?: CreateScreenshotTitlePromptOptions,\n): string {\n const resolved = normalizeOptions(options);\n const inputJson = JSON.stringify(data, null, INPUT_JSON_INDENT);\n\n return [\n 'You are a screenshot title generator for Storybook Playwright.',\n 'Your goal is to read the input JSON and produce one clear screenshot title.',\n '',\n 'Follow this process internally before writing the final answer:',\n '1) Parse INPUT_JSON as JSON.',\n '2) Review every top-level and nested field and understand what each field says about the screenshot context.',\n '3) Decide the most important details for naming this screenshot.',\n '4) Build a short, human-friendly title.',\n '',\n 'Field guide:',\n '- story.name: story display name.',\n '- story.title: Storybook group/title path.',\n '- story.changedArgs: args changed from defaults; high-priority signal for title.',\n '- story.initialArgs: default args for the story; use for context only.',\n '- story.argTypes: arg metadata; use only when it clarifies changedArgs.',\n '- story.parameters: Storybook-level metadata; only use if it impacts screenshot meaning.',\n '- story.filePath: source story file path.',\n '- story.id: unique Storybook story id.',\n '- browser.type: browser engine (chromium, firefox, webkit).',\n '- browser.options: browser/device options such as viewport and device profile.',\n '- screenshotOptions: screenshot behavior options that may change output meaning.',\n '',\n 'Title rules:',\n `- Maximum length: ${resolved.maxTitleLength} characters.`,\n `- ${resolved.includeBrowserType ? 'Include browser type only when it adds useful context.' : 'Do not include browser type in the title.'}`,\n `- ${resolved.includeStoryId ? 'You may include story.id when needed for uniqueness.' : 'Do not include story.id unless no other unique context exists.'}`,\n '- Prefer changedArgs details when present.',\n '- Avoid filler words and generic phrases.',\n '- Title must be plain text (no markdown, no quotes around the full title).',\n '',\n 'Output contract (strict):',\n '- Return JSON only.',\n '- Return exactly one object with exactly one key: title.',\n '- Shape: {\"title\":\"<generated title>\"}',\n `- If context is insufficient, use fallback title: ${JSON.stringify(resolved.fallbackTitle)}`,\n '',\n 'INPUT_JSON:',\n inputJson,\n ].join('\\n');\n}\n"]}
1
+ {"version":3,"sources":["../../src/ai/generate-screenshot-title-prompt.ts"],"names":["DEFAULT_OPTIONS","INPUT_JSON_INDENT","MIN_TITLE_LENGTH","storyGuide","browserGuide","screenshotOptionsGuide","fieldGuide","hasOwnDefinedValue","value","key","normalizeOptions","options","maxTitleLength","outputPrompt","instruction","x","createScreenshotTitlePrompt","context","resolved","inputJson","fieldGuideSections","description"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { GenerateScreenshotTitleInput } from '../schema';\n\nexport interface CreateScreenshotTitlePromptOptions {\n /**\n * Maximum number of characters allowed in the returned title.\n *\n * @default 80\n */\n maxTitleLength?: number;\n\n /**\n * Fallback title the model should use when input is too sparse.\n *\n * @default 'Should render correctly.'\n */\n fallbackTitle?: string;\n\n /**\n * Whether the generated title should include the browser type when useful.\n *\n * @default true\n */\n includeBrowserType?: boolean;\n\n /**\n * Whether the generated title can include the story id.\n *\n * @default false\n */\n includeStoryId?: boolean;\n\n /**\n * Additional instructions for the output format, appended to the prompt's output contract section.\n *\n * @default 'Return only the generated title as string, without any additional text or formatting.'\n */\n outputPrompt?: string | string[];\n}\n\ntype PartialContext = Partial<GenerateScreenshotTitleInput>;\n\ntype ScreenshotTitleFieldGuide = {\n story: Record<keyof GenerateScreenshotTitleInput['story'], string>;\n browser: Record<keyof GenerateScreenshotTitleInput['browser'], string>;\n screenshotOptions: string;\n};\n\nconst DEFAULT_OPTIONS: Required<CreateScreenshotTitlePromptOptions> = {\n fallbackTitle: 'Should render correctly.',\n includeBrowserType: true,\n includeStoryId: false,\n maxTitleLength: 80,\n outputPrompt:\n 'Return only the generated title as string, without any additional text or formatting.',\n};\n\nconst INPUT_JSON_INDENT = 2;\nconst MIN_TITLE_LENGTH = 10;\n\nconst storyGuide = {\n changedArgs:\n 'The specific arguments that have been changed from their default values for this story; these are high-priority signals for understanding what is unique about this screenshot.',\n initialArgs:\n 'The default arguments for the story, which can provide context but are less important than changedArgs for title generation.',\n argTypes:\n 'Metadata about the story arguments, which should only be used if it clarifies the meaning of changedArgs.',\n name: 'The display name of the story, often concise and descriptive.',\n title:\n 'The hierarchical path of the story in Storybook, which may include groupings and can provide context about the component and its variations.',\n parameters:\n 'Additional metadata at the Storybook level, which should only be considered if it impacts the meaning of the screenshot.',\n filePath:\n 'The file path to the source story, which may provide context about the component or feature being tested.',\n id: 'The unique identifier for the Storybook story, which should only be included in the title if no other unique context exists.',\n} satisfies ScreenshotTitleFieldGuide['story'];\n\nconst browserGuide = {\n type: 'The type of browser engine used (e.g., chromium, firefox, webkit), which should be included in the title only when it adds useful context.',\n options:\n 'Options related to the browser or device, such as viewport size and device profile, which may influence the meaning of the screenshot.',\n} satisfies ScreenshotTitleFieldGuide['browser'];\n\nconst screenshotOptionsGuide =\n 'Behavior options for taking the screenshot that may change its meaning or context.';\n\nconst fieldGuide: ScreenshotTitleFieldGuide = {\n story: storyGuide,\n browser: browserGuide,\n screenshotOptions: screenshotOptionsGuide,\n};\n\nfunction hasOwnDefinedValue<T extends object, K extends keyof T>(\n value: T,\n key: K,\n): boolean {\n return value[key] !== undefined;\n}\n\nfunction normalizeOptions(\n options: CreateScreenshotTitlePromptOptions = {},\n): Required<CreateScreenshotTitlePromptOptions> {\n const maxTitleLength = Number.isFinite(options.maxTitleLength)\n ? Math.max(MIN_TITLE_LENGTH, Math.floor(options.maxTitleLength as number))\n : DEFAULT_OPTIONS.maxTitleLength;\n\n const outputPrompt = (\n Array.isArray(options.outputPrompt)\n ? options.outputPrompt\n : typeof options.outputPrompt === 'string'\n ? [options.outputPrompt]\n : [DEFAULT_OPTIONS.outputPrompt]\n )\n .map((instruction) => (instruction as string).trim())\n .map((x) => '- ' + x);\n\n return {\n fallbackTitle:\n typeof options.fallbackTitle === 'string' && options.fallbackTitle.trim()\n ? options.fallbackTitle.trim()\n : DEFAULT_OPTIONS.fallbackTitle,\n includeBrowserType: options.includeBrowserType ?? DEFAULT_OPTIONS.includeBrowserType,\n includeStoryId: options.includeStoryId ?? DEFAULT_OPTIONS.includeStoryId,\n maxTitleLength,\n outputPrompt: outputPrompt,\n };\n}\n\n/**\n * Creates a strict prompt for LLMs to generate a screenshot title from Storybook data.\n *\n * The prompt enforces JSON-only output in the form:\n * `{\"title\":\"...\"}`.\n */\nexport function createScreenshotTitlePrompt(\n context: PartialContext,\n options?: CreateScreenshotTitlePromptOptions,\n): string {\n const resolved = normalizeOptions(options);\n const inputJson = JSON.stringify(context, null, INPUT_JSON_INDENT);\n const fieldGuideSections: string[] = ['Field guide:'];\n\n if (hasOwnDefinedValue(context, 'story') && context.story) {\n fieldGuideSections.push(\n ...Object.entries(fieldGuide.story).map(\n ([key, description]) => `- story.${key}: ${description}`,\n ),\n );\n }\n\n if (hasOwnDefinedValue(context, 'browser') && context.browser) {\n fieldGuideSections.push(\n ...Object.entries(fieldGuide.browser).map(\n ([key, description]) => `- browser.${key}: ${description}`,\n ),\n );\n }\n\n if (hasOwnDefinedValue(context, 'screenshotOptions') && context.screenshotOptions) {\n fieldGuideSections.push(`- screenshotOptions: ${fieldGuide.screenshotOptions}`);\n }\n\n fieldGuideSections.push('');\n\n return [\n 'You are a screenshot title generator for Storybook Playwright.',\n 'Your goal is to read the input JSON and produce one clear screenshot title.',\n '',\n 'Follow this process internally before writing the final answer:',\n '1) Parse INPUT_JSON as JSON.',\n '2) Review every top-level and nested field and understand what each field says about the screenshot context.',\n '3) Decide the most important details for naming this screenshot.',\n '4) Build a short, human-friendly title.',\n '',\n ...fieldGuideSections,\n 'Title rules:',\n `- Maximum length: ${resolved.maxTitleLength} characters.`,\n `- ${resolved.includeBrowserType ? 'Include browser type only when it adds useful context.' : 'Do not include browser type in the title.'}`,\n `- ${resolved.includeStoryId ? 'You may include story.id when needed for uniqueness.' : 'Do not include story.id unless no other unique context exists.'}`,\n '- Prefer changedArgs details when present.',\n '- Avoid filler words and generic phrases.',\n '- Title must be plain text (no markdown, no quotes around the full title).',\n '',\n 'Output contract (strict):',\n ...resolved.outputPrompt,\n `- If context is insufficient, use fallback title: ${JSON.stringify(resolved.fallbackTitle)}`,\n '',\n 'INPUT_JSON:',\n inputJson,\n ].join('\\n');\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storybook-addon-playwright",
3
- "version": "5.4.2",
3
+ "version": "5.6.0",
4
4
  "description": "An addon to visually test the stories in the multiple browsers within storybook environment",
5
5
  "author": "m.doaie <mdoaie@yahoo.co.uk>",
6
6
  "license": "MIT",