diff --git a/src/componets/content/ConfigTemplate.tsx b/src/componets/content/ConfigTemplate.tsx index 0a503d1..a81a699 100644 --- a/src/componets/content/ConfigTemplate.tsx +++ b/src/componets/content/ConfigTemplate.tsx @@ -21,6 +21,10 @@ export function ConfigTemplate(props: ConfigTemplateProps) { } }, [props.config.template.content, mode]); + // Validate placeholders (check if @placeholders@ have matching params) + const missingPlaceholders = props.config.validatePlaceholders(); + const hasValidationWarnings = missingPlaceholders.length > 0; + function handleEdit() { setOriginalContent(props.config.template.content); setDraftContent(props.config.template.content); @@ -67,11 +71,21 @@ export function ConfigTemplate(props: ConfigTemplateProps) {
{mode === 'view' ? ( <> -
+
+ {hasValidationWarnings && ( + + ⚠ {missingPlaceholders.length} placeholder(s) without params + + )}
+ {hasValidationWarnings && ( +
+ Missing parameters: {missingPlaceholders.join(", ")} +
+ )} {props.config.template.content || "{}"} diff --git a/src/models/Config.tsx b/src/models/Config.tsx index 4c9fff9..b51417e 100644 --- a/src/models/Config.tsx +++ b/src/models/Config.tsx @@ -109,5 +109,50 @@ export class Config { return missingParams; } + + /** + * Validates that all @placeholders@ in template have corresponding params. + * Checks DEFAULT env first, then all custom envs. + * Returns array of placeholder names that are not defined. + */ + validatePlaceholders(): string[] { + const defaultEnv = this.envs.find(e => e.name === "DEFAULT"); + const customEnvs = this.envs.filter(e => e.name !== "DEFAULT"); + + // Collect all param names from DEFAULT + const defaultParamNames = new Set( + defaultEnv?.params.map(p => p.name).filter(n => n && n.trim() !== "") || [] + ); + + // Collect all param names from all custom envs + const customParamNames = new Set( + customEnvs.flatMap(e => e.params.map(p => p.name).filter(n => n && n.trim() !== "")) + ); + + // Extract all @placeholders@ from template + const placeholderRegex = /@(\w+)@/g; + const placeholdersInTemplate = new Set(); + let match; + while ((match = placeholderRegex.exec(this.template.content)) !== null) { + placeholdersInTemplate.add(match[1]); + } + + // Find placeholders that don't have matching params + const missingParams: string[] = []; + for (const placeholder of placeholdersInTemplate) { + if (placeholder === Config.ENV_NAME_PARAM) continue; // Skip built-in + + // Check if exists in DEFAULT or in ANY custom env + const inDefault = defaultParamNames.has(placeholder); + const inCustom = customParamNames.has(placeholder); + + // Valid if: in DEFAULT, or in at least one custom env + if (!inDefault && !inCustom) { + missingParams.push(placeholder); + } + } + + return missingParams; + } }