feat: Implement Issue #56 - Data-driven multiple draft generation
Add generate-drafts CLI command for batch document generation from data sources.
Supports JSON and CSV data with field mapping, validation, and automatic file naming.
Features:
- CLI command: markitect generate-drafts <schema> <data> -o <output_dir>
- JSON and CSV data source support
- Field mapping via x-markitect-field-mapping schema extensions
- Template variable substitution (e.g., {name} -> actual values)
- Data validation with required field checking
- Automatic file naming based on data content
- Schema reference metadata in generated files
- Integration with existing stub generation (Issue #55)
Technical implementation:
- New DraftGenerator class with comprehensive data processing
- Enhanced CLI with generate-drafts command and error handling
- Comprehensive test suite with 11 test cases covering all acceptance criteria
- Field mapping extraction and validation
- Template content substitution for data-driven content
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2061,6 +2061,81 @@ def generate_stub(config, schema_file, output, style, title):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@cli.command('generate-drafts')
|
||||
@click.argument('schema_file', type=click.Path(exists=True, path_type=Path))
|
||||
@click.argument('data_source', type=click.Path(exists=True, path_type=Path))
|
||||
@click.option('--output-dir', '-o', type=click.Path(path_type=Path), required=True,
|
||||
help='Output directory for generated drafts')
|
||||
@pass_config
|
||||
def generate_drafts(config, schema_file, data_source, output_dir):
|
||||
"""
|
||||
Generate multiple document drafts from a schema and data source.
|
||||
|
||||
Creates multiple markdown documents by combining a JSON schema template
|
||||
with data from JSON or CSV sources. Each record in the data source
|
||||
generates a separate draft file with field mapping applied.
|
||||
|
||||
SCHEMA_FILE: Path to the JSON schema file
|
||||
DATA_SOURCE: Path to JSON or CSV data source file
|
||||
|
||||
Examples:
|
||||
markitect generate-drafts schema.json data.json -o ./drafts/
|
||||
markitect generate-drafts blog_schema.json posts.csv -o ./blog_posts/
|
||||
|
||||
Field Mapping:
|
||||
Use x-markitect-field-mapping extension in schema to map data fields
|
||||
to content areas. Data validation ensures compatibility.
|
||||
|
||||
Output:
|
||||
Generated drafts maintain schema references for validation and
|
||||
use automatic file naming based on data content.
|
||||
"""
|
||||
try:
|
||||
if config.get('verbose'):
|
||||
click.echo(f"Generating drafts from schema: {schema_file}", err=True)
|
||||
click.echo(f"Using data source: {data_source}", err=True)
|
||||
click.echo(f"Output directory: {output_dir}", err=True)
|
||||
|
||||
from .draft_generator import DraftGenerator
|
||||
|
||||
generator = DraftGenerator()
|
||||
|
||||
# Load schema
|
||||
import json
|
||||
with open(schema_file, 'r') as f:
|
||||
schema = json.load(f)
|
||||
|
||||
# Generate drafts
|
||||
generated_files = generator.generate_drafts_from_data_source(
|
||||
schema=schema,
|
||||
data_source=data_source,
|
||||
output_dir=Path(output_dir),
|
||||
schema_file_path=str(schema_file)
|
||||
)
|
||||
|
||||
# Report results
|
||||
click.echo(f"✅ Generated {len(generated_files)} drafts in {output_dir}")
|
||||
if config.get('verbose'):
|
||||
for file_path in generated_files:
|
||||
click.echo(f" - {file_path}", err=True)
|
||||
|
||||
except FileNotFoundError as e:
|
||||
click.echo(f"Error: {e}", err=True)
|
||||
sys.exit(1)
|
||||
except json.JSONDecodeError as e:
|
||||
click.echo(f"Error: Invalid JSON in schema file - {e}", err=True)
|
||||
sys.exit(1)
|
||||
except ValueError as e:
|
||||
click.echo(f"Error: {e}", err=True)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
click.echo(f"Draft generation error: {e}", err=True)
|
||||
if config and config.get('verbose'):
|
||||
import traceback
|
||||
click.echo(traceback.format_exc(), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@cli.group('associated-files')
|
||||
@pass_config
|
||||
def associated_files_group(config):
|
||||
|
||||
Reference in New Issue
Block a user