@pep/term-deck 1.0.14 → 1.0.15

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.
Files changed (37) hide show
  1. package/dist/bin/term-deck.d.ts +1 -0
  2. package/dist/bin/term-deck.js +1720 -0
  3. package/dist/bin/term-deck.js.map +1 -0
  4. package/dist/index.d.ts +670 -0
  5. package/dist/index.js +159 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +16 -13
  8. package/bin/term-deck.js +0 -14
  9. package/bin/term-deck.ts +0 -45
  10. package/src/cli/__tests__/errors.test.ts +0 -201
  11. package/src/cli/__tests__/help.test.ts +0 -157
  12. package/src/cli/__tests__/init.test.ts +0 -110
  13. package/src/cli/commands/export.ts +0 -33
  14. package/src/cli/commands/init.ts +0 -125
  15. package/src/cli/commands/present.ts +0 -29
  16. package/src/cli/errors.ts +0 -77
  17. package/src/core/__tests__/slide.test.ts +0 -1759
  18. package/src/core/__tests__/theme.test.ts +0 -1103
  19. package/src/core/slide.ts +0 -509
  20. package/src/core/theme.ts +0 -388
  21. package/src/export/__tests__/recorder.test.ts +0 -566
  22. package/src/export/recorder.ts +0 -639
  23. package/src/index.ts +0 -36
  24. package/src/presenter/__tests__/main.test.ts +0 -244
  25. package/src/presenter/main.ts +0 -658
  26. package/src/renderer/__tests__/screen-extended.test.ts +0 -801
  27. package/src/renderer/__tests__/screen.test.ts +0 -525
  28. package/src/renderer/screen.ts +0 -671
  29. package/src/schemas/__tests__/config.test.ts +0 -429
  30. package/src/schemas/__tests__/slide.test.ts +0 -349
  31. package/src/schemas/__tests__/theme.test.ts +0 -970
  32. package/src/schemas/__tests__/validation.test.ts +0 -256
  33. package/src/schemas/config.ts +0 -58
  34. package/src/schemas/slide.ts +0 -56
  35. package/src/schemas/theme.ts +0 -203
  36. package/src/schemas/validation.ts +0 -64
  37. package/src/themes/matrix/index.ts +0 -53
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js","../../src/schemas/slide.ts","../../src/schemas/theme.ts","../../src/schemas/config.ts","../../src/schemas/validation.ts","../../src/core/theme.ts","../../src/core/slide.ts","../../src/renderer/screen.ts","../../src/presenter/main.ts","../../bin/term-deck.ts","../../package.json","../../src/cli/commands/present.ts","../../src/cli/errors.ts","../../src/cli/commands/export.ts","../../src/export/recorder.ts","../../src/cli/commands/init.ts"],"names":["z","path","init_theme","convertMermaid","init_slide","gradient","access","blessed","nextSlide","join","mkdir","loadDeck","createRenderer","destroyRenderer","renderSlide","Command","writeFile","present"],"mappings":"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","file":"term-deck.js","sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { z } from 'zod'\n\n/**\n * Schema for validating slide frontmatter.\n * Defines the metadata for a single slide.\n */\nexport const SlideFrontmatterSchema = z.object({\n // Required: window title\n title: z.string().min(1, {\n message: 'Slide must have a title',\n }),\n\n // ASCII art text (figlet) - can be a single line or multiple lines\n bigText: z.union([\n z.string(),\n z.array(z.string()),\n ]).optional(),\n\n // Which gradient to use for bigText\n gradient: z.string().optional(),\n\n // Override theme for this slide\n theme: z.string().optional(),\n\n // Transition effect\n transition: z.enum([\n 'glitch', // Default: glitch reveal line by line\n 'fade', // Fade in\n 'instant', // No animation\n 'typewriter', // Character by character\n ]).default('glitch'),\n\n // Custom metadata (ignored by renderer, useful for tooling)\n meta: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport type SlideFrontmatter = z.infer<typeof SlideFrontmatterSchema>\n\n/**\n * Schema for a complete slide after parsing.\n * Includes the parsed frontmatter, body content, optional notes, and metadata.\n */\nexport const SlideSchema = z.object({\n // Parsed frontmatter\n frontmatter: SlideFrontmatterSchema,\n // Markdown body content\n body: z.string(),\n // Presenter notes (extracted from <!-- notes --> block)\n notes: z.string().optional(),\n // Source file path\n sourcePath: z.string(),\n // Slide index in deck (0-indexed)\n index: z.number(),\n})\n\nexport type Slide = z.infer<typeof SlideSchema>\n","import { z } from 'zod'\n\n/**\n * Schema for validating hex color strings.\n * Accepts 6-digit hex colors with # prefix (e.g., #ff0066)\n */\nexport const HexColorSchema = z.string().regex(/^#[0-9a-fA-F]{6}$/, {\n message: 'Color must be a valid hex color (e.g., #ff0066)',\n})\n\nexport type HexColor = z.infer<typeof HexColorSchema>\n\n/**\n * Schema for validating gradient color arrays.\n * A gradient requires at least 2 hex colors.\n */\nexport const GradientSchema = z.array(HexColorSchema).min(2, {\n message: 'Gradient must have at least 2 colors',\n})\n\nexport type Gradient = z.infer<typeof GradientSchema>\n\n/**\n * Schema for validating theme objects.\n * Defines the visual appearance of the presentation deck.\n */\nexport const ThemeSchema = z.object({\n // Theme metadata\n name: z.string().min(1, { message: 'Theme name is required' }),\n description: z.string().optional(),\n author: z.string().optional(),\n version: z.string().optional(),\n\n // Color palette\n colors: z.object({\n primary: HexColorSchema,\n secondary: HexColorSchema.optional(),\n accent: HexColorSchema,\n background: HexColorSchema,\n text: HexColorSchema,\n muted: HexColorSchema,\n success: HexColorSchema.optional(),\n warning: HexColorSchema.optional(),\n error: HexColorSchema.optional(),\n }),\n\n // Named gradients for bigText\n gradients: z.record(z.string(), GradientSchema).refine(\n (g) => Object.keys(g).length >= 1,\n { message: 'At least one gradient must be defined' }\n ),\n\n // Glyph set for matrix rain background\n glyphs: z.string().min(10, {\n message: 'Glyph set must have at least 10 characters',\n }),\n\n // Animation settings\n animations: z.object({\n // Speed multiplier (1.0 = normal, 0.5 = half speed, 2.0 = double speed)\n revealSpeed: z.number().min(0.1).max(5.0).default(1.0),\n // Matrix rain density (number of drops)\n matrixDensity: z.number().min(10).max(200).default(50),\n // Glitch effect iterations\n glitchIterations: z.number().min(1).max(20).default(5),\n // Delay between lines during reveal (ms)\n lineDelay: z.number().min(0).max(500).default(30),\n // Matrix rain update interval (ms)\n matrixInterval: z.number().min(20).max(200).default(80),\n }),\n\n // Window appearance\n window: z.object({\n // Border style\n borderStyle: z.enum(['line', 'double', 'rounded', 'none']).default('line'),\n // Shadow effect\n shadow: z.boolean().default(true),\n // Padding inside windows\n padding: z.object({\n top: z.number().min(0).max(5).default(1),\n bottom: z.number().min(0).max(5).default(1),\n left: z.number().min(0).max(10).default(2),\n right: z.number().min(0).max(10).default(2),\n }).optional(),\n }).optional(),\n})\n\nexport type Theme = z.infer<typeof ThemeSchema>\n\n// ============================================================================\n// Color Token System\n// ============================================================================\n\n/**\n * Valid color tokens for inline styling in slide body content.\n * Tokens can be either:\n * - Built-in colors: GREEN, ORANGE, CYAN, PINK, WHITE, GRAY\n * - Theme-mapped colors: PRIMARY, SECONDARY, ACCENT, MUTED, TEXT, BACKGROUND\n *\n * Usage in slides: {GREEN}colored text{/}\n */\nexport const ColorTokens = [\n 'GREEN',\n 'ORANGE',\n 'CYAN',\n 'PINK',\n 'WHITE',\n 'GRAY',\n 'PRIMARY', // Maps to theme.colors.primary\n 'SECONDARY', // Maps to theme.colors.secondary\n 'ACCENT', // Maps to theme.colors.accent\n 'MUTED', // Maps to theme.colors.muted\n 'TEXT', // Maps to theme.colors.text\n 'BACKGROUND', // Maps to theme.colors.background\n] as const\n\n/**\n * Type for valid color token names.\n */\nexport type ColorToken = typeof ColorTokens[number]\n\n/**\n * Pattern for matching color tokens in slide content.\n * Matches: {GREEN}, {ORANGE}, {CYAN}, {PINK}, {WHITE}, {GRAY},\n * {PRIMARY}, {SECONDARY}, {ACCENT}, {MUTED}, {TEXT}, {BACKGROUND}, {/}\n *\n * The {/} token closes any open color tag.\n */\nexport const COLOR_TOKEN_PATTERN = /\\{(GREEN|ORANGE|CYAN|PINK|WHITE|GRAY|PRIMARY|SECONDARY|ACCENT|MUTED|TEXT|BACKGROUND|\\/)\\}/g\n\n// ============================================================================\n// Partial Theme for Extension\n// ============================================================================\n\n/**\n * Deep partial utility type that makes all nested properties optional.\n * Used for theme extension where only specific fields need to be overridden.\n */\nexport type DeepPartial<T> = T extends object ? {\n [P in keyof T]?: DeepPartial<T[P]>\n} : T\n\n/**\n * Partial theme type for use with theme.extend() functionality.\n * All fields (including nested) become optional.\n */\nexport type PartialTheme = DeepPartial<Theme>\n\n/**\n * Schema for validating partial theme objects.\n * All fields become optional recursively, allowing partial overrides.\n * Used for theme extension validation.\n */\nexport const PartialThemeSchema = ThemeSchema.deepPartial()\n\n// ============================================================================\n// Default Theme\n// ============================================================================\n\n/**\n * Default matrix/cyberpunk theme.\n * Used when no theme is specified or as a base for theme extension.\n */\nexport const DEFAULT_THEME: Theme = {\n name: 'matrix',\n description: 'Default cyberpunk/matrix theme',\n\n colors: {\n primary: '#00cc66',\n accent: '#ff6600',\n background: '#0a0a0a',\n text: '#ffffff',\n muted: '#666666',\n },\n\n gradients: {\n fire: ['#ff6600', '#ff3300', '#ff0066'],\n cool: ['#00ccff', '#0066ff', '#6600ff'],\n pink: ['#ff0066', '#ff0099', '#cc00ff'],\n hf: ['#99cc00', '#00cc66', '#00cccc'],\n },\n\n glyphs: 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン0123456789',\n\n animations: {\n revealSpeed: 1.0,\n matrixDensity: 50,\n glitchIterations: 5,\n lineDelay: 30,\n matrixInterval: 80,\n },\n\n window: {\n borderStyle: 'line',\n shadow: true,\n padding: {\n top: 1,\n bottom: 1,\n left: 2,\n right: 2,\n },\n },\n}\n","import { z } from 'zod'\nimport { ThemeSchema } from './theme'\n\n/**\n * Schema for presentation settings.\n * Controls how the presentation behaves during runtime.\n */\nexport const SettingsSchema = z.object({\n // Start slide (0-indexed)\n startSlide: z.number().min(0).default(0),\n // Loop back to first slide after last\n loop: z.boolean().default(false),\n // Auto-advance slides (ms, 0 = disabled)\n autoAdvance: z.number().min(0).default(0),\n // Show slide numbers\n showSlideNumbers: z.boolean().default(false),\n // Show progress bar\n showProgress: z.boolean().default(false),\n})\n\nexport type Settings = z.infer<typeof SettingsSchema>\n\n/**\n * Schema for export settings.\n * Controls the output dimensions and quality of exported videos/GIFs.\n */\nexport const ExportSettingsSchema = z.object({\n // Output width in characters (min 80, max 400)\n width: z.number().min(80).max(400).default(120),\n // Output height in characters (min 24, max 100)\n height: z.number().min(24).max(100).default(40),\n // Frames per second for video (min 10, max 60)\n fps: z.number().min(10).max(60).default(30),\n})\n\nexport type ExportSettings = z.infer<typeof ExportSettingsSchema>\n\n/**\n * Schema for validating deck configuration (deck.config.ts).\n * Defines the complete configuration for a presentation deck.\n */\nexport const DeckConfigSchema = z.object({\n // Presentation metadata\n title: z.string().optional(),\n author: z.string().optional(),\n date: z.string().optional(),\n\n // Theme (already validated Theme object)\n theme: ThemeSchema,\n\n // Presentation settings\n settings: SettingsSchema.optional(),\n\n // Export settings\n export: ExportSettingsSchema.optional(),\n})\n\nexport type DeckConfig = z.infer<typeof DeckConfigSchema>\n","import { z, ZodError } from 'zod'\n\n/**\n * Custom error class for validation failures.\n * Extends Error with a specific name for easy identification.\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ValidationError'\n }\n}\n\n/**\n * Format Zod errors into user-friendly messages.\n * Formats each issue with its field path and message.\n *\n * @param error - The ZodError to format\n * @param context - A description of what was being validated (e.g., \"theme\", \"slide frontmatter\")\n * @returns A formatted string with all validation issues\n *\n * @example\n * const error = new ZodError([...])\n * formatZodError(error, 'theme')\n * // Returns:\n * // \"Invalid theme:\n * // - colors.primary: Color must be a valid hex color (e.g., #ff0066)\n * // - name: Theme name is required\"\n */\nexport function formatZodError(error: ZodError, context: string): string {\n const issues = error.issues.map((issue) => {\n const path = issue.path.join('.')\n return ` - ${path ? `${path}: ` : ''}${issue.message}`\n })\n\n return `Invalid ${context}:\\n${issues.join('\\n')}`\n}\n\n/**\n * Parse data with a Zod schema and throw a ValidationError with friendly messages on failure.\n *\n * @param schema - The Zod schema to validate against\n * @param data - The data to validate\n * @param context - A description of what's being validated (e.g., \"theme\", \"slide frontmatter\")\n * @returns The parsed and validated data\n * @throws {ValidationError} If validation fails\n *\n * @example\n * const theme = safeParse(ThemeSchema, rawData, 'theme')\n * // Throws ValidationError with formatted message if invalid\n */\nexport function safeParse<T>(\n schema: z.ZodSchema<T>,\n data: unknown,\n context: string\n): T {\n const result = schema.safeParse(data)\n\n if (!result.success) {\n throw new ValidationError(formatZodError(result.error, context))\n }\n\n return result.data\n}\n","import { parse as parseYaml } from 'yaml'\nimport deepmerge from 'deepmerge'\nimport gradient from 'gradient-string'\nimport { readFile, access } from 'fs/promises'\nimport type { Theme, PartialTheme } from '../schemas/theme'\nimport { ThemeSchema } from '../schemas/theme'\nimport { safeParse, ValidationError } from '../schemas/validation'\n\n/**\n * Error class for theme-related failures.\n * Includes optional source information (theme name and file path) for better debugging.\n */\nexport class ThemeError extends Error {\n /**\n * @param message - The error message\n * @param themeName - Optional name of the theme that caused the error\n * @param path - Optional path to the theme file or package\n */\n constructor(\n message: string,\n public readonly themeName?: string,\n public readonly path?: string\n ) {\n super(message)\n this.name = 'ThemeError'\n }\n}\n\n/**\n * Format any error into a user-friendly ThemeError.\n * Handles ValidationError, generic Error, and unknown error types.\n *\n * @param error - The error to format\n * @param source - Description of the theme source (e.g., file path or package name)\n * @returns A ThemeError with a user-friendly message\n *\n * @example\n * try {\n * await loadThemeFromFile('./theme.yml')\n * } catch (error) {\n * throw formatThemeError(error, './theme.yml')\n * }\n */\nexport function formatThemeError(error: unknown, source: string): ThemeError {\n if (error instanceof ValidationError) {\n return new ThemeError(\n `Invalid theme from ${source}:\\n${error.message}`,\n undefined,\n source\n )\n }\n\n if (error instanceof Error) {\n return new ThemeError(\n `Failed to load theme from ${source}: ${error.message}`,\n undefined,\n source\n )\n }\n\n return new ThemeError(`Unknown error loading theme from ${source}`)\n}\n\n/**\n * Theme object with extension capability.\n * Extends the base Theme type with an extend() method that allows\n * Tailwind-style theme customization.\n */\nexport interface ThemeObject extends Theme {\n /**\n * Create a new theme by merging overrides into this theme.\n * Uses deep merge with array replacement strategy.\n *\n * @param overrides - Partial theme object with values to override\n * @returns A new ThemeObject with the merged values\n *\n * @example\n * const custom = matrix.extend({\n * colors: { primary: '#ff0066' }\n * })\n *\n * @example\n * // Chained extensions\n * const custom = matrix\n * .extend({ colors: { primary: '#ff0066' } })\n * .extend({ animations: { revealSpeed: 0.5 } })\n */\n extend(overrides: PartialTheme): ThemeObject\n}\n\n/**\n * Theme package structure for npm packages or local theme files.\n * Contains the raw YAML source, parsed theme, and package metadata.\n */\nexport interface ThemePackage {\n /** Raw YAML content of the theme file */\n yaml: string\n\n /** Parsed and validated theme object */\n theme: ThemeObject\n\n /** Package metadata */\n meta: {\n /** Package or theme name */\n name: string\n /** Package version */\n version: string\n /** Path to the theme file or package */\n path: string\n }\n}\n\n/**\n * Create a ThemeObject from a validated Theme.\n * Internal helper that adds the extend() method to a Theme.\n *\n * @param validated - A validated Theme object\n * @returns A ThemeObject with extension capability\n */\nfunction createThemeFromMerge(base: Theme, overrides: PartialTheme): ThemeObject {\n // Deep merge, with overrides taking precedence\n const merged = deepmerge(base, overrides, {\n // Arrays should be replaced, not concatenated\n arrayMerge: (_, source) => source,\n }) as Theme\n\n // Re-validate the merged result\n const validated = safeParse(ThemeSchema, merged, 'merged theme')\n\n return {\n ...validated,\n extend(newOverrides: PartialTheme): ThemeObject {\n return createThemeFromMerge(validated, newOverrides)\n },\n }\n}\n\n/**\n * Create a theme from a YAML string.\n * Parses the YAML, validates it against ThemeSchema, and returns a ThemeObject\n * with extension capability.\n *\n * @param yaml - The YAML string containing the theme definition\n * @returns A validated ThemeObject with extend() method\n * @throws {Error} If the YAML syntax is invalid\n * @throws {ValidationError} If the parsed data doesn't match ThemeSchema\n *\n * @example\n * const theme = createTheme(`\n * name: custom\n * colors:\n * primary: \"#ff0066\"\n * accent: \"#00ff66\"\n * background: \"#000000\"\n * text: \"#ffffff\"\n * muted: \"#666666\"\n * gradients:\n * main:\n * - \"#ff0066\"\n * - \"#00ff66\"\n * glyphs: \"0123456789ABCDEF\"\n * animations:\n * revealSpeed: 1.0\n * matrixDensity: 30\n * glitchIterations: 3\n * lineDelay: 20\n * matrixInterval: 100\n * `)\n */\nexport function createTheme(yaml: string): ThemeObject {\n const parsed = parseYaml(yaml)\n const validated = safeParse(ThemeSchema, parsed, 'theme')\n\n return {\n ...validated,\n extend(overrides: PartialTheme): ThemeObject {\n return createThemeFromMerge(validated, overrides)\n },\n }\n}\n\n/**\n * Load a theme from a YAML file on the filesystem.\n * Reads the file contents and passes them to createTheme for parsing and validation.\n *\n * @param path - The filesystem path to the YAML theme file\n * @returns A validated ThemeObject with extend() method\n * @throws {Error} If the file cannot be read (e.g., file not found, permission denied)\n * @throws {Error} If the YAML syntax is invalid\n * @throws {ValidationError} If the parsed data doesn't match ThemeSchema\n *\n * @example\n * const theme = await loadThemeFromFile('./themes/matrix.yml')\n * const customTheme = theme.extend({ colors: { primary: '#ff0066' } })\n */\nexport async function loadThemeFromFile(path: string): Promise<ThemeObject> {\n try {\n await access(path)\n } catch {\n throw new Error(`Theme file not found: ${path}`)\n }\n\n const content = await readFile(path, 'utf-8')\n return createTheme(content)\n}\n\n/**\n * Load a theme from an npm package.\n * Packages must export a default ThemeObject.\n *\n * @param name - The npm package name (e.g., '@term-deck/theme-retro')\n * @returns A validated ThemeObject with extend() method\n * @throws {Error} If the package doesn't export a default theme\n * @throws {Error} If the package is not installed (with helpful install message)\n * @throws {ValidationError} If the exported theme doesn't match ThemeSchema\n *\n * @example\n * const theme = await loadThemeFromPackage('@term-deck/theme-retro')\n * const customTheme = theme.extend({ colors: { primary: '#ff0066' } })\n */\nexport async function loadThemeFromPackage(name: string): Promise<ThemeObject> {\n try {\n // Dynamic import of npm package\n const pkg = await import(name)\n\n if (!pkg.default) {\n throw new Error(`Theme package \"${name}\" must export a default theme`)\n }\n\n // Validate the exported theme\n const validated = safeParse(ThemeSchema, pkg.default, `theme from ${name}`)\n\n return {\n ...validated,\n extend(overrides: PartialTheme): ThemeObject {\n return createThemeFromMerge(validated, overrides)\n },\n }\n } catch (error) {\n // Handle module not found with helpful message\n // Bun's module resolution errors are not instanceof Error but have message/code properties\n const err = error as { message?: string; code?: string }\n const isModuleNotFound =\n err.message?.includes('Cannot find package') ||\n err.message?.includes('Cannot find module') ||\n err.code === 'MODULE_NOT_FOUND' ||\n err.code === 'ERR_MODULE_NOT_FOUND'\n\n if (isModuleNotFound) {\n throw new Error(\n `Theme package \"${name}\" not found. Install it with: bun add ${name}`\n )\n }\n throw error\n }\n}\n\n/**\n * Function type for applying a gradient to text.\n * Returns ANSI-colored text with the gradient applied.\n */\nexport interface GradientFunction {\n (text: string): string\n}\n\n/**\n * Create gradient functions from theme gradients.\n * Returns an object mapping gradient names to gradient functions that can be\n * applied to text to produce ANSI-colored output.\n *\n * @param theme - The theme containing gradient definitions\n * @returns Record mapping gradient names to gradient functions\n *\n * @example\n * const gradients = createGradients(theme)\n * const styledText = gradients.fire('Hello World')\n */\nexport function createGradients(theme: Theme): Record<string, GradientFunction> {\n const gradients: Record<string, GradientFunction> = {}\n\n for (const [name, colors] of Object.entries(theme.gradients)) {\n gradients[name] = gradient(colors)\n }\n\n return gradients\n}\n\n/**\n * Apply a gradient to text by name.\n * Looks up the gradient in the theme and applies it to the text.\n * Falls back gracefully if the gradient doesn't exist.\n *\n * @param text - The text to apply the gradient to\n * @param gradientName - The name of the gradient to use\n * @param theme - The theme containing gradient definitions\n * @returns The text with gradient applied, or unstyled text if gradient not found\n *\n * @example\n * const styledText = applyGradient('Hello World', 'fire', theme)\n */\nexport function applyGradient(\n text: string,\n gradientName: string,\n theme: Theme\n): string {\n const colors = theme.gradients[gradientName]\n\n if (!colors) {\n // Fall back gracefully - return unstyled text\n return text\n }\n\n return gradient(colors)(text)\n}\n\n/**\n * Built-in color mappings for color tokens in slide content.\n * These are fixed colors that don't change with the theme.\n */\nexport const BUILTIN_COLORS: Record<string, string> = {\n GREEN: '#00cc66',\n ORANGE: '#ff6600',\n CYAN: '#00ccff',\n PINK: '#ff0066',\n WHITE: '#ffffff',\n GRAY: '#666666',\n}\n\n/**\n * Resolve a color token to its hex value.\n * Theme colors (PRIMARY, ACCENT, etc.) are resolved from the theme.\n * Built-in colors (GREEN, ORANGE, etc.) use fixed values.\n *\n * @param token - The color token to resolve (e.g., 'PRIMARY', 'GREEN')\n * @param theme - The theme to resolve theme-specific tokens from\n * @returns The hex color value\n *\n * @example\n * const color = resolveColorToken('PRIMARY', theme) // '#00cc66'\n * const color = resolveColorToken('GREEN', theme) // '#00cc66'\n */\nexport function resolveColorToken(token: string, theme: Theme): string {\n // Check theme colors first\n switch (token) {\n case 'PRIMARY':\n return theme.colors.primary\n case 'SECONDARY':\n return theme.colors.secondary ?? theme.colors.primary\n case 'ACCENT':\n return theme.colors.accent\n case 'MUTED':\n return theme.colors.muted\n case 'TEXT':\n return theme.colors.text\n case 'BACKGROUND':\n return theme.colors.background\n }\n\n // Fall back to built-in colors\n return BUILTIN_COLORS[token] ?? theme.colors.text\n}\n\n/**\n * Convert color tokens in content to blessed tags.\n * Transforms tokens like {GREEN} to blessed color tags like {#00cc66-fg}.\n * Preserves closing tags {/} as-is.\n *\n * @param content - The content with color tokens\n * @param theme - The theme to resolve theme-specific tokens from\n * @returns Content with color tokens converted to blessed tags\n *\n * @example\n * const content = '{GREEN}Hello{/} {ORANGE}World{/}'\n * const result = colorTokensToBlessedTags(content, theme)\n * // '{#00cc66-fg}Hello{/} {#ff6600-fg}World{/}'\n */\nexport function colorTokensToBlessedTags(content: string, theme: Theme): string {\n return content.replace(\n /\\{(GREEN|ORANGE|CYAN|PINK|WHITE|GRAY|PRIMARY|SECONDARY|ACCENT|MUTED|TEXT|BACKGROUND|\\/)\\}/g,\n (_, token) => {\n if (token === '/') {\n return '{/}' // Close tag\n }\n const color = resolveColorToken(token, theme)\n return `{${color}-fg}`\n }\n )\n}\n","import matter from 'gray-matter'\nimport { join } from 'path'\nimport fg from 'fast-glob'\nimport { readFile, access } from 'fs/promises'\nimport { mermaidToAscii as convertMermaid } from 'mermaid-ascii'\nimport type { Slide } from '../schemas/slide.js'\nimport type { DeckConfig } from '../schemas/config.js'\nimport type { Theme } from '../schemas/theme.js'\nimport { SlideFrontmatterSchema, SlideSchema } from '../schemas/slide.js'\nimport { DeckConfigSchema } from '../schemas/config.js'\nimport { safeParse } from '../schemas/validation.js'\nimport { DEFAULT_THEME } from '../schemas/theme.js'\nimport { colorTokensToBlessedTags } from './theme.js'\n\n/**\n * Raw parsed slide before validation.\n * This is the intermediate structure after parsing frontmatter\n * but before Zod validation.\n */\nexport interface RawSlide {\n frontmatter: Record<string, unknown>\n body: string\n notes?: string\n sourcePath: string\n}\n\n/**\n * Deck structure containing all slides and configuration.\n * Represents a complete presentation loaded from disk.\n */\nexport interface Deck {\n slides: Slide[]\n config: DeckConfig\n basePath: string\n}\n\n/**\n * Slide file info for sorting and loading.\n * Used during the slide discovery phase.\n */\nexport interface SlideFile {\n path: string\n name: string\n index: number\n}\n\n/**\n * Result of extracting notes from slide content.\n */\nexport interface ExtractedNotes {\n body: string\n notes?: string\n}\n\nconst NOTES_MARKER = '<!-- notes -->'\nconst NOTES_END_MARKER = '<!-- /notes -->'\n\n/**\n * Pattern to match mermaid code blocks in markdown content.\n * Captures the diagram code inside the block.\n *\n * Matches: ```mermaid\\n<content>```\n * Group 1: The mermaid diagram code\n */\nconst MERMAID_BLOCK_PATTERN = /```mermaid\\n([\\s\\S]*?)```/g\n\n/**\n * Check if content contains mermaid diagrams.\n *\n * @param content - The markdown content to check\n * @returns true if the content contains at least one mermaid code block\n */\nexport function hasMermaidDiagrams(content: string): boolean {\n // Reset pattern since we use global flag\n MERMAID_BLOCK_PATTERN.lastIndex = 0\n return MERMAID_BLOCK_PATTERN.test(content)\n}\n\n/**\n * Extract all mermaid blocks from content.\n *\n * Finds all mermaid code blocks and extracts the diagram code\n * (without the ```mermaid and ``` delimiters).\n *\n * @param content - The markdown content to search\n * @returns Array of mermaid diagram code strings (trimmed)\n */\nexport function extractMermaidBlocks(content: string): string[] {\n const blocks: string[] = []\n let match: RegExpExecArray | null\n\n // Reset pattern before use\n MERMAID_BLOCK_PATTERN.lastIndex = 0\n\n while ((match = MERMAID_BLOCK_PATTERN.exec(content)) !== null) {\n blocks.push(match[1].trim())\n }\n\n return blocks\n}\n\n/**\n * Format a mermaid parsing error as ASCII.\n *\n * Creates a visually recognizable error block showing the\n * first few lines of the diagram with a border.\n *\n * @param code - The mermaid diagram code that failed to parse\n * @param _error - The error that occurred (unused but kept for signature)\n * @returns ASCII art error block\n */\nexport function formatMermaidError(code: string, _error: unknown): string {\n const lines = [\n '┌─ Diagram (parse error) ─┐',\n '│ │',\n ]\n\n // Show first few lines of the diagram\n const codeLines = code.split('\\n').slice(0, 5)\n for (const line of codeLines) {\n const truncated = line.slice(0, 23).padEnd(23)\n lines.push(`│ ${truncated} │`)\n }\n\n if (code.split('\\n').length > 5) {\n lines.push('│ ... │')\n }\n\n lines.push('│ │')\n lines.push('└─────────────────────────┘')\n\n return lines.join('\\n')\n}\n\n/**\n * Convert mermaid diagram to ASCII art.\n *\n * Uses the mermaid-ascii library to convert mermaid diagram\n * syntax to ASCII art representation. Falls back to an error\n * block if parsing fails.\n *\n * @param mermaidCode - Raw mermaid diagram code\n * @returns ASCII art representation or error block\n */\nexport function mermaidToAscii(mermaidCode: string): string {\n try {\n return convertMermaid(mermaidCode)\n } catch (error) {\n // If parsing fails, return a formatted error block\n return formatMermaidError(mermaidCode, error)\n }\n}\n\n/**\n * Escape special regex characters in a string.\n *\n * @param str - String to escape\n * @returns Escaped string safe for use in RegExp\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/**\n * Process all mermaid blocks in slide content.\n *\n * Finds all mermaid code blocks in the content and replaces them\n * with their ASCII art representation.\n *\n * @param content - The slide content potentially containing mermaid blocks\n * @returns Content with mermaid blocks replaced by ASCII art\n */\nexport function processMermaidDiagrams(content: string): string {\n if (!hasMermaidDiagrams(content)) {\n return content\n }\n\n // Find all blocks and convert\n let result = content\n const blocks = extractMermaidBlocks(content)\n\n for (const block of blocks) {\n const ascii = mermaidToAscii(block)\n\n // Replace mermaid block with ASCII\n // The pattern matches the code block including newlines\n result = result.replace(\n new RegExp('```mermaid\\\\n' + escapeRegex(block) + '\\\\n?```', 'g'),\n ascii\n )\n }\n\n return result\n}\n\n/**\n * Process slide body content.\n *\n * Applies the full content processing pipeline:\n * 1. Process mermaid diagrams (convert to ASCII)\n * 2. Apply color tokens (convert to blessed tags)\n *\n * The order is important: mermaid diagrams are processed first so that\n * any color tokens they might contain are then converted to blessed tags.\n *\n * @param body - The slide body content to process\n * @param theme - The theme to use for color token resolution\n * @returns Processed content with mermaid converted and color tokens applied\n *\n * @example\n * const processed = await processSlideContent(\n * '{GREEN}Hello{/}\\n\\n```mermaid\\ngraph LR\\nA-->B\\n```',\n * theme\n * )\n * // Returns: '{#00cc66-fg}Hello{/}\\n\\n<ascii art>'\n */\nexport async function processSlideContent(\n body: string,\n theme: Theme\n): Promise<string> {\n // Process mermaid diagrams first\n let processed = processMermaidDiagrams(body)\n\n // Apply color tokens\n processed = colorTokensToBlessedTags(processed, theme)\n\n return processed\n}\n\n/**\n * Extract presenter notes from body content.\n *\n * Notes are delimited by `<!-- notes -->` marker.\n * An optional `<!-- /notes -->` end marker can be used to include\n * content after notes in the body.\n *\n * @param content - Raw body content from markdown file\n * @returns Object containing separated body and notes\n */\nexport function extractNotes(content: string): ExtractedNotes {\n const notesStart = content.indexOf(NOTES_MARKER)\n\n if (notesStart === -1) {\n return { body: content }\n }\n\n const body = content.slice(0, notesStart).trim()\n\n // Check for explicit end marker\n const notesEnd = content.indexOf(NOTES_END_MARKER, notesStart)\n\n let notes: string\n if (notesEnd !== -1) {\n notes = content.slice(notesStart + NOTES_MARKER.length, notesEnd).trim()\n } else {\n // Everything after marker is notes\n notes = content.slice(notesStart + NOTES_MARKER.length).trim()\n }\n\n return { body, notes: notes || undefined }\n}\n\n/**\n * Parse a single slide file.\n *\n * Reads the markdown file, extracts frontmatter using gray-matter,\n * extracts presenter notes, and validates the result against the schema.\n *\n * @param filePath - Path to the markdown slide file\n * @param index - The slide index in the deck (0-indexed)\n * @returns Validated Slide object\n * @throws {ValidationError} If frontmatter or slide validation fails\n */\nexport async function parseSlide(\n filePath: string,\n index: number\n): Promise<Slide> {\n // Read file content\n const content = await readFile(filePath, 'utf-8')\n\n // Parse frontmatter with gray-matter\n const { data, content: rawBody } = matter(content)\n\n // Extract notes from body\n const { body, notes } = extractNotes(rawBody)\n\n // Validate frontmatter\n const frontmatter = safeParse(\n SlideFrontmatterSchema,\n data,\n `frontmatter in ${filePath}`\n )\n\n // Build full slide object\n const slide = {\n frontmatter,\n body: body.trim(),\n notes: notes?.trim(),\n sourcePath: filePath,\n index,\n }\n\n // Validate complete slide and return\n return safeParse(SlideSchema, slide, `slide ${filePath}`)\n}\n\n/**\n * Find and sort slide files in a directory.\n *\n * Finds all markdown files (*.md), excludes non-slide files like\n * README.md and files starting with underscore, and sorts them\n * numerically by filename (e.g., 01-intro.md, 02-content.md).\n *\n * @param dir - Directory to search for slide files\n * @returns Array of SlideFile objects sorted by filename\n */\nexport async function findSlideFiles(dir: string): Promise<SlideFile[]> {\n const pattern = join(dir, '*.md')\n const foundFiles = await fg(pattern, { onlyFiles: true })\n\n const files: SlideFile[] = []\n\n for (const filePath of foundFiles) {\n const name = filePath.split('/').pop() || ''\n\n // Skip non-slide files\n if (name === 'README.md' || name.startsWith('_')) {\n continue\n }\n\n files.push({\n path: filePath,\n name,\n index: 0, // Will be set after sorting\n })\n }\n\n // Sort by filename numerically (01-intro.md, 02-problem.md, etc.)\n files.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true }))\n\n // Assign indices after sorting\n files.forEach((file, i) => {\n file.index = i\n })\n\n return files\n}\n\n/**\n * Load deck configuration from deck.config.ts in slides directory.\n *\n * Looks for a deck.config.ts file in the specified directory.\n * If found, dynamically imports and validates it against DeckConfigSchema.\n * If not found, returns a default config with the DEFAULT_THEME.\n *\n * @param slidesDir - Directory to search for deck.config.ts\n * @returns Validated DeckConfig object\n * @throws {ValidationError} If config file exists but fails validation\n */\nexport async function loadDeckConfig(slidesDir: string): Promise<DeckConfig> {\n const configPath = join(slidesDir, 'deck.config.ts')\n\n try {\n // Check if config file exists\n try {\n await access(configPath)\n } catch {\n // File doesn't exist, return default config with DEFAULT_THEME\n return {\n theme: DEFAULT_THEME,\n }\n }\n\n // Dynamic import of TypeScript config\n // Add cache buster to prevent module caching in tests\n const configModule = await import(configPath + '?t=' + Date.now())\n\n if (!configModule.default) {\n throw new Error('deck.config.ts must export default config')\n }\n\n // Validate config against schema\n return safeParse(DeckConfigSchema, configModule.default, 'deck.config.ts')\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'MODULE_NOT_FOUND') {\n // No config file found, use defaults\n return { theme: DEFAULT_THEME }\n }\n throw error\n }\n}\n\n/**\n * Load a complete deck from a directory.\n *\n * Loads the deck configuration, finds all slide files, and parses\n * them in parallel. Returns a Deck object containing all slides,\n * the configuration, and the base path.\n *\n * @param slidesDir - Directory containing slide files and optional deck.config.ts\n * @returns Complete Deck object with slides, config, and basePath\n * @throws {ValidationError} If any slide fails to parse or validate\n */\nexport async function loadDeck(slidesDir: string): Promise<Deck> {\n // Load config first\n const config = await loadDeckConfig(slidesDir)\n\n // Find all markdown files\n const slideFiles = await findSlideFiles(slidesDir)\n\n // Parse all slides in parallel\n const slides = await Promise.all(\n slideFiles.map((file) => parseSlide(file.path, file.index))\n )\n\n return {\n slides,\n config,\n basePath: slidesDir,\n }\n}\n\n/**\n * Normalize bigText to array.\n *\n * Converts the bigText frontmatter field to a consistent array format\n * for use by the renderer. Handles:\n * - undefined → empty array\n * - string → single-element array\n * - string[] → pass through unchanged\n *\n * @param bigText - The bigText value from slide frontmatter\n * @returns Array of strings for rendering\n *\n * @example\n * normalizeBigText(undefined) // []\n * normalizeBigText('HELLO') // ['HELLO']\n * normalizeBigText(['A', 'B']) // ['A', 'B']\n */\nexport function normalizeBigText(bigText: string | string[] | undefined): string[] {\n if (!bigText) return []\n return Array.isArray(bigText) ? bigText : [bigText]\n}\n\n/**\n * Error class for slide parsing failures.\n * Includes the file path of the slide that failed to parse and\n * optionally the underlying cause for error chaining.\n */\nexport class SlideParseError extends Error {\n /**\n * @param message - The error message describing what went wrong\n * @param filePath - Path to the slide file that failed to parse\n * @param cause - Optional underlying error that caused this failure\n */\n constructor(\n message: string,\n public readonly filePath: string,\n public override readonly cause?: Error\n ) {\n super(message)\n this.name = 'SlideParseError'\n }\n}\n\n/**\n * Error class for deck loading failures.\n * Includes the directory path of the slides and optionally\n * the underlying cause for error chaining.\n */\nexport class DeckLoadError extends Error {\n /**\n * @param message - The error message describing what went wrong\n * @param slidesDir - Path to the directory that was being loaded\n * @param cause - Optional underlying error that caused this failure\n */\n constructor(\n message: string,\n public readonly slidesDir: string,\n public override readonly cause?: Error\n ) {\n super(message)\n this.name = 'DeckLoadError'\n }\n}\n\n/**\n * Format a slide parse error for user-friendly display.\n * Creates a multi-line message with the file path, error message,\n * and optional cause chain.\n *\n * @param error - The SlideParseError to format\n * @returns A formatted string suitable for console output\n *\n * @example\n * const error = new SlideParseError(\n * 'Missing required field: title',\n * '/slides/01-intro.md',\n * new Error('Validation failed')\n * )\n * console.log(formatSlideError(error))\n * // Error parsing slide: /slides/01-intro.md\n * // Missing required field: title\n * // Caused by: Validation failed\n */\nexport function formatSlideError(error: SlideParseError): string {\n let msg = `Error parsing slide: ${error.filePath}\\n`\n msg += ` ${error.message}\\n`\n\n if (error.cause) {\n msg += ` Caused by: ${error.cause.message}\\n`\n }\n\n return msg\n}\n","import blessed from 'neo-blessed'\nimport figlet from 'figlet'\nimport gradient from 'gradient-string'\nimport type { Theme } from '../schemas/theme.js'\nimport type { Slide } from '../schemas/slide.js'\nimport { normalizeBigText, processSlideContent } from '../core/slide.js'\n\n/**\n * Main renderer state.\n * Manages the blessed screen, matrix rain background, window stack, and theme.\n */\nexport interface Renderer {\n /** The blessed screen instance */\n screen: blessed.Widgets.Screen\n /** Box element for matrix rain background */\n matrixBox: blessed.Widgets.BoxElement\n /** Stack of window elements (slides render on top of each other) */\n windowStack: blessed.Widgets.BoxElement[]\n /** Active theme for rendering */\n theme: Theme\n /** Array of matrix rain drops for animation */\n matrixDrops: MatrixDrop[]\n /** Interval timer for matrix rain animation (null if stopped) */\n matrixInterval: NodeJS.Timer | null\n}\n\n/**\n * Matrix rain drop.\n * Represents a single falling column of glyphs in the matrix background.\n */\nexport interface MatrixDrop {\n /** Horizontal position (column) */\n x: number\n /** Vertical position (row, can be fractional for smooth animation) */\n y: number\n /** Fall speed (rows per animation frame) */\n speed: number\n /** Array of glyph characters forming the drop's trail */\n trail: string[]\n}\n\n/**\n * Window creation options.\n * Configuration for creating slide windows with stacking effect.\n */\nexport interface WindowOptions {\n /** Window title displayed in the border */\n title: string\n /** Border color (defaults to theme-based cycling) */\n color?: string\n /** Window width (number for absolute, string for percentage) */\n width?: number | string\n /** Window height (number for absolute, string for percentage) */\n height?: number | string\n /** Top position (number for absolute, string for percentage) */\n top?: number | string\n /** Left position (number for absolute, string for percentage) */\n left?: number | string\n}\n\n/**\n * Rendered slide content.\n * Structured content ready for display in a window.\n */\nexport interface RenderedContent {\n /** ASCII art big text (from figlet) */\n bigText?: string\n /** Main body content */\n body: string\n /** Mermaid diagram converted to ASCII */\n diagram?: string\n}\n\n/**\n * Create the main blessed screen.\n * Configures the screen with optimal settings for presentation:\n * - smartCSR: Enables smart cursor movement for efficient rendering\n * - fullUnicode: Enables full unicode support for glyphs\n * - altScreen: Uses alternate screen buffer (preserves terminal on exit)\n * - mouse: Disabled (keyboard-only navigation)\n *\n * @param title - Window title (defaults to 'term-deck')\n * @returns Configured blessed screen instance\n */\nexport function createScreen(title: string = 'term-deck'): blessed.Widgets.Screen {\n const screen = blessed.screen({\n smartCSR: true,\n title,\n fullUnicode: true,\n mouse: false,\n altScreen: true,\n })\n\n return screen\n}\n\n/**\n * Generate a trail of random glyphs.\n * Randomly selects glyphs from the theme's glyph set to form a drop trail.\n *\n * @param glyphs - String of available glyphs to choose from\n * @param length - Number of characters in the trail\n * @returns Array of random glyph characters\n */\nfunction generateTrail(glyphs: string, length: number): string[] {\n return Array.from({ length }, () =>\n glyphs[Math.floor(Math.random() * glyphs.length)]\n )\n}\n\n/**\n * Render one frame of matrix rain.\n * Updates the matrix background with falling glyph trails.\n * This function is called repeatedly by the animation interval.\n *\n * @param renderer - The renderer instance to update\n */\nexport function renderMatrixRain(renderer: Renderer): void {\n const { screen, matrixBox, matrixDrops, theme } = renderer\n const width = Math.max(20, (screen.width as number) || 80)\n const height = Math.max(10, (screen.height as number) || 24)\n\n // Create grid for positioning characters\n const grid: string[][] = Array.from({ length: height }, () =>\n Array(width).fill(' ')\n )\n\n // Update and render drops\n for (const drop of matrixDrops) {\n drop.y += drop.speed\n\n // Reset if off screen\n if (drop.y > height + drop.trail.length) {\n drop.y = -drop.trail.length\n drop.x = Math.floor(Math.random() * width)\n }\n\n // Draw trail\n for (let i = 0; i < drop.trail.length; i++) {\n const y = Math.floor(drop.y) - i\n if (y >= 0 && y < height && drop.x < width) {\n grid[y][drop.x] = drop.trail[i]\n }\n }\n }\n\n // Convert grid to string with colors\n let output = ''\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const char = grid[y][x]\n if (char !== ' ') {\n const brightness = Math.random() > 0.7 ? '{bold}' : ''\n output += `${brightness}{${theme.colors.primary}-fg}${char}{/}`\n } else {\n output += ' '\n }\n }\n if (y < height - 1) output += '\\n'\n }\n\n matrixBox.setContent(output)\n}\n\n/**\n * Initialize matrix rain drops.\n * Creates the initial set of drops and starts the animation loop.\n * This is called automatically by createRenderer.\n *\n * @param renderer - The renderer instance to initialize\n */\nexport function initMatrixRain(renderer: Renderer): void {\n const { screen, theme } = renderer\n const width = (screen.width as number) || 80\n const height = (screen.height as number) || 24\n const density = theme.animations.matrixDensity\n\n renderer.matrixDrops = []\n\n for (let i = 0; i < density; i++) {\n renderer.matrixDrops.push({\n x: Math.floor(Math.random() * width),\n y: Math.floor(Math.random() * height),\n speed: 0.3 + Math.random() * 0.7,\n trail: generateTrail(theme.glyphs, 5 + Math.floor(Math.random() * 10)),\n })\n }\n\n // Start animation loop\n renderer.matrixInterval = setInterval(() => {\n renderMatrixRain(renderer)\n renderer.screen.render()\n }, theme.animations.matrixInterval)\n}\n\n/**\n * Create the renderer with all components.\n * Initializes the blessed screen, matrix rain background box,\n * empty window stack, and starts the matrix rain animation.\n *\n * @param theme - Theme configuration for rendering\n * @returns Fully initialized Renderer instance\n */\nexport function createRenderer(theme: Theme): Renderer {\n const screen = createScreen()\n\n // Create matrix background box covering full screen\n const matrixBox = blessed.box({\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n tags: true,\n })\n screen.append(matrixBox)\n\n const renderer: Renderer = {\n screen,\n matrixBox,\n windowStack: [],\n theme,\n matrixDrops: [],\n matrixInterval: null,\n }\n\n // Initialize matrix rain\n initMatrixRain(renderer)\n\n return renderer\n}\n\n/**\n * Destroy renderer and cleanup resources.\n * Stops the matrix rain animation, destroys all windows in the stack,\n * and destroys the blessed screen to restore the terminal.\n *\n * @param renderer - The renderer instance to destroy\n */\nexport function destroyRenderer(renderer: Renderer): void {\n // Clear matrix rain animation interval\n if (renderer.matrixInterval) {\n clearInterval(renderer.matrixInterval)\n renderer.matrixInterval = null\n }\n\n // Destroy all windows in the stack\n for (const win of renderer.windowStack) {\n win.destroy()\n }\n renderer.windowStack = []\n\n // Destroy the screen (restores terminal)\n renderer.screen.destroy()\n}\n\n/**\n * Get window border color based on index.\n * Cycles through theme colors and additional cyberpunk colors\n * to create a stacking effect with varied border colors.\n *\n * @param index - Window index in the stack\n * @param theme - Theme configuration\n * @returns Hex color string for the window border\n */\nexport function getWindowColor(index: number, theme: Theme): string {\n const colors = [\n theme.colors.primary,\n theme.colors.accent,\n theme.colors.secondary ?? theme.colors.primary,\n '#ff0066', // pink\n '#9966ff', // purple\n '#ffcc00', // yellow\n ]\n return colors[index % colors.length]\n}\n\n/**\n * Create a slide window with stacking effect.\n * Creates a bordered box element with theme-based styling,\n * random position for stacking effect, and adds it to the window stack.\n *\n * @param renderer - The renderer instance\n * @param options - Window configuration options\n * @returns The created window box element\n */\nexport function createWindow(\n renderer: Renderer,\n options: WindowOptions\n): blessed.Widgets.BoxElement {\n const { screen, windowStack, theme } = renderer\n const windowIndex = windowStack.length\n const color = options.color ?? getWindowColor(windowIndex, theme)\n\n const screenWidth = (screen.width as number) || 120\n const screenHeight = (screen.height as number) || 40\n\n // Default dimensions: 75% width, 70% height\n const width = options.width ?? Math.floor(screenWidth * 0.75)\n const height = options.height ?? Math.floor(screenHeight * 0.7)\n\n // Random position within bounds (for stacking effect)\n const maxTop = Math.max(1, screenHeight - (height as number) - 2)\n const maxLeft = Math.max(1, screenWidth - (width as number) - 2)\n const top = options.top ?? Math.floor(Math.random() * maxTop)\n const left = options.left ?? Math.floor(Math.random() * maxLeft)\n\n const window = theme.window ?? { borderStyle: 'line', shadow: true }\n const padding = window.padding ?? { top: 1, bottom: 1, left: 2, right: 2 }\n\n const box = blessed.box({\n top,\n left,\n width,\n height,\n border: {\n type: window.borderStyle === 'none' ? undefined : 'line',\n },\n label: ` ${options.title} `,\n style: {\n fg: theme.colors.text,\n bg: theme.colors.background,\n border: { fg: color },\n label: { fg: color, bold: true },\n },\n padding,\n tags: true,\n shadow: window.shadow,\n })\n\n screen.append(box)\n windowStack.push(box)\n\n return box\n}\n\n/**\n * Clear all windows from stack.\n * Destroys all window elements in the stack and resets the stack to empty.\n * This is typically called when transitioning between slides.\n *\n * @param renderer - The renderer instance containing the window stack\n */\nexport function clearWindows(renderer: Renderer): void {\n for (const window of renderer.windowStack) {\n window.destroy()\n }\n renderer.windowStack = []\n}\n\n/**\n * Generate ASCII art text with gradient.\n * Uses figlet to convert text to ASCII art and applies a gradient color effect.\n * This function is asynchronous because figlet uses a callback-based API.\n *\n * @param text - The text to convert to ASCII art\n * @param gradientColors - Array of hex colors for the gradient effect\n * @param font - Figlet font to use (defaults to 'Standard')\n * @returns Promise resolving to the gradient-colored ASCII art text\n */\nexport async function generateBigText(\n text: string,\n gradientColors: string[],\n font: string = 'Standard'\n): Promise<string> {\n return new Promise((resolve, reject) => {\n figlet.text(text, { font }, (err, result) => {\n if (err || !result) {\n reject(err ?? new Error('Failed to generate figlet text'))\n return\n }\n\n // Apply gradient\n const gradientFn = gradient(gradientColors)\n resolve(gradientFn(result))\n })\n })\n}\n\n/**\n * Generate multi-line big text (for arrays like ['SPEC', 'MACHINE']).\n * Creates ASCII art for each line separately and joins them with newlines.\n * Each line gets the same gradient applied independently.\n *\n * @param lines - Array of text strings to convert to ASCII art\n * @param gradientColors - Array of hex colors for the gradient effect\n * @param font - Figlet font to use (defaults to 'Standard')\n * @returns Promise resolving to the combined gradient-colored ASCII art\n */\nexport async function generateMultiLineBigText(\n lines: string[],\n gradientColors: string[],\n font: string = 'Standard'\n): Promise<string> {\n const results = await Promise.all(\n lines.map((line) => generateBigText(line, gradientColors, font))\n )\n return results.join('\\n')\n}\n\n/**\n * Characters used for glitch effect (avoiding box drawing).\n * These characters create a cyberpunk glitch aesthetic when scrambling text.\n * Includes: block characters, shapes, math symbols, Greek letters, and katakana.\n */\nconst GLITCH_CHARS =\n '█▓▒░▀▄▌▐■□▪▫●○◊◘◙♦♣♠♥★☆⌂ⁿ²³ÆØ∞≈≠±×÷αβγδεζηθλμπσφωΔΣΩアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン'\n\n/**\n * Characters to never glitch.\n * Protects structural characters like spaces, punctuation, box drawing,\n * and arrows to maintain readability and layout integrity during glitch effects.\n */\nconst PROTECTED_CHARS = new Set([\n ' ', '\\t', '\\n', '{', '}', '-', '/', '#', '[', ']', '(', ')', ':', ';',\n ',', '.', '!', '?', \"'\", '\"', '`', '_', '|', '\\\\', '<', '>', '=', '+',\n '*', '&', '^', '%', '$', '@', '~',\n // Box drawing\n '┌', '┐', '└', '┘', '│', '─', '├', '┤', '┬', '┴', '┼', '═', '║',\n '╔', '╗', '╚', '╝', '╠', '╣', '╦', '╩', '╬', '╭', '╮', '╯', '╰',\n // Arrows\n '→', '←', '↑', '↓', '▶', '◀', '▲', '▼', '►', '◄',\n])\n\n/**\n * Sleep helper for async animations.\n * Returns a promise that resolves after the specified delay.\n *\n * @param ms - Delay in milliseconds\n * @returns Promise that resolves after the delay\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Glitch-reveal a single line of text.\n * Animates the transition from scrambled characters to the final text.\n * The scramble ratio decreases with each iteration, gradually revealing the text.\n * Protected characters (spaces, punctuation, box drawing) are never scrambled.\n *\n * @param box - The blessed box element to render into\n * @param screen - The blessed screen for rendering\n * @param currentLines - Array of already-revealed lines\n * @param newLine - The new line to glitch-reveal\n * @param iterations - Number of glitch iterations (default: 5)\n */\nexport async function glitchLine(\n box: blessed.Widgets.BoxElement,\n screen: blessed.Widgets.Screen,\n currentLines: string[],\n newLine: string,\n iterations: number = 5\n): Promise<void> {\n for (let i = iterations; i >= 0; i--) {\n const scrambleRatio = i / iterations\n let scrambledLine = ''\n\n for (const char of newLine) {\n if (PROTECTED_CHARS.has(char)) {\n scrambledLine += char\n } else if (Math.random() < scrambleRatio) {\n scrambledLine += GLITCH_CHARS[Math.floor(Math.random() * GLITCH_CHARS.length)]\n } else {\n scrambledLine += char\n }\n }\n\n box.setContent([...currentLines, scrambledLine].join('\\n'))\n screen.render()\n await sleep(20)\n }\n}\n\n/**\n * Reveal content line by line with glitch effect.\n * Animates the transition of multi-line content by revealing each line\n * sequentially with a glitch effect. Uses theme-configured line delay\n * and glitch iteration count for consistent animation timing.\n *\n * @param box - The blessed box element to render into\n * @param screen - The blessed screen for rendering\n * @param content - The complete content string (with newlines)\n * @param theme - Theme configuration for animation timing\n */\nexport async function lineByLineReveal(\n box: blessed.Widgets.BoxElement,\n screen: blessed.Widgets.Screen,\n content: string,\n theme: Theme\n): Promise<void> {\n const lines = content.split('\\n')\n const revealedLines: string[] = []\n const lineDelay = theme.animations.lineDelay\n const glitchIterations = theme.animations.glitchIterations\n\n for (const line of lines) {\n await glitchLine(box, screen, revealedLines, line, glitchIterations)\n revealedLines.push(line)\n box.setContent(revealedLines.join('\\n'))\n screen.render()\n\n // Delay between lines (skip for empty lines)\n if (line.trim()) {\n await sleep(lineDelay)\n }\n }\n}\n\n/**\n * Transition type for slide animations.\n * Defines the available transition effects for revealing slide content.\n */\nexport type TransitionType = 'glitch' | 'fade' | 'instant' | 'typewriter'\n\n/**\n * Fade-in reveal (character by character, all at once).\n * Gradually reveals characters randomly across the entire content\n * to create a fade-in effect. Uses multiple steps with increasing\n * reveal probability for a smooth animation.\n *\n * @param box - The blessed box element to render into\n * @param screen - The blessed screen for rendering\n * @param content - The complete content string to reveal\n * @param theme - Theme configuration for animation timing\n */\nasync function fadeInReveal(\n box: blessed.Widgets.BoxElement,\n screen: blessed.Widgets.Screen,\n content: string,\n theme: Theme\n): Promise<void> {\n const steps = 10\n const delay = (theme.animations.lineDelay * 2) / steps\n\n for (let step = 0; step < steps; step++) {\n const revealRatio = step / steps\n let revealed = ''\n\n for (const char of content) {\n if (char === '\\n' || PROTECTED_CHARS.has(char) || Math.random() < revealRatio) {\n revealed += char\n } else {\n revealed += ' '\n }\n }\n\n box.setContent(revealed)\n screen.render()\n await sleep(delay)\n }\n\n box.setContent(content)\n screen.render()\n}\n\n/**\n * Typewriter reveal (character by character, sequentially).\n * Reveals content character by character in order, like a typewriter.\n * Skips delay for spaces and newlines to maintain smooth flow.\n *\n * @param box - The blessed box element to render into\n * @param screen - The blessed screen for rendering\n * @param content - The complete content string to reveal\n * @param theme - Theme configuration for animation timing\n */\nasync function typewriterReveal(\n box: blessed.Widgets.BoxElement,\n screen: blessed.Widgets.Screen,\n content: string,\n theme: Theme\n): Promise<void> {\n const charDelay = theme.animations.lineDelay / 5\n let revealed = ''\n\n for (const char of content) {\n revealed += char\n box.setContent(revealed)\n screen.render()\n\n if (char !== ' ' && char !== '\\n') {\n await sleep(charDelay)\n }\n }\n}\n\n/**\n * Apply transition effect to reveal content.\n * Dispatcher function that selects and applies the appropriate\n * transition animation based on the specified transition type.\n *\n * @param box - The blessed box element to render into\n * @param screen - The blessed screen for rendering\n * @param content - The complete content string to reveal\n * @param transition - The type of transition effect to apply\n * @param theme - Theme configuration for animation timing\n */\nexport async function applyTransition(\n box: blessed.Widgets.BoxElement,\n screen: blessed.Widgets.Screen,\n content: string,\n transition: TransitionType,\n theme: Theme\n): Promise<void> {\n switch (transition) {\n case 'glitch':\n await lineByLineReveal(box, screen, content, theme)\n break\n\n case 'fade':\n await fadeInReveal(box, screen, content, theme)\n break\n\n case 'instant':\n box.setContent(content)\n screen.render()\n break\n\n case 'typewriter':\n await typewriterReveal(box, screen, content, theme)\n break\n\n default:\n box.setContent(content)\n screen.render()\n }\n}\n\n/**\n * Render a slide to a window.\n * Creates a window, generates bigText if present, processes the body content,\n * and applies the specified transition effect to reveal the slide.\n *\n * @param renderer - The renderer instance\n * @param slide - The slide to render\n * @returns The created window box element containing the rendered slide\n */\nexport async function renderSlide(\n renderer: Renderer,\n slide: Slide\n): Promise<blessed.Widgets.BoxElement> {\n const { theme } = renderer\n const { frontmatter, body } = slide\n\n // Create window\n const window = createWindow(renderer, {\n title: frontmatter.title,\n })\n\n // Build content\n let content = ''\n\n // Big text (figlet)\n const bigTextLines = normalizeBigText(frontmatter.bigText)\n if (bigTextLines.length > 0) {\n const gradientName = frontmatter.gradient ?? 'fire'\n const gradientColors = theme.gradients[gradientName] ?? theme.gradients.fire\n\n const bigText = await generateMultiLineBigText(bigTextLines, gradientColors)\n content += bigText + '\\n\\n'\n }\n\n // Process body content (color tokens, mermaid)\n const processedBody = await processSlideContent(body, theme)\n content += processedBody\n\n // Apply transition\n const transition = frontmatter.transition ?? 'glitch'\n await applyTransition(window, renderer.screen, content, transition, theme)\n\n return window\n}\n","import blessed from 'neo-blessed';\nimport { access } from 'fs/promises';\nimport type { Deck } from '../core/slide.js';\nimport type { Renderer } from '../renderer/screen.js';\nimport { loadDeck } from '../core/slide.js';\nimport { createRenderer, destroyRenderer, renderSlide, clearWindows } from '../renderer/screen.js';\n\n/**\n * Presenter state\n *\n * Manages the state of the active presentation including:\n * - The loaded deck with slides and configuration\n * - The renderer instance for displaying slides\n * - Current slide index\n * - Animation state to prevent concurrent navigation\n * - Optional notes window for presenter mode\n * - Optional auto-advance timer\n * - Optional progress bar\n */\nexport interface Presenter {\n deck: Deck;\n renderer: Renderer;\n currentSlide: number;\n isAnimating: boolean;\n notesWindow: NotesWindow | null;\n autoAdvanceTimer: NodeJS.Timer | null;\n progressBar: blessed.Widgets.ProgressBarElement | null;\n}\n\n/**\n * Notes window state (separate terminal)\n *\n * Represents a secondary display on a different TTY for presenter notes.\n * Shows current slide notes, slide number, and preview of next slide.\n */\nexport interface NotesWindow {\n screen: blessed.Widgets.Screen;\n contentBox: blessed.Widgets.BoxElement;\n tty: string; // TTY device path (e.g., '/dev/tty2')\n}\n\n/**\n * Presentation options\n *\n * Configuration options for starting a presentation:\n * - startSlide: Index of slide to start from (defaults to 0)\n * - showNotes: Whether to open a notes window on separate TTY\n * - notesTty: Specific TTY device path for notes (optional, will auto-detect if not provided)\n * - loop: Whether to loop back to first slide after reaching the end\n */\nexport interface PresentOptions {\n startSlide?: number;\n showNotes?: boolean;\n notesTty?: string;\n loop?: boolean;\n}\n\n/**\n * Start a presentation\n *\n * Loads the deck, creates the renderer, sets up keyboard controls,\n * and enters the main presentation loop.\n *\n * @param slidesDir - Directory containing markdown slides and deck.config.ts\n * @param options - Presentation options (startSlide, showNotes, notesTty, loop)\n * @returns Promise that resolves when the presentation ends (user quits)\n *\n * @example\n * ```typescript\n * await present('./slides', { startSlide: 0, showNotes: true });\n * ```\n */\nexport async function present(\n slidesDir: string,\n options: PresentOptions = {}\n): Promise<void> {\n // Load deck\n const deck = await loadDeck(slidesDir);\n\n if (deck.slides.length === 0) {\n throw new Error(`No slides found in ${slidesDir}`);\n }\n\n // Create renderer\n const renderer = createRenderer(deck.config.theme);\n\n // Create presenter state\n const presenter: Presenter = {\n deck,\n renderer,\n currentSlide: options.startSlide ?? deck.config.settings?.startSlide ?? 0,\n isAnimating: false,\n notesWindow: null,\n autoAdvanceTimer: null,\n progressBar: null,\n };\n\n // Setup notes window if requested\n if (options.showNotes) {\n presenter.notesWindow = await createNotesWindow(options.notesTty);\n }\n\n // Setup progress bar if enabled\n if (deck.config.settings?.showProgress) {\n presenter.progressBar = createProgressBar(presenter);\n }\n\n // Setup keyboard controls\n setupControls(presenter);\n\n // Show first slide\n await showSlide(presenter, presenter.currentSlide);\n\n // Update progress bar\n if (presenter.progressBar) {\n updateProgress(presenter.progressBar, presenter.currentSlide, deck.slides.length);\n }\n\n // Start auto-advance if configured\n presenter.autoAdvanceTimer = startAutoAdvance(presenter);\n\n // Keep process alive until quit\n await new Promise<void>((resolve) => {\n renderer.screen.key(['q', 'C-c', 'escape'], () => {\n cleanup(presenter);\n resolve();\n });\n });\n}\n\n/**\n * Cleanup resources\n *\n * Destroys the notes window (if present), stops auto-advance timer,\n * and destroys the main renderer, freeing all resources and restoring the terminal.\n *\n * @param presenter - The presenter state to clean up\n */\nfunction cleanup(presenter: Presenter): void {\n stopAutoAdvance(presenter.autoAdvanceTimer);\n if (presenter.notesWindow) {\n presenter.notesWindow.screen.destroy();\n }\n destroyRenderer(presenter.renderer);\n}\n\n/**\n * Show a specific slide (placeholder for task 5.4)\n */\nasync function showSlide(presenter: Presenter, index: number): Promise<void> {\n if (presenter.isAnimating) return;\n if (index < 0 || index >= presenter.deck.slides.length) return;\n\n presenter.isAnimating = true;\n presenter.currentSlide = index;\n\n const slide = presenter.deck.slides[index];\n\n // Render slide\n await renderSlide(presenter.renderer, slide);\n presenter.renderer.screen.render();\n\n // Update notes window\n if (presenter.notesWindow) {\n updateNotesWindow(presenter);\n }\n\n // Update progress bar\n if (presenter.progressBar) {\n updateProgress(presenter.progressBar, presenter.currentSlide, presenter.deck.slides.length);\n }\n\n presenter.isAnimating = false;\n}\n\n/**\n * Go to next slide\n *\n * Advances to the next slide in the deck. If at the last slide:\n * - If loop is enabled, wraps to first slide\n * - If loop is disabled, stays on last slide\n *\n * @param presenter - The presenter state\n */\nexport async function nextSlide(presenter: Presenter): Promise<void> {\n const nextIndex = presenter.currentSlide + 1;\n const { slides } = presenter.deck;\n const loop = presenter.deck.config.settings?.loop ?? false;\n\n if (nextIndex >= slides.length) {\n if (loop) {\n await showSlide(presenter, 0);\n }\n return;\n }\n\n await showSlide(presenter, nextIndex);\n}\n\n/**\n * Go to previous slide\n *\n * Goes back to the previous slide in the deck. If at the first slide:\n * - If loop is enabled, wraps to last slide\n * - If loop is disabled, stays on first slide\n *\n * To maintain the stacked window effect, this function clears all windows\n * and re-renders all slides from 0 up to the target slide.\n *\n * @param presenter - The presenter state\n */\nexport async function prevSlide(presenter: Presenter): Promise<void> {\n const prevIndex = presenter.currentSlide - 1;\n const { slides } = presenter.deck;\n const loop = presenter.deck.config.settings?.loop ?? false;\n\n if (prevIndex < 0) {\n if (loop) {\n // Clear and re-render all slides up to the last one\n clearWindows(presenter.renderer);\n for (let i = 0; i < slides.length; i++) {\n await renderSlide(presenter.renderer, slides[i]);\n }\n presenter.currentSlide = slides.length - 1;\n\n // Update notes window\n if (presenter.notesWindow) {\n updateNotesWindow(presenter);\n }\n\n // Update progress bar\n if (presenter.progressBar) {\n updateProgress(presenter.progressBar, presenter.currentSlide, presenter.deck.slides.length);\n }\n\n presenter.renderer.screen.render();\n }\n // If not looping, stay at current slide (index 0)\n return;\n }\n\n // Clear windows and re-render from start up to prevIndex\n clearWindows(presenter.renderer);\n for (let i = 0; i <= prevIndex; i++) {\n await renderSlide(presenter.renderer, slides[i]);\n }\n\n presenter.currentSlide = prevIndex;\n\n // Update notes window\n if (presenter.notesWindow) {\n updateNotesWindow(presenter);\n }\n\n // Update progress bar\n if (presenter.progressBar) {\n updateProgress(presenter.progressBar, presenter.currentSlide, presenter.deck.slides.length);\n }\n\n // Render screen to display changes\n presenter.renderer.screen.render();\n}\n\n/**\n * Jump to a specific slide by index\n *\n * Jumps directly to the specified slide index. To maintain the stacked window\n * effect, this function clears all windows and re-renders all slides from 0\n * up to the target slide.\n *\n * Invalid indices (negative or beyond deck length) are ignored.\n *\n * @param presenter - The presenter state\n * @param index - The slide index to jump to (0-based)\n */\nexport async function jumpToSlide(presenter: Presenter, index: number): Promise<void> {\n // Check bounds - ignore invalid indices\n if (index < 0 || index >= presenter.deck.slides.length) return;\n\n // Clear all windows to prepare for re-rendering\n clearWindows(presenter.renderer);\n\n // Re-render slides 0 through target index to preserve stacking\n for (let i = 0; i <= index; i++) {\n await renderSlide(presenter.renderer, presenter.deck.slides[i]);\n }\n\n // Update current slide\n presenter.currentSlide = index;\n\n // Update notes window if present\n if (presenter.notesWindow) {\n updateNotesWindow(presenter);\n }\n\n // Update progress bar\n if (presenter.progressBar) {\n updateProgress(presenter.progressBar, presenter.currentSlide, presenter.deck.slides.length);\n }\n\n // Render screen to display changes\n presenter.renderer.screen.render();\n}\n\n/**\n * Setup keyboard event handlers\n *\n * Registers all keyboard controls for the presentation:\n * - Next slide: Space, Enter, Right, n\n * - Previous slide: Left, Backspace, p\n * - Jump to slide: 0-9\n * - Show slide list: l\n * - Toggle notes visibility: N\n * - Quit: q, Ctrl+C, Escape (handled in present() function)\n *\n * @param presenter - The presenter state\n */\nfunction setupControls(presenter: Presenter): void {\n const { screen } = presenter.renderer;\n\n // Next slide: Space, Enter, Right, n\n screen.key(['space', 'enter', 'right', 'n'], () => {\n nextSlide(presenter);\n });\n\n // Previous slide: Left, Backspace, p\n screen.key(['left', 'backspace', 'p'], () => {\n prevSlide(presenter);\n });\n\n // Jump to slide: 0-9\n screen.key(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], (ch) => {\n const index = parseInt(ch, 10);\n jumpToSlide(presenter, index);\n });\n\n // Show slide list: l\n screen.key(['l'], () => {\n showSlideList(presenter);\n });\n\n // Toggle notes visibility: N (only if notes window exists)\n screen.key(['N'], () => {\n if (presenter.notesWindow) {\n toggleNotesVisibility(presenter.notesWindow);\n }\n });\n\n // Note: quit keys (q, Ctrl+C, Escape) are handled in the present() function\n}\n\n/**\n * Show slide list overlay\n *\n * Displays an overlay showing all slides in the deck with the current slide marked.\n * User can press Escape, l, or q to close, or press a number key to jump to that slide.\n *\n * @param presenter - The presenter state\n */\nfunction showSlideList(presenter: Presenter): void {\n const { screen } = presenter.renderer;\n const { slides } = presenter.deck;\n\n // Build list content with current slide marker\n const listContent = slides\n .map((slide, i) => {\n const marker = i === presenter.currentSlide ? '▶ ' : ' ';\n return `${marker}${i}: ${slide.frontmatter.title}`;\n })\n .join('\\n');\n\n // Create overlay box centered on screen\n const listBox = screen.box({\n top: 'center',\n left: 'center',\n width: 50,\n height: Math.min(slides.length + 4, 20),\n border: { type: 'line' },\n label: ' SLIDES (press number or Esc) ',\n style: {\n fg: '#ffffff',\n bg: '#0a0a0a',\n border: { fg: '#ffcc00' },\n },\n padding: 1,\n tags: true,\n content: listContent,\n });\n\n screen.append(listBox);\n\n screen.render();\n\n // Close list helper\n const closeList = () => {\n listBox.destroy();\n screen.render();\n };\n\n // Close on Escape, l, or q\n screen.onceKey(['escape', 'l', 'q'], closeList);\n\n // Number keys jump to slide and close\n screen.onceKey(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], (ch) => {\n closeList();\n jumpToSlide(presenter, parseInt(ch ?? '0', 10));\n });\n}\n\n/**\n * Toggle notes window visibility\n *\n * Toggles the visibility of the notes window between shown and hidden.\n *\n * @param notesWindow - The notes window to toggle\n */\nfunction toggleNotesVisibility(notesWindow: NotesWindow): void {\n const { contentBox, screen } = notesWindow;\n contentBox.toggle();\n screen.render();\n}\n\n/**\n * Find an available TTY for notes window\n *\n * This is a best-effort approach - user should specify with --notes-tty.\n * Searches common TTY paths on macOS and Linux.\n *\n * @returns Promise resolving to an available TTY path\n * @throws Error if no available TTY is found\n */\nasync function findAvailableTty(): Promise<string> {\n // On macOS, try common TTY paths\n const candidates = [\n '/dev/ttys001',\n '/dev/ttys002',\n '/dev/ttys003',\n '/dev/pts/1',\n '/dev/pts/2',\n ];\n\n for (const tty of candidates) {\n try {\n await access(tty);\n return tty;\n } catch {\n // Continue to next candidate\n }\n }\n\n throw new Error(\n 'Could not find available TTY for notes window. ' +\n 'Open a second terminal, run `tty`, and pass the path with --notes-tty'\n );\n}\n\n/**\n * Create notes window on a separate TTY\n *\n * Creates a blessed screen on a different TTY device for displaying presenter notes.\n * If no TTY is specified, attempts to find one automatically.\n *\n * Usage: Open a second terminal and run `tty` to get the device path,\n * then pass it with --notes-tty /dev/ttys001\n *\n * @param ttyPath - Optional TTY device path (e.g., '/dev/ttys001')\n * @returns Promise resolving to the created notes window\n *\n * @example\n * ```typescript\n * // With explicit TTY path\n * const notesWindow = await createNotesWindow('/dev/ttys001');\n *\n * // Auto-detect TTY\n * const notesWindow = await createNotesWindow();\n * ```\n */\nasync function createNotesWindow(ttyPath?: string): Promise<NotesWindow> {\n const blessed = (await import('neo-blessed')).default;\n const { openSync } = await import('node:fs');\n\n // If no TTY specified, try to find one\n const tty = ttyPath ?? await findAvailableTty();\n\n // Create screen on the specified TTY\n const screen = blessed.screen({\n smartCSR: true,\n title: 'term-deck notes',\n fullUnicode: true,\n input: openSync(tty, 'r'),\n output: openSync(tty, 'w'),\n });\n\n // Create content box\n const contentBox = blessed.box({\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n tags: true,\n padding: 2,\n style: {\n fg: '#ffffff',\n bg: '#1a1a1a',\n },\n });\n\n screen.append(contentBox);\n screen.render();\n\n return {\n screen,\n contentBox,\n tty,\n };\n}\n\n/**\n * Update notes window content for current slide\n *\n * Updates the notes window to display:\n * - Current slide number and title\n * - Presenter notes (or \"No notes\" if none exist)\n * - Preview of next slide title (or \"Last slide\" if at end)\n *\n * @param presenter - The presenter state\n */\nfunction updateNotesWindow(presenter: Presenter): void {\n if (!presenter.notesWindow) return;\n\n const { contentBox, screen } = presenter.notesWindow;\n const { slides } = presenter.deck;\n const currentIndex = presenter.currentSlide;\n const currentSlide = slides[currentIndex];\n const nextSlide = slides[currentIndex + 1];\n\n // Build notes content\n let content = '';\n\n // Header\n content += `{bold}Slide ${currentIndex + 1} of ${slides.length}{/bold}\\n`;\n content += `{gray-fg}${currentSlide.frontmatter.title}{/}\\n`;\n content += '\\n';\n content += '─'.repeat(50) + '\\n';\n content += '\\n';\n\n // Notes\n if (currentSlide.notes) {\n content += '{bold}PRESENTER NOTES:{/bold}\\n\\n';\n content += currentSlide.notes + '\\n';\n } else {\n content += '{gray-fg}No notes for this slide{/}\\n';\n }\n\n content += '\\n';\n content += '─'.repeat(50) + '\\n';\n content += '\\n';\n\n // Next slide preview\n if (nextSlide) {\n content += `{bold}NEXT:{/bold} \"${nextSlide.frontmatter.title}\"\\n`;\n } else {\n content += '{gray-fg}Last slide{/}\\n';\n }\n\n contentBox.setContent(content);\n screen.render();\n}\n\n/**\n * Start auto-advance timer\n *\n * Automatically advances to the next slide at a specified interval.\n * Respects the isAnimating flag to avoid advancing during animations.\n * Returns null if auto-advance is disabled (interval <= 0).\n *\n * @param presenter - The presenter state\n * @returns Timer object if auto-advance is enabled, null otherwise\n */\nfunction startAutoAdvance(presenter: Presenter): NodeJS.Timer | null {\n const interval = presenter.deck.config.settings?.autoAdvance;\n\n // Auto-advance disabled if interval is undefined, 0, or negative\n if (!interval || interval <= 0) {\n return null;\n }\n\n // Start interval timer\n return setInterval(() => {\n // Only advance if not currently animating\n if (!presenter.isAnimating) {\n nextSlide(presenter);\n }\n }, interval);\n}\n\n/**\n * Stop auto-advance timer\n *\n * Clears the auto-advance interval timer if it exists.\n *\n * @param timer - The timer to stop (can be null)\n */\nfunction stopAutoAdvance(timer: NodeJS.Timer | null): void {\n if (timer) {\n clearInterval(timer);\n }\n}\n\n/**\n * Create progress bar at bottom of screen\n *\n * Creates a horizontal progress bar that shows presentation progress.\n * The bar is positioned at the bottom of the screen and fills from left\n * to right as the presentation advances.\n *\n * @param presenter - The presenter state\n * @returns Progress bar element\n */\nfunction createProgressBar(presenter: Presenter): blessed.Widgets.ProgressBarElement {\n const { screen } = presenter.renderer;\n\n const progressBar = blessed.progressbar({\n bottom: 0,\n left: 0,\n width: '100%',\n height: 1,\n style: {\n bg: '#333333',\n bar: { bg: '#00cc66' },\n },\n filled: 0,\n });\n\n screen.append(progressBar);\n\n return progressBar;\n}\n\n/**\n * Update progress bar\n *\n * Updates the progress bar to reflect the current slide position.\n * Progress is calculated as (current + 1) / total * 100.\n *\n * @param progressBar - The progress bar element to update\n * @param current - Current slide index (0-based)\n * @param total - Total number of slides\n */\nfunction updateProgress(\n progressBar: blessed.Widgets.ProgressBarElement,\n current: number,\n total: number\n): void {\n const progress = ((current + 1) / total) * 100;\n progressBar.setProgress(progress);\n}\n","#!/usr/bin/env node\n/**\n * CLI Entry Point for term-deck\n *\n * Terminal presentation tool with a cyberpunk aesthetic.\n * Provides commands for presenting, exporting, and initializing decks.\n */\n\nimport { Command } from 'commander';\nimport { version } from '../package.json';\nimport { presentCommand } from '../src/cli/commands/present.js';\nimport { exportCommand } from '../src/cli/commands/export.js';\nimport { initCommand } from '../src/cli/commands/init.js';\nimport { handleError } from '../src/cli/errors.js';\n\nconst program = new Command();\n\nprogram\n .name('term-deck')\n .description('Terminal presentation tool with a cyberpunk aesthetic')\n .version(version);\n\n// Register commands\nprogram.addCommand(presentCommand);\nprogram.addCommand(exportCommand);\nprogram.addCommand(initCommand);\n\n// Default action: present if directory given, else show help\nprogram\n .argument('[dir]', 'Slides directory to present')\n .action(async (dir) => {\n if (dir) {\n // Default action: present the deck\n try {\n const { present } = await import('../src/presenter/main.js');\n await present(dir, {});\n } catch (error) {\n handleError(error);\n }\n } else {\n program.help();\n }\n });\n\nprogram.parse();\n","{\n \"name\": \"@pep/term-deck\",\n \"version\": \"1.0.15\",\n \"description\": \"Terminal presentation tool with a cyberpunk aesthetic\",\n \"type\": \"module\",\n \"bin\": {\n \"term-deck\": \"./dist/bin/term-deck.js\"\n },\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"scripts\": {\n \"dev\": \"tsx bin/term-deck.ts\",\n \"build\": \"tsup\",\n \"prepublishOnly\": \"pnpm run build\",\n \"test\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\"\n },\n \"keywords\": [\n \"presentation\",\n \"terminal\",\n \"slides\",\n \"cli\",\n \"tui\",\n \"blessed\",\n \"cyberpunk\",\n \"markdown\"\n ],\n \"author\": \"Pepijn Senders\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/PepijnSenders/term-deck.git\"\n },\n \"bugs\": {\n \"url\": \"https://github.com/PepijnSenders/term-deck/issues\"\n },\n \"homepage\": \"https://github.com/PepijnSenders/term-deck#readme\",\n \"engines\": {\n \"node\": \">=18.0.0\"\n },\n \"files\": [\n \"dist/\",\n \"themes/\",\n \"examples/\",\n \"LICENSE\",\n \"README.md\"\n ],\n \"dependencies\": {\n \"canvas\": \"^3.2.1\",\n \"commander\": \"^14.0.2\",\n \"deepmerge\": \"^4.3.1\",\n \"execa\": \"^9.6.1\",\n \"fast-glob\": \"^3.3.3\",\n \"figlet\": \"^1.9.4\",\n \"gradient-string\": \"^3.0.0\",\n \"gray-matter\": \"^4.0.3\",\n \"mermaid-ascii\": \"^1.0.0\",\n \"neo-blessed\": \"^0.2.0\",\n \"yaml\": \"^2.7.0\",\n \"zod\": \"^3.22.4\"\n },\n \"devDependencies\": {\n \"@types/figlet\": \"^1.5.8\",\n \"@types/node\": \"^22.0.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^2.1.8\"\n }\n}\n","/**\n * Present Command\n *\n * Starts a presentation with the given options.\n */\n\nimport { Command } from 'commander';\nimport { present } from '../../presenter/main.js';\nimport { handleError } from '../errors.js';\n\nexport const presentCommand = new Command('present')\n .description('Start a presentation')\n .argument('<dir>', 'Slides directory')\n .option('-s, --start <n>', 'Start at slide number', '0')\n .option('-n, --notes', 'Show presenter notes in separate terminal')\n .option('--notes-tty <path>', 'TTY device for notes window (e.g., /dev/ttys001)')\n .option('-l, --loop', 'Loop back to first slide after last')\n .action(async (dir, options) => {\n try {\n await present(dir, {\n startSlide: Number.parseInt(options.start, 10),\n showNotes: options.notes,\n notesTty: options.notesTty,\n loop: options.loop,\n });\n } catch (error) {\n handleError(error);\n }\n });\n","/**\n * CLI Error Handling\n *\n * Provides user-friendly error messages for various error types\n * that can occur during CLI operations.\n */\n\nimport { ValidationError } from '../schemas/validation.js';\nimport { SlideParseError, DeckLoadError } from '../core/slide.js';\nimport { ThemeError } from '../core/theme.js';\n\n/**\n * Handle CLI errors with user-friendly messages\n *\n * Converts various error types into readable console output\n * and exits with appropriate status code.\n */\nexport function handleError(error: unknown): never {\n if (error instanceof ValidationError) {\n console.error(`\\n${error.message}`);\n process.exit(1);\n }\n\n if (error instanceof SlideParseError) {\n console.error(`\\nSlide error in ${error.filePath}:`);\n console.error(` ${error.message}`);\n if (error.cause) {\n const causeMessage = error.cause instanceof Error ? error.cause.message : String(error.cause);\n console.error(` Caused by: ${causeMessage}`);\n }\n process.exit(1);\n }\n\n if (error instanceof DeckLoadError) {\n console.error(`\\nFailed to load deck from ${error.slidesDir}:`);\n console.error(` ${error.message}`);\n process.exit(1);\n }\n\n if (error instanceof ThemeError) {\n console.error('\\nTheme error:');\n console.error(` ${error.message}`);\n process.exit(1);\n }\n\n if (error instanceof Error) {\n // Check for common issues\n if (error.message.includes('ENOENT')) {\n console.error('\\nFile or directory not found.');\n console.error(` ${error.message}`);\n process.exit(1);\n }\n\n if (error.message.includes('ffmpeg')) {\n console.error('\\nffmpeg error:');\n console.error(` ${error.message}`);\n console.error('\\nMake sure ffmpeg is installed:');\n console.error(' macOS: brew install ffmpeg');\n console.error(' Ubuntu: sudo apt install ffmpeg');\n process.exit(1);\n }\n\n // Generic error\n console.error(`\\nError: ${error.message}`);\n\n if (process.env.DEBUG) {\n console.error(error.stack);\n }\n\n process.exit(1);\n }\n\n // Unknown error\n console.error('\\nUnknown error occurred');\n console.error(error);\n process.exit(1);\n}\n","/**\n * Export Command\n *\n * Exports a presentation to GIF or MP4 format.\n */\n\nimport { Command } from 'commander';\nimport { exportPresentation } from '../../export/recorder.js';\nimport { handleError } from '../errors.js';\n\nexport const exportCommand = new Command('export')\n .description('Export presentation to GIF or MP4')\n .argument('<dir>', 'Slides directory')\n .requiredOption('-o, --output <file>', 'Output file (.mp4 or .gif)')\n .option('-w, --width <n>', 'Terminal width in characters', '120')\n .option('-h, --height <n>', 'Terminal height in characters', '40')\n .option('--fps <n>', 'Frames per second', '30')\n .option('-t, --slide-time <n>', 'Seconds per slide', '3')\n .option('-q, --quality <n>', 'Quality 1-100 (video only)', '80')\n .action(async (dir, options) => {\n try {\n await exportPresentation(dir, {\n output: options.output,\n width: Number.parseInt(options.width, 10),\n height: Number.parseInt(options.height, 10),\n fps: Number.parseInt(options.fps, 10),\n slideTime: Number.parseFloat(options.slideTime),\n quality: Number.parseInt(options.quality, 10),\n });\n } catch (error) {\n handleError(error);\n }\n });\n","/**\n * Export Data Structures\n *\n * This module defines the core interfaces and types for exporting presentations\n * to video (MP4) or GIF formats.\n */\n\nimport { writeFile, unlink } from 'fs/promises';\nimport { execa } from 'execa';\n\n/**\n * Export options\n */\nexport interface ExportOptions {\n /** Output file path (.mp4 or .gif) */\n output: string\n /** Terminal width in characters */\n width?: number\n /** Terminal height in characters */\n height?: number\n /** Frames per second */\n fps?: number\n /** Time per slide in seconds (for auto-advance) */\n slideTime?: number\n /** Quality (1-100, only for video) */\n quality?: number\n}\n\n/**\n * Export format\n */\nexport type ExportFormat = 'mp4' | 'gif'\n\n/**\n * Asciicast v2 format header\n * https://docs.asciinema.org/manual/asciicast/v2/\n */\nexport interface AsciicastHeader {\n version: 2\n width: number\n height: number\n timestamp?: number\n env?: Record<string, string>\n}\n\n/**\n * Asciicast frame: [time, stream, data]\n * time: timestamp in seconds\n * stream: 'o' for stdout, 'i' for stdin\n * data: the text content\n */\nexport type AsciicastFrame = [number, 'o' | 'i', string]\n\n/**\n * Recording session state\n */\nexport interface RecordingSession {\n tempDir: string\n frameCount: number\n width: number\n height: number\n fps: number\n}\n\n/**\n * Virtual terminal buffer for capturing frames\n *\n * We render to a string buffer and convert to images\n */\nexport class VirtualTerminal {\n private buffer: string[][]\n private colors: string[][]\n\n constructor(\n public width: number,\n public height: number\n ) {\n this.buffer = Array.from({ length: height }, () =>\n Array(width).fill(' ')\n )\n this.colors = Array.from({ length: height }, () =>\n Array(width).fill('#ffffff')\n )\n }\n\n /**\n * Set character at position\n */\n setChar(x: number, y: number, char: string, color: string = '#ffffff'): void {\n if (x >= 0 && x < this.width && y >= 0 && y < this.height) {\n this.buffer[y][x] = char\n this.colors[y][x] = color\n }\n }\n\n /**\n * Clear the buffer\n */\n clear(): void {\n for (let y = 0; y < this.height; y++) {\n for (let x = 0; x < this.width; x++) {\n this.buffer[y][x] = ' '\n this.colors[y][x] = '#ffffff'\n }\n }\n }\n\n /**\n * Get buffer as string (for debugging)\n */\n toString(): string {\n return this.buffer.map((row) => row.join('')).join('\\n')\n }\n\n /**\n * Convert buffer to PNG image data\n */\n async toPng(): Promise<Uint8Array> {\n // Use canvas or similar to render text to image\n return renderTerminalToPng(this.buffer, this.colors, this.width, this.height)\n }\n}\n\n// Character dimensions in pixels (monospace font)\nconst CHAR_WIDTH = 10\nconst CHAR_HEIGHT = 20\n\n/**\n * Render terminal buffer to PNG\n */\nasync function renderTerminalToPng(\n buffer: string[][],\n colors: string[][],\n width: number,\n height: number\n): Promise<Uint8Array> {\n // Dynamic import to avoid bundling issues\n const { createCanvas } = await import('canvas')\n\n const canvas = createCanvas(width * CHAR_WIDTH, height * CHAR_HEIGHT)\n const ctx = canvas.getContext('2d')\n\n // Background\n ctx.fillStyle = '#0a0a0a'\n ctx.fillRect(0, 0, canvas.width, canvas.height)\n\n // Set font\n ctx.font = `${CHAR_HEIGHT - 4}px monospace`\n ctx.textBaseline = 'top'\n\n // Render each character\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const char = buffer[y][x]\n const color = colors[y][x]\n\n if (char !== ' ') {\n ctx.fillStyle = color\n ctx.fillText(char, x * CHAR_WIDTH, y * CHAR_HEIGHT + 2)\n }\n }\n }\n\n return canvas.toBuffer('image/png')\n}\n\n/**\n * Capture blessed screen content to virtual terminal\n *\n * This parses the blessed screen's internal buffer\n */\nexport function captureScreen(\n screen: any, // neo-blessed screen type\n vt: VirtualTerminal\n): void {\n // blessed stores screen content in screen.lines\n // Each line is an array of cells with char, fg, bg\n\n const lines = screen.lines || []\n\n for (let y = 0; y < Math.min(lines.length, vt.height); y++) {\n const line = lines[y]\n if (!line) continue\n\n for (let x = 0; x < Math.min(line.length, vt.width); x++) {\n const cell = line[x]\n if (!cell) continue\n\n // Cell format: [char, attr] or just char\n const char = Array.isArray(cell) ? cell[0] : cell\n const attr = Array.isArray(cell) ? cell[1] : null\n\n // Extract color from attr (blessed-specific format)\n const color = extractColor(attr) || '#ffffff'\n\n vt.setChar(x, y, char || ' ', color)\n }\n }\n}\n\n/**\n * Capture blessed screen content as ANSI escape sequence string\n *\n * This generates a string with ANSI color codes that can be played back\n * in a terminal or saved to an asciicast file.\n *\n * @param screen - The neo-blessed screen to capture\n * @returns ANSI-encoded string representation of the screen\n */\nexport function captureScreenAsAnsi(screen: any): string {\n // blessed can output its content with ANSI codes\n // We need to convert the internal buffer to ANSI escape sequences\n\n const lines = screen.lines || []\n const output: string[] = []\n\n // Clear screen and reset cursor\n output.push('\\x1b[2J\\x1b[H')\n\n for (let y = 0; y < lines.length; y++) {\n const line = lines[y]\n if (!line) {\n output.push('\\n')\n continue\n }\n\n let lineStr = ''\n let lastColor: string | null = null\n\n for (let x = 0; x < line.length; x++) {\n const cell = line[x]\n if (!cell) {\n lineStr += ' '\n continue\n }\n\n // Cell format: [char, attr] or just char\n const char = Array.isArray(cell) ? cell[0] : cell\n const attr = Array.isArray(cell) ? cell[1] : null\n\n // Extract color\n const color = extractColor(attr)\n\n // Apply color if changed\n if (color && color !== lastColor) {\n // Convert hex to ANSI 256-color code\n lineStr += hexToAnsi256(color)\n lastColor = color\n }\n\n lineStr += char || ' '\n }\n\n // Reset color at end of line\n if (lastColor) {\n lineStr += '\\x1b[0m'\n }\n\n output.push(lineStr)\n if (y < lines.length - 1) {\n output.push('\\n')\n }\n }\n\n return output.join('')\n}\n\n/**\n * Convert hex color to ANSI 256-color escape sequence\n */\nfunction hexToAnsi256(hex: string): string {\n // Parse hex color\n const r = Number.parseInt(hex.slice(1, 3), 16)\n const g = Number.parseInt(hex.slice(3, 5), 16)\n const b = Number.parseInt(hex.slice(5, 7), 16)\n\n // Convert to 256-color palette\n // Use 216-color cube (16-231)\n const rIndex = Math.round(r / 51)\n const gIndex = Math.round(g / 51)\n const bIndex = Math.round(b / 51)\n\n const colorCode = 16 + (rIndex * 36) + (gIndex * 6) + bIndex\n\n // Return ANSI escape sequence for foreground color\n return `\\x1b[38;5;${colorCode}m`\n}\n\n/**\n * Extract hex color from blessed attribute\n */\nfunction extractColor(attr: any): string | null {\n if (!attr) return null\n\n // blessed stores fg color in attr.fg\n if (typeof attr === 'object' && attr.fg !== undefined) {\n // Could be number (256 color) or string (hex)\n if (typeof attr.fg === 'string' && attr.fg.startsWith('#')) {\n return attr.fg\n }\n // Convert 256 color to hex\n if (typeof attr.fg === 'number') {\n return ansi256ToHex(attr.fg)\n }\n }\n\n return null\n}\n\n/**\n * Convert ANSI 256 color to hex\n */\nexport function ansi256ToHex(code: number): string {\n // Standard 16 colors\n const standard16 = [\n '#000000', '#800000', '#008000', '#808000',\n '#000080', '#800080', '#008080', '#c0c0c0',\n '#808080', '#ff0000', '#00ff00', '#ffff00',\n '#0000ff', '#ff00ff', '#00ffff', '#ffffff',\n ]\n\n if (code < 16) {\n return standard16[code]\n }\n\n // 216 color cube (16-231)\n if (code < 232) {\n const n = code - 16\n const r = Math.floor(n / 36) * 51\n const g = Math.floor((n % 36) / 6) * 51\n const b = (n % 6) * 51\n return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`\n }\n\n // Grayscale (232-255)\n const gray = (code - 232) * 10 + 8\n const hex = gray.toString(16).padStart(2, '0')\n return `#${hex}${hex}${hex}`\n}\n\n/**\n * Create a new recording session\n */\nexport async function createRecordingSession(\n options: ExportOptions\n): Promise<RecordingSession> {\n const { tmpdir } = await import('os')\n const { join } = await import('path')\n const { mkdir } = await import('fs/promises')\n\n // Create temp directory for frames\n const tempDir = join(tmpdir(), `term-deck-export-${Date.now()}`)\n await mkdir(tempDir, { recursive: true })\n\n return {\n tempDir,\n frameCount: 0,\n width: options.width ?? 120,\n height: options.height ?? 40,\n fps: options.fps ?? 30,\n }\n}\n\n/**\n * Save a frame to the recording session\n */\nexport async function saveFrame(\n session: RecordingSession,\n png: Uint8Array\n): Promise<void> {\n const { join } = await import('path')\n\n const frameNum = session.frameCount.toString().padStart(6, '0')\n const framePath = join(session.tempDir, `frame_${frameNum}.png`)\n\n await writeFile(framePath, png)\n session.frameCount++\n}\n\n/**\n * Cleanup recording session\n */\nexport async function cleanupSession(session: RecordingSession): Promise<void> {\n const { rm } = await import('fs/promises')\n await rm(session.tempDir, { recursive: true, force: true })\n}\n\n/**\n * Check if ffmpeg is available\n *\n * Throws an error with installation instructions if ffmpeg is not found\n */\nexport async function checkFfmpeg(): Promise<void> {\n try {\n await execa('which', ['ffmpeg'])\n } catch {\n throw new Error(\n 'ffmpeg not found. Install it with:\\n' +\n ' macOS: brew install ffmpeg\\n' +\n ' Ubuntu: sudo apt install ffmpeg'\n )\n }\n}\n\n/**\n * Detect export format from filename\n *\n * Checks the file extension and returns the corresponding export format.\n * Throws an error if the extension is not recognized.\n *\n * @param output - The output file path\n * @returns The export format ('mp4' or 'gif')\n * @throws Error if the file extension is not .mp4 or .gif\n */\nexport function detectFormat(output: string): ExportFormat {\n if (output.endsWith('.gif')) return 'gif'\n if (output.endsWith('.mp4')) return 'mp4'\n\n throw new Error(\n `Unknown output format for ${output}. Use .mp4 or .gif extension.`\n )\n}\n\n/**\n * Encode frames to video using ffmpeg\n */\nasync function encodeVideo(\n session: RecordingSession,\n output: string,\n format: ExportFormat,\n quality?: number\n): Promise<void> {\n const { join } = await import('path')\n const inputPattern = join(session.tempDir, 'frame_%06d.png')\n\n if (format === 'mp4') {\n await encodeMp4(inputPattern, output, session.fps, quality ?? 80)\n } else {\n await encodeGif(inputPattern, output, session.fps)\n }\n}\n\n/**\n * Encode to MP4\n */\nasync function encodeMp4(\n input: string,\n output: string,\n fps: number,\n quality: number\n): Promise<void> {\n // CRF: 0 = lossless, 51 = worst. ~18-23 is good quality\n const crf = Math.round(51 - (quality / 100) * 33)\n\n await execa('ffmpeg', [\n '-y',\n '-framerate', fps.toString(),\n '-i', input,\n '-c:v', 'libx264',\n '-crf', crf.toString(),\n '-pix_fmt', 'yuv420p',\n output\n ])\n}\n\n/**\n * Encode to GIF\n */\nasync function encodeGif(\n input: string,\n output: string,\n fps: number\n): Promise<void> {\n const { tmpdir } = await import('os')\n const { join } = await import('path')\n\n // Two-pass encoding for better quality GIF\n const paletteFile = join(tmpdir(), `palette-${Date.now()}.png`)\n\n try {\n // Pass 1: Generate palette\n await execa('ffmpeg', [\n '-y',\n '-framerate', fps.toString(),\n '-i', input,\n '-vf', `fps=${fps},scale=-1:-1:flags=lanczos,palettegen=stats_mode=diff`,\n paletteFile\n ])\n\n // Pass 2: Encode with palette\n await execa('ffmpeg', [\n '-y',\n '-framerate', fps.toString(),\n '-i', input,\n '-i', paletteFile,\n '-lavfi', `fps=${fps},scale=-1:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle`,\n output\n ])\n } finally {\n // Cleanup palette\n try {\n await unlink(paletteFile)\n } catch {\n // Ignore\n }\n }\n}\n\n/**\n * Export a presentation to video\n */\nexport async function exportPresentation(\n slidesDir: string,\n options: ExportOptions\n): Promise<void> {\n // Check ffmpeg is available\n await checkFfmpeg()\n\n // Detect format from output extension\n const format = detectFormat(options.output)\n\n // Load deck\n const { loadDeck } = await import('../core/slide.js')\n const deck = await loadDeck(slidesDir)\n\n if (deck.slides.length === 0) {\n throw new Error(`No slides found in ${slidesDir}`)\n }\n\n // Create recording session\n const session = await createRecordingSession(options)\n\n // Create virtual terminal\n const vt = new VirtualTerminal(session.width, session.height)\n\n // Create renderer (headless mode)\n const { createRenderer, destroyRenderer, renderSlide } = await import('../renderer/screen.js')\n const renderer = createRenderer(deck.config.theme)\n\n // Override screen dimensions\n ;(renderer.screen as any).width = session.width\n ;(renderer.screen as any).height = session.height\n\n const slideTime = options.slideTime ?? 3 // seconds per slide\n const framesPerSlide = session.fps * slideTime\n\n console.log(`Exporting ${deck.slides.length} slides...`)\n\n try {\n for (let i = 0; i < deck.slides.length; i++) {\n const slide = deck.slides[i]\n console.log(` Slide ${i + 1}/${deck.slides.length}: ${slide.frontmatter.title}`)\n\n // Render slide\n await renderSlide(renderer, slide)\n\n // Capture frames for this slide\n for (let f = 0; f < framesPerSlide; f++) {\n // Update matrix rain\n renderer.screen.render()\n\n // Capture to virtual terminal\n captureScreen(renderer.screen, vt)\n\n // Save frame\n const png = await vt.toPng()\n await saveFrame(session, png)\n }\n }\n\n // Encode video\n console.log('Encoding video...')\n await encodeVideo(session, options.output, format, options.quality)\n\n console.log(`Exported to ${options.output}`)\n } finally {\n // Cleanup\n destroyRenderer(renderer)\n await cleanupSession(session)\n }\n}\n\n/**\n * Record presentation as ANSI text file (asciicast format)\n *\n * This is an alternative to the video export that doesn't require ffmpeg or canvas.\n * The output can be played back with asciinema: `asciinema play output.cast`\n *\n * @param slidesDir - Directory containing slide markdown files\n * @param output - Output file path (e.g., 'presentation.cast')\n * @param options - Recording options\n */\nexport async function recordAnsi(\n slidesDir: string,\n output: string,\n options: { slideTime?: number; width?: number; height?: number } = {}\n): Promise<void> {\n // Load deck\n const { loadDeck } = await import('../core/slide.js')\n const deck = await loadDeck(slidesDir)\n\n if (deck.slides.length === 0) {\n throw new Error(`No slides found in ${slidesDir}`)\n }\n\n // Create renderer (headless mode)\n const { createRenderer, destroyRenderer, renderSlide } = await import('../renderer/screen.js')\n const renderer = createRenderer(deck.config.theme)\n\n // Override screen dimensions if specified\n const width = options.width ?? 120\n const height = options.height ?? 40\n ;(renderer.screen as any).width = width\n ;(renderer.screen as any).height = height\n\n const slideTime = options.slideTime ?? 3\n const frames: AsciicastFrame[] = []\n let currentTime = 0\n\n console.log(`Recording ${deck.slides.length} slides to asciicast format...`)\n\n try {\n for (let i = 0; i < deck.slides.length; i++) {\n const slide = deck.slides[i]\n console.log(` Slide ${i + 1}/${deck.slides.length}: ${slide.frontmatter.title}`)\n\n // Render slide\n await renderSlide(renderer, slide)\n\n // Capture screen as ANSI string\n const content = captureScreenAsAnsi(renderer.screen)\n\n // Add frame\n frames.push([currentTime, 'o', content])\n currentTime += slideTime\n }\n\n // Write asciicast file\n const header: AsciicastHeader = {\n version: 2,\n width,\n height,\n timestamp: Math.floor(Date.now() / 1000),\n env: { TERM: 'xterm-256color' },\n }\n\n const lines = [JSON.stringify(header)]\n for (const frame of frames) {\n lines.push(JSON.stringify(frame))\n }\n\n await writeFile(output, lines.join('\\n') + '\\n')\n\n console.log(`Recorded to ${output}`)\n console.log(`Play with: asciinema play ${output}`)\n } finally {\n destroyRenderer(renderer)\n }\n}\n","/**\n * Init Command\n *\n * Creates a new presentation deck with sample slides and configuration.\n */\n\nimport { Command } from 'commander';\nimport { join } from 'node:path';\nimport { mkdir, writeFile } from 'fs/promises';\nimport { handleError } from '../errors.js';\n\nexport const initCommand = new Command('init')\n .description('Create a new presentation deck')\n .argument('<name>', 'Deck name (will create directory)')\n .option('-t, --theme <name>', 'Theme to use', 'matrix')\n .action(async (name, options) => {\n try {\n await initDeck(name, options.theme);\n console.log(`Created deck: ${name}/`);\n console.log('\\nNext steps:');\n console.log(` cd ${name}/slides`);\n console.log(' term-deck present .');\n } catch (error) {\n handleError(error);\n }\n });\n\n/**\n * Initialize a new deck directory\n *\n * Creates the directory structure, configuration file, sample slides,\n * and README for a new presentation deck.\n */\nexport async function initDeck(name: string, theme: string): Promise<void> {\n const deckDir = join(process.cwd(), name);\n const slidesDir = join(deckDir, 'slides');\n\n // Create directories\n await mkdir(slidesDir, { recursive: true });\n await writeFile(join(slidesDir, '.gitkeep'), '');\n\n // Create deck.config.ts\n const configContent = `import { defineConfig } from 'term-deck'\nimport matrix from '@term-deck/theme-matrix'\n\nexport default defineConfig({\n title: '${name}',\n theme: matrix,\n})\n`;\n await writeFile(join(slidesDir, 'deck.config.ts'), configContent);\n\n // Create sample slides\n const slide1 = `---\ntitle: ${name.toUpperCase()}\nbigText: ${name.toUpperCase()}\ngradient: fire\n---\n\n{GREEN}Welcome to your presentation{/}\n\nPress {CYAN}Space{/} or {CYAN}→{/} to advance\n`;\n\n const slide2 = `---\ntitle: SLIDE TWO\nbigText: HELLO\ngradient: cool\n---\n\n{WHITE}This is the second slide{/}\n\n- Point one\n- Point two\n- Point three\n\n<!-- notes -->\nRemember to explain each point clearly.\n`;\n\n const slide3 = `---\ntitle: THE END\nbigText: FIN\ngradient: pink\n---\n\n{ORANGE}Thank you!{/}\n\nPress {CYAN}q{/} to exit\n`;\n\n await writeFile(join(slidesDir, '01-intro.md'), slide1);\n await writeFile(join(slidesDir, '02-content.md'), slide2);\n await writeFile(join(slidesDir, '03-end.md'), slide3);\n\n // Create README\n const readme = `# ${name}\n\nA term-deck presentation.\n\n## Usage\n\n\\`\\`\\`bash\ncd slides\nterm-deck present .\n\\`\\`\\`\n\n## Export\n\n\\`\\`\\`bash\nterm-deck export slides/ -o ${name}.mp4\nterm-deck export slides/ -o ${name}.gif\n\\`\\`\\`\n\n## Hotkeys\n\n| Key | Action |\n|-----|--------|\n| Space / → | Next slide |\n| ← | Previous slide |\n| 0-9 | Jump to slide |\n| l | Show slide list |\n| q | Quit |\n`;\n\n await writeFile(join(deckDir, 'README.md'), readme);\n}\n"]}