/** * SpecOutput to XML converter. * Converts a structured SpecOutput object back to XML format. */ import type { SpecOutput } from '@automaker/types'; import { escapeXml } from './xml-utils.js'; /** * Convert structured spec output to XML format. * * @param spec - The SpecOutput object to convert * @returns XML string formatted for app_spec.txt */ export function specToXml(spec: SpecOutput): string { const indent = ' '; let xml = ` ${indent}${escapeXml(spec.project_name)} ${indent} ${indent}${indent}${escapeXml(spec.overview)} ${indent} ${indent} ${spec.technology_stack.map((t) => `${indent}${indent}${escapeXml(t)}`).join('\n')} ${indent} ${indent} ${spec.core_capabilities.map((c) => `${indent}${indent}${escapeXml(c)}`).join('\n')} ${indent} ${indent} ${spec.implemented_features .map( (f) => `${indent}${indent} ${indent}${indent}${indent}${escapeXml(f.name)} ${indent}${indent}${indent}${escapeXml(f.description)}${ f.file_locations && f.file_locations.length > 0 ? `\n${indent}${indent}${indent} ${f.file_locations.map((loc) => `${indent}${indent}${indent}${indent}${escapeXml(loc)}`).join('\n')} ${indent}${indent}${indent}` : '' } ${indent}${indent}` ) .join('\n')} ${indent}`; // Optional sections if (spec.additional_requirements && spec.additional_requirements.length > 0) { xml += ` ${indent} ${spec.additional_requirements.map((r) => `${indent}${indent}${escapeXml(r)}`).join('\n')} ${indent}`; } if (spec.development_guidelines && spec.development_guidelines.length > 0) { xml += ` ${indent} ${spec.development_guidelines.map((g) => `${indent}${indent}${escapeXml(g)}`).join('\n')} ${indent}`; } if (spec.implementation_roadmap && spec.implementation_roadmap.length > 0) { xml += ` ${indent} ${spec.implementation_roadmap .map( (r) => `${indent}${indent} ${indent}${indent}${indent}${escapeXml(r.phase)} ${indent}${indent}${indent}${escapeXml(r.status)} ${indent}${indent}${indent}${escapeXml(r.description)} ${indent}${indent}` ) .join('\n')} ${indent}`; } xml += ` `; return xml; }