Files
Claude-Code-Workflow/.claude/skills/command-generator/phases/04-content-formatting.md
catlog22 3b92bfae8c feat: add Discuss and Explore subagents for dynamic critique and code exploration
- Implement Discuss Subagent for multi-perspective critique with dynamic perspectives.
- Create Explore Subagent for shared codebase exploration with centralized caching.
- Add tests for CcwToolsMcpCard component to ensure enabled tools are preserved on config save.
- Introduce SessionPreviewPanel component for previewing and selecting sessions for Memory V2 extraction.
- Develop CommandCreateDialog component for creating/importing commands with import and CLI generate modes.
2026-02-27 17:25:52 +08:00

4.4 KiB

Phase 4: Content Formatting

Format template content by substituting placeholders with parameter values.

Objective

Replace all placeholder variables in the template with validated parameter values:

  • {{name}} -> skillName
  • {{description}} -> description
  • {{group}} -> group (if provided)
  • {{argumentHint}} -> argumentHint (if provided)

Input

From Phase 3:

{
  template: {
    content: string,
    requiredPlaceholders: string[],
    optionalPlaceholders: string[]
  },
  targetPath: string,
  params: {
    skillName: string,
    description: string,
    location: string,
    group: string | null,
    argumentHint: string
  }
}

Placeholder Mapping

const placeholderMap = {
  '{{name}}': params.skillName,
  '{{description}}': params.description,
  '{{group}}': params.group || '',
  '{{argumentHint}}': params.argumentHint || ''
};

Execution Steps

Step 1: Initialize Content

let formattedContent = template.content;

Step 2: Substitute Required Placeholders

// These must always be replaced
formattedContent = formattedContent.replace(/\{\{name\}\}/g, params.skillName);
formattedContent = formattedContent.replace(/\{\{description\}\}/g, params.description);

Step 3: Handle Optional Placeholders

// Group placeholder
if (params.group) {
  formattedContent = formattedContent.replace(/\{\{group\}\}/g, params.group);
} else {
  // Remove group line if not provided
  formattedContent = formattedContent.replace(/^group: \{\{group\}\}\n?/gm, '');
  formattedContent = formattedContent.replace(/\{\{group\}\}/g, '');
}

// Argument hint placeholder
if (params.argumentHint) {
  formattedContent = formattedContent.replace(/\{\{argumentHint\}\}/g, params.argumentHint);
} else {
  // Remove argument-hint line if not provided
  formattedContent = formattedContent.replace(/^argument-hint: \{\{argumentHint\}\}\n?/gm, '');
  formattedContent = formattedContent.replace(/\{\{argumentHint\}\}/g, '');
}

Step 4: Handle Conditional Sections

// Remove empty frontmatter lines (caused by missing optional fields)
formattedContent = formattedContent.replace(/\n{3,}/g, '\n\n');

// Handle {{#if group}} style conditionals
if (formattedContent.includes('{{#if')) {
  // Process group conditional
  if (params.group) {
    formattedContent = formattedContent.replace(/\{\{#if group\}\}([\s\S]*?)\{\{\/if\}\}/g, '$1');
  } else {
    formattedContent = formattedContent.replace(/\{\{#if group\}\}[\s\S]*?\{\{\/if\}\}/g, '');
  }
  
  // Process argumentHint conditional
  if (params.argumentHint) {
    formattedContent = formattedContent.replace(/\{\{#if argumentHint\}\}([\s\S]*?)\{\{\/if\}\}/g, '$1');
  } else {
    formattedContent = formattedContent.replace(/\{\{#if argumentHint\}\}[\s\S]*?\{\{\/if\}\}/g, '');
  }
}

Step 5: Validate Final Content

// Ensure no unresolved placeholders remain
const unresolvedPlaceholders = formattedContent.match(/\{\{[^}]+\}\}/g);
if (unresolvedPlaceholders) {
  console.warn(`Warning: Unresolved placeholders found: ${unresolvedPlaceholders.join(', ')}`);
}

// Ensure frontmatter is valid
const frontmatterMatch = formattedContent.match(/^---\n([\s\S]*?)\n---/);
if (!frontmatterMatch) {
  throw new Error('Generated content has invalid frontmatter structure');
}

Step 6: Generate Summary

const summary = {
  name: params.skillName,
  description: params.description.substring(0, 50) + (params.description.length > 50 ? '...' : ''),
  location: params.location,
  group: params.group,
  hasArgumentHint: !!params.argumentHint
};

Output

{
  status: 'formatted',
  content: formattedContent,
  targetPath: targetPath,
  summary: summary
}

Content Example

Input Template

---
name: {{name}}
description: {{description}}
{{#if group}}group: {{group}}{{/if}}
{{#if argumentHint}}argument-hint: {{argumentHint}}{{/if}}
---

# {{name}} Command

Output (with all fields)

---
name: create
description: Create structured issue from GitHub URL or text description
group: issue
argument-hint: [-y|--yes] <github-url | text-description> [--priority 1-5]
---

# create Command

Output (minimal fields)

---
name: deploy
description: Deploy application to production environment
---

# deploy Command

Next Phase

Proceed to Phase 5: File Generation with content and targetPath.