{"version":3,"file":"styling.mjs","names":[],"sources":["../../src/output/styling.ts"],"sourcesContent":["import type { PadroneActionContext } from '../types/index.ts';\nimport { type ColorConfig, type ColorTheme, createColorizer } from './colorizer.ts';\n\nexport const DEFAULT_TERMINAL_WIDTH = 80;\n\nexport function wrapText(text: string, maxWidth: number): string[] {\n  if (maxWidth <= 0 || text.length <= maxWidth) return [text];\n  const words = text.split(' ');\n  const lines: string[] = [];\n  let current = '';\n  for (const word of words) {\n    if (current && current.length + 1 + word.length > maxWidth) {\n      lines.push(current);\n      current = word;\n    } else {\n      current = current ? `${current} ${word}` : word;\n    }\n  }\n  if (current) lines.push(current);\n  return lines.length > 0 ? lines : [text];\n}\n\nexport function escapeHtml(text: string): string {\n  return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;');\n}\n\n// ── Styler ──────────────────────────────────────────────────────────────\n\n/**\n * Styling functions for semantic text roles.\n * Used by formatters to apply visual styles (ANSI, HTML, Markdown, etc.)\n * to different types of content.\n */\nexport type Styler = {\n  command: (text: string) => string;\n  arg: (text: string) => string;\n  type: (text: string) => string;\n  description: (text: string) => string;\n  label: (text: string) => string;\n  section: (text: string) => string;\n  meta: (text: string) => string;\n  example: (text: string) => string;\n  exampleValue: (text: string) => string;\n  deprecated: (text: string) => string;\n};\n\n/**\n * Layout configuration for formatters.\n */\nexport type LayoutConfig = {\n  newline: string;\n  indent: (level: number) => string;\n  join: (parts: string[]) => string;\n  wrapDocument?: (content: string) => string;\n};\n\n// ── Styler Factories ────────────────────────────────────────────────────\n\nexport function createTextStyler(): Styler {\n  return {\n    command: (text) => text,\n    arg: (text) => text,\n    type: (text) => text,\n    description: (text) => text,\n    label: (text) => text,\n    section: (text) => text,\n    meta: (text) => text,\n    example: (text) => text,\n    exampleValue: (text) => text,\n    deprecated: (text) => text,\n  };\n}\n\nexport function createAnsiStyler(theme?: ColorTheme | ColorConfig): Styler {\n  const colorizer = createColorizer(theme);\n  return {\n    command: colorizer.command,\n    arg: colorizer.arg,\n    type: colorizer.type,\n    description: colorizer.description,\n    label: colorizer.label,\n    section: colorizer.label,\n    meta: colorizer.meta,\n    example: colorizer.example,\n    exampleValue: colorizer.exampleValue,\n    deprecated: colorizer.deprecated,\n  };\n}\n\nexport function createConsoleStyler(theme?: ColorTheme | ColorConfig): Styler {\n  return createAnsiStyler(theme);\n}\n\nexport function createMarkdownStyler(): Styler {\n  return {\n    command: (text) => `**${text}**`,\n    arg: (text) => `\\`${text}\\``,\n    type: (text) => `\\`${text}\\``,\n    description: (text) => text,\n    label: (text) => `**${text}**`,\n    section: (text) => `### ${text}`,\n    meta: (text) => `*${text}*`,\n    example: (text) => `**${text}**`,\n    exampleValue: (text) => `\\`${text}\\``,\n    deprecated: (text) => `~~${text}~~`,\n  };\n}\n\nexport function createHtmlStyler(): Styler {\n  return {\n    command: (text) => `<strong style=\"color: #00bcd4;\">${escapeHtml(text)}</strong>`,\n    arg: (text) => `<code style=\"color: #4caf50;\">${escapeHtml(text)}</code>`,\n    type: (text) => `<code style=\"color: #ff9800;\">${escapeHtml(text)}</code>`,\n    description: (text) => `<span style=\"color: #666;\">${escapeHtml(text)}</span>`,\n    label: (text) => `<strong>${escapeHtml(text)}</strong>`,\n    section: (text) => `<h3>${escapeHtml(text)}</h3>`,\n    meta: (text) => `<span style=\"color: #999;\">${escapeHtml(text)}</span>`,\n    example: (text) => `<strong style=\"text-decoration: underline;\">${escapeHtml(text)}</strong>`,\n    exampleValue: (text) => `<em>${escapeHtml(text)}</em>`,\n    deprecated: (text) => `<del style=\"color: #999;\">${escapeHtml(text)}</del>`,\n  };\n}\n\n// ── Layout Factories ────────────────────────────────────────────────────\n\nexport function createTextLayout(): LayoutConfig {\n  return {\n    newline: '\\n',\n    indent: (level) => '  '.repeat(level),\n    join: (parts) => parts.filter(Boolean).join(' '),\n  };\n}\n\nexport function createMarkdownLayout(): LayoutConfig {\n  return {\n    newline: '\\n\\n',\n    indent: (level) => {\n      if (level === 0) return '';\n      if (level === 1) return '  ';\n      return '    ';\n    },\n    join: (parts) => parts.filter(Boolean).join(' '),\n  };\n}\n\nexport function createHtmlLayout(): LayoutConfig {\n  return {\n    newline: '<br>',\n    indent: (level) => '&nbsp;&nbsp;'.repeat(level),\n    join: (parts) => parts.filter(Boolean).join(' '),\n    wrapDocument: (content) => `<div style=\"font-family: monospace; line-height: 1.6;\">${content}</div>`,\n  };\n}\n\n// ── Format Detection ────────────────────────────────────────────────────\n\nexport function shouldUseAnsi(env?: Record<string, string | undefined>, isTTY?: boolean): boolean {\n  if (env?.NO_COLOR) return false;\n  if (env?.CI) return false;\n  if (typeof isTTY === 'boolean') return isTTY;\n  return false;\n}\n\n// ── Output Context ──────────────────────────────────────────────────────\n\n/** Resolved formatting context used by output primitives. */\nexport type OutputFormat = 'text' | 'ansi' | 'json' | 'markdown' | 'html';\n\nexport type OutputContext = {\n  format: OutputFormat;\n  styler: Styler;\n  layout: LayoutConfig;\n  terminalWidth?: number;\n};\n\n/** Resolve the output format from the runtime and caller context. */\nexport function resolveOutputFormat(\n  runtime: {\n    format?: string;\n    theme?: ColorTheme | ColorConfig;\n    terminal?: { columns?: number; isTTY?: boolean };\n    env: () => Record<string, string | undefined>;\n  },\n  caller?: PadroneActionContext['caller'],\n): OutputContext {\n  let format: OutputFormat;\n\n  if (caller === 'serve' || caller === 'mcp' || caller === 'tool') {\n    format = 'json';\n  } else if (runtime.format && runtime.format !== 'auto' && runtime.format !== 'console') {\n    format = runtime.format as OutputFormat;\n  } else {\n    format = shouldUseAnsi(runtime.env(), runtime.terminal?.isTTY) ? 'ansi' : 'text';\n  }\n\n  const terminalWidth = format === 'markdown' || format === 'html' ? undefined : (runtime.terminal?.columns ?? DEFAULT_TERMINAL_WIDTH);\n\n  let styler: Styler;\n  let layout: LayoutConfig;\n\n  switch (format) {\n    case 'ansi':\n      styler = createAnsiStyler(runtime.theme);\n      layout = createTextLayout();\n      break;\n    case 'markdown':\n      styler = createMarkdownStyler();\n      layout = createMarkdownLayout();\n      break;\n    case 'html':\n      styler = createHtmlStyler();\n      layout = createHtmlLayout();\n      break;\n    default:\n      styler = createTextStyler();\n      layout = createTextLayout();\n      break;\n  }\n\n  return { format, styler, layout, terminalWidth };\n}\n"],"mappings":"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"}