import { isMap, parseDocument } from 'yaml'; import { DiagramType } from './detect'; export interface DiagramTemplate { /** File name under templates/. */ file: string; type: DiagramType; label: string; description: string; /** Suggested name for the new file, without .archify. */ defaultName: string; } export const TEMPLATES: readonly DiagramTemplate[] = [ { file: 'architecture.archify', type: 'architecture', label: 'Architecture', description: 'Parts of a system and how they connect', defaultName: 'architecture' }, { file: 'workflow.archify', type: 'workflow', label: 'Workflow', description: 'Steps of a process, in lanes', defaultName: 'workflow' }, { file: 'sequence.archify', type: 'sequence', label: 'Sequence', description: 'Who calls whom, in order', defaultName: 'sequence' }, { file: 'dataflow.archify', type: 'dataflow', label: 'Data Flow', description: 'Where data comes from and where it goes', defaultName: 'dataflow' }, { file: 'lifecycle.archify', type: 'lifecycle', label: 'Lifecycle', description: 'States something moves through', defaultName: 'lifecycle' }, { file: 'everyday-plan.archify', type: 'workflow', label: 'Everyday Plan', description: 'A plan or process from daily life', defaultName: 'plan' }, ]; /** Strips a typed .archify suffix and surrounding spaces. */ export function diagramName(input: string): string { return input.trim().replace(/\.archify$/i, '').trim(); } /** Why a name cannot be used as a file name, or undefined when it can. */ export function invalidNameReason(input: string): string | undefined { const name = diagramName(input); if (!name) return 'Enter a name.'; if (/[\\/:*?"<>|\u0000-\u001f]/.test(name)) return 'A name cannot contain \\ / : * ? " < > | or control characters.'; if (/^\.+$/.test(name)) return 'Enter a name.'; return undefined; } /** "sales-report_v2" → "Sales report v2". */ export function titleFromName(name: string): string { const words = name.replace(/[-_.]+/g, ' ').replace(/\s+/g, ' ').trim(); return words ? words.charAt(0).toUpperCase() + words.slice(1) : name; } /** * Template YAML with meta.title and meta.output set for the new file. * Works on the YAML document so the template's comments and layout stay. */ export function diagramFromTemplate(templateText: string, name: string): string { const doc = parseDocument(templateText); if (!isMap(doc.get('meta'))) doc.set('meta', doc.createNode({})); doc.setIn(['meta', 'title'], titleFromName(name)); doc.setIn(['meta', 'output'], `${name}.html`); return doc.toString({ lineWidth: 0, flowCollectionPadding: false }); }