source dump of claude code
at main 98 lines 3.4 kB view raw
1import memoize from 'lodash-es/memoize.js' 2import { basename } from 'path' 3import type { OutputStyleConfig } from '../constants/outputStyles.js' 4import { logForDebugging } from '../utils/debug.js' 5import { coerceDescriptionToString } from '../utils/frontmatterParser.js' 6import { logError } from '../utils/log.js' 7import { 8 extractDescriptionFromMarkdown, 9 loadMarkdownFilesForSubdir, 10} from '../utils/markdownConfigLoader.js' 11import { clearPluginOutputStyleCache } from '../utils/plugins/loadPluginOutputStyles.js' 12 13/** 14 * Loads markdown files from .claude/output-styles directories throughout the project 15 * and from ~/.claude/output-styles directory and converts them to output styles. 16 * 17 * Each filename becomes a style name, and the file content becomes the style prompt. 18 * The frontmatter provides name and description. 19 * 20 * Structure: 21 * - Project .claude/output-styles/*.md -> project styles 22 * - User ~/.claude/output-styles/*.md -> user styles (overridden by project styles) 23 * 24 * @param cwd Current working directory for project directory traversal 25 */ 26export const getOutputStyleDirStyles = memoize( 27 async (cwd: string): Promise<OutputStyleConfig[]> => { 28 try { 29 const markdownFiles = await loadMarkdownFilesForSubdir( 30 'output-styles', 31 cwd, 32 ) 33 34 const styles = markdownFiles 35 .map(({ filePath, frontmatter, content, source }) => { 36 try { 37 const fileName = basename(filePath) 38 const styleName = fileName.replace(/\.md$/, '') 39 40 // Get style configuration from frontmatter 41 const name = (frontmatter['name'] || styleName) as string 42 const description = 43 coerceDescriptionToString( 44 frontmatter['description'], 45 styleName, 46 ) ?? 47 extractDescriptionFromMarkdown( 48 content, 49 `Custom ${styleName} output style`, 50 ) 51 52 // Parse keep-coding-instructions flag (supports both boolean and string values) 53 const keepCodingInstructionsRaw = 54 frontmatter['keep-coding-instructions'] 55 const keepCodingInstructions = 56 keepCodingInstructionsRaw === true || 57 keepCodingInstructionsRaw === 'true' 58 ? true 59 : keepCodingInstructionsRaw === false || 60 keepCodingInstructionsRaw === 'false' 61 ? false 62 : undefined 63 64 // Warn if force-for-plugin is set on non-plugin output style 65 if (frontmatter['force-for-plugin'] !== undefined) { 66 logForDebugging( 67 `Output style "${name}" has force-for-plugin set, but this option only applies to plugin output styles. Ignoring.`, 68 { level: 'warn' }, 69 ) 70 } 71 72 return { 73 name, 74 description, 75 prompt: content.trim(), 76 source, 77 keepCodingInstructions, 78 } 79 } catch (error) { 80 logError(error) 81 return null 82 } 83 }) 84 .filter(style => style !== null) 85 86 return styles 87 } catch (error) { 88 logError(error) 89 return [] 90 } 91 }, 92) 93 94export function clearOutputStyleCaches(): void { 95 getOutputStyleDirStyles.cache?.clear?.() 96 loadMarkdownFilesForSubdir.cache?.clear?.() 97 clearPluginOutputStyleCache() 98}