140 lines
6.0 KiB
Markdown
140 lines
6.0 KiB
Markdown
# Story 2.4: HTML Formatting with Multiple Templates
|
|
|
|
## Status
|
|
Completed
|
|
|
|
## Story
|
|
**As a developer**, I want a module that takes the generated text content and formats it into a standard HTML file using one of a few predefined CSS templates, assigning one template per bucket/subdomain, so that all deployed content has a consistent look and feel per site.
|
|
|
|
## Acceptance Criteria
|
|
- A directory of multiple, predefined HTML/CSS templates exists.
|
|
- The master JSON configuration file maps a specific template to each deployment target (e.g., S3 bucket, subdomain).
|
|
- A function accepts the generated content and a target identifier (e.g., bucket name).
|
|
- The function correctly selects and applies the appropriate template based on the configuration mapping.
|
|
- The content is structured into a valid HTML document with the selected CSS.
|
|
- The final HTML content is stored and associated with the project in the database.
|
|
|
|
## Dependencies
|
|
- **Story 2.5**: Deployment Target Assignment must run before this story to set `site_deployment_id` on GeneratedContent
|
|
- If `site_deployment_id` is null, a random template will be selected
|
|
|
|
## Tasks / Subtasks
|
|
|
|
### 1. Create Template Infrastructure
|
|
**Effort:** 3 story points
|
|
|
|
- [x] Create template file structure under `src/templating/templates/`
|
|
- Basic template (default)
|
|
- Modern template
|
|
- Classic template
|
|
- Minimal template
|
|
- [x] Each template should include:
|
|
- HTML structure with placeholders for title, meta, content
|
|
- Embedded or inline CSS for styling
|
|
- Responsive design (mobile-friendly)
|
|
- SEO-friendly structure (proper heading hierarchy, meta tags)
|
|
|
|
### 2. Implement Template Loading Service
|
|
**Effort:** 3 story points
|
|
|
|
- [x] Implement `TemplateService` class in `src/templating/service.py`
|
|
- [x] Add `load_template(template_name: str)` method that reads template file
|
|
- [x] Add `get_available_templates()` method that lists all templates
|
|
- [x] Handle template file not found errors gracefully with fallback to default
|
|
- [x] Cache loaded templates in memory for performance
|
|
|
|
### 3. Implement Template Selection Logic
|
|
**Effort:** 2 story points
|
|
|
|
- [x] Add `select_template_for_content(site_deployment_id: Optional[int])` method
|
|
- [x] If `site_deployment_id` exists:
|
|
- Query SiteDeployment table and return `site.template_name`
|
|
- Template is tracked at site/domain level in database
|
|
- [x] If `site_deployment_id` is null: randomly select template (don't persist)
|
|
- [x] Return template name
|
|
|
|
### 4. Implement Content Formatting
|
|
**Effort:** 5 story points
|
|
|
|
- [x] Create `format_content(content: str, title: str, meta_description: str, template_name: str)` method
|
|
- [x] Parse HTML content and extract components
|
|
- [x] Replace template placeholders with actual content
|
|
- [x] Ensure proper escaping of HTML entities where needed
|
|
- [x] Validate output is well-formed HTML
|
|
- [x] Return formatted HTML string
|
|
|
|
### 5. Database Integration
|
|
**Effort:** 2 story points
|
|
|
|
- [x] Add `template_name` field to `SiteDeployment` model (String(50), default='basic', not null)
|
|
- [x] Add `formatted_html` field to `GeneratedContent` model (Text type, nullable)
|
|
- [x] Add `template_used` field to `GeneratedContent` model (String(50), nullable)
|
|
- [x] Add `site_deployment_id` field to `GeneratedContent` model (FK to site_deployments, nullable, indexed)
|
|
- [x] Create database migration script (`scripts/migrate_add_template_to_sites.py`)
|
|
- [x] Update repository to save formatted HTML and template_used alongside raw content
|
|
|
|
### 6. Integration with Content Generation Flow
|
|
**Effort:** 2 story points
|
|
|
|
- [x] Update `src/generation/service.py` to call template service after content generation
|
|
- [x] Template service reads `site_deployment_id` from GeneratedContent
|
|
- [x] Store formatted HTML and template_used in database
|
|
- [x] Handle template formatting errors without breaking content generation
|
|
|
|
### 7. Unit Tests
|
|
**Effort:** 3 story points
|
|
|
|
- [x] Test template loading with valid and invalid names
|
|
- [x] Test template selection with site_deployment_id present
|
|
- [x] Test template selection with site_deployment_id null (random)
|
|
- [x] Test content formatting with different templates
|
|
- [x] Test fallback behavior when template not found
|
|
- [x] Test error handling for malformed templates
|
|
- [x] Achieve >80% code coverage for templating module
|
|
|
|
### 8. Integration Tests
|
|
**Effort:** 2 story points
|
|
|
|
- [x] Test end-to-end flow: content generation → template application → database storage
|
|
- [x] Test with site_deployment_id assigned (consistent template per site)
|
|
- [x] Test with site_deployment_id null (random template)
|
|
- [x] Verify formatted HTML is valid and renders correctly
|
|
- [x] Test new site gets random template assigned and persisted to config
|
|
|
|
## Dev Notes
|
|
|
|
### Current State
|
|
- `master.config.json` already has templates section with mappings (lines 52-59)
|
|
- `src/templating/service.py` exists but is empty (only 2 lines)
|
|
- `src/templating/templates/` directory exists but only contains `__init__.py`
|
|
- `GeneratedContent` model stores raw content in Text field but no formatted HTML field yet
|
|
|
|
### Dependencies
|
|
- Story 2.2/2.3: Content must be generated before it can be formatted
|
|
- Story 2.5: Deployment target assignment (optional - defaults to random if not assigned)
|
|
- Configuration system: Uses existing master.config.json structure
|
|
|
|
### Technical Decisions
|
|
1. **Template format:** Simple string replacement with {{ placeholders }}
|
|
2. **CSS approach:** Embedded `<style>` tags in HTML template
|
|
3. **Storage:** Store both raw content AND formatted HTML
|
|
4. **Template selection:**
|
|
- Has site_deployment_id → use site.template_name from database
|
|
- No site_deployment_id → pick random, don't persist
|
|
5. **Template tracking:** Stored at site level in `site_deployments.template_name` field
|
|
6. Story 2.4 owns ALL template selection logic
|
|
|
|
### Suggested Template Structure
|
|
```
|
|
src/templating/templates/
|
|
├── basic.html
|
|
├── modern.html
|
|
├── classic.html
|
|
└── minimal.html
|
|
```
|
|
|
|
|
|
### Testing Approach
|
|
- Unit tests: Test each service method in isolation
|
|
- Integration tests: Test full content → template → storage flow
|
|
- Manual QA: Visual inspection of rendered HTML in browser |