docs: Merge LONG-PDF-GENERATION.md into comprehensive PDF documentation
## Merged Content - Merged LONG-PDF-GENERATION.md technical details into doc/11-PDF-EXPORT.md - Removed duplicate documentation file - Single source of truth for all PDF export documentation ## Added Technical Details - PDF generation flow diagram - 2-column vs 3-column layout architecture decision - Sidebar width configuration guide (18%-30% analysis) - Detailed CSS injection strategy with code examples - HTML structure examples for page layouts - Expanded compact sidebar fonts implementation details - Font size breakdown table (2-6% reduction) ## Result - Comprehensive PDF documentation: 966 lines (was 793) - Added 173 lines of technical implementation details - Removed 411-line duplicate file - Better organized, single reference for developers and users Benefits: - Single source of truth for PDF features - No duplication between docs - Easier maintenance - Complete technical and user-facing documentation in one place
This commit is contained in:
@@ -43,6 +43,179 @@ The CV application provides a comprehensive PDF export system with three predefi
|
|||||||
|
|
||||||
**See**: `internal/pdf/generator.go` lines 146-165 for implementation
|
**See**: `internal/pdf/generator.go` lines 146-165 for implementation
|
||||||
|
|
||||||
|
### PDF Generation Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
User selects PDF option in modal
|
||||||
|
↓
|
||||||
|
Frontend: /export/pdf?lang={lang}&length={length}&icons={icons}&version={version}
|
||||||
|
↓
|
||||||
|
Backend: GenerateFromURLWithOptions(url, cookies, RenderMode)
|
||||||
|
↓
|
||||||
|
Chromedp: Navigate to URL with cookies
|
||||||
|
↓
|
||||||
|
CSS Injection: Override print.css + Show/hide sidebars + Layout adjustments
|
||||||
|
↓
|
||||||
|
PDF Generation: PrintToPDF with A4 dimensions
|
||||||
|
↓
|
||||||
|
Output: PDF file (4, 5, 7, or 9 pages depending on configuration)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2-Column vs 3-Column Layout Decision
|
||||||
|
|
||||||
|
**Critical Architecture Decision** for long CV with sidebars:
|
||||||
|
|
||||||
|
#### ❌ Previous Approach (3-column - WRONG)
|
||||||
|
```css
|
||||||
|
.page-1, .page-2: 25% | 50% | 25% /* Always 3 columns */
|
||||||
|
```
|
||||||
|
**Problems:**
|
||||||
|
- Page 1 had empty right column (25% wasted space)
|
||||||
|
- Page 2 had empty left column (25% wasted space)
|
||||||
|
- Result: 10-19 pages (excessive)
|
||||||
|
|
||||||
|
#### ✅ Current Approach (2-column - CORRECT)
|
||||||
|
```css
|
||||||
|
.page-1: 25% | 75% /* Left sidebar + Main, NO right space */
|
||||||
|
.page-2: 75% | 25% /* Main + Right sidebar, NO left space */
|
||||||
|
```
|
||||||
|
**Benefits:**
|
||||||
|
- No wasted space on either page
|
||||||
|
- Matches web's actual layout exactly
|
||||||
|
- Result: **9 pages** (optimal)
|
||||||
|
|
||||||
|
### Sidebar Width Configuration
|
||||||
|
|
||||||
|
Sidebar width affects page count and readability:
|
||||||
|
|
||||||
|
| Width | Layout | Pages | Notes |
|
||||||
|
|-------|--------|-------|-------|
|
||||||
|
| 18% | 18% \| 82% | 9 pages | Too narrow, cramped |
|
||||||
|
| 20% | 20% \| 80% | 8 pages | Minimal sidebars |
|
||||||
|
| **25%** | **25% \| 75%** | **9 pages** | ✅ **Current** (optimal balance) |
|
||||||
|
| 30% | 30% \| 70% | 10+ pages | Too wide, excessive |
|
||||||
|
|
||||||
|
**Current Setting**: 25% sidebars (configured in `internal/pdf/generator.go:176,181`)
|
||||||
|
|
||||||
|
**To adjust sidebar width**, update these lines in `internal/pdf/generator.go`:
|
||||||
|
```go
|
||||||
|
// Page 1: Left sidebar (XX%) + Main (YY%) - NO right space
|
||||||
|
'.page-1 .page-content { grid-template-columns: XX% YY% !important; }' +
|
||||||
|
|
||||||
|
// Page 2: Main (YY%) + Right sidebar (XX%) - NO left space
|
||||||
|
'.page-2 .page-content { grid-template-columns: YY% XX% !important; }'
|
||||||
|
|
||||||
|
// Where XX + YY = 100
|
||||||
|
```
|
||||||
|
|
||||||
|
### Detailed CSS Injection Strategy
|
||||||
|
|
||||||
|
For `RenderModeScreen` (long CV with sidebars), the following CSS is injected:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Override parent width constraints (full A4 width)
|
||||||
|
'.cv-page, .cv-paper, .cv-container { max-width: 100% !important; width: 100% !important; }'
|
||||||
|
|
||||||
|
// Show sidebars (override print.css hiding)
|
||||||
|
'.cv-sidebar, .cv-sidebar-left, .cv-sidebar-right { display: block !important; }'
|
||||||
|
|
||||||
|
// Hide mobile UI elements (accordion headers, navigation, etc.)
|
||||||
|
'.sidebar-accordion-header { display: none !important; }'
|
||||||
|
'.no-print, .action-bar, .navigation-menu, .hamburger-btn { display: none !important; }'
|
||||||
|
'footer, .back-to-top, .info-button, .info-modal { display: none !important; }'
|
||||||
|
|
||||||
|
// Force page break before page 2
|
||||||
|
'.page-2 { page-break-before: always !important; break-before: page !important; }'
|
||||||
|
|
||||||
|
// 2-column layouts (no wasted space)
|
||||||
|
'.page-1 .page-content { grid-template-columns: 25% 75% !important; }' // Left + Main
|
||||||
|
'.page-2 .page-content { grid-template-columns: 75% 25% !important; }' // Main + Right
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTML Structure
|
||||||
|
|
||||||
|
**Page 1** - Left sidebar + Main content:
|
||||||
|
```html
|
||||||
|
<div class="cv-page page-1">
|
||||||
|
<div class="page-content">
|
||||||
|
<aside class="cv-sidebar cv-sidebar-left">
|
||||||
|
<!-- Skills, languages, etc. -->
|
||||||
|
</aside>
|
||||||
|
<main class="cv-main">
|
||||||
|
<!-- Work experience, education -->
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Page 2** - Main content + Right sidebar:
|
||||||
|
```html
|
||||||
|
<div class="cv-page page-2">
|
||||||
|
<div class="page-content">
|
||||||
|
<main class="cv-main">
|
||||||
|
<!-- Continued work experience -->
|
||||||
|
</main>
|
||||||
|
<aside class="cv-sidebar cv-sidebar-right">
|
||||||
|
<!-- Additional skills, references -->
|
||||||
|
</aside>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compact Sidebar Fonts Feature
|
||||||
|
|
||||||
|
**Overview:**
|
||||||
|
Automatically reduces sidebar font sizes by 2-6% **only for short CVs with skills** (`length=short&version=with_skills`), reducing page count from 6 to 5 pages while maintaining readability.
|
||||||
|
|
||||||
|
**Impact:**
|
||||||
|
- Page count reduction: 6 → 5 pages (16.7% reduction)
|
||||||
|
- Font size reduction: 2-6% (very subtle, 0.94-0.98em)
|
||||||
|
- Readability: Maintained - fonts remain professional
|
||||||
|
- **Only for short version** - Long version uses full-size fonts
|
||||||
|
|
||||||
|
**Activation Conditions:**
|
||||||
|
1. `length=short` (detected via `cv-length` cookie)
|
||||||
|
2. `version=with_skills` (RenderModeScreen with sidebars)
|
||||||
|
|
||||||
|
**Does NOT activate for:**
|
||||||
|
- Long CVs (`length=long`) - always use full-size fonts
|
||||||
|
- Clean version (`version=clean`) - no sidebars shown
|
||||||
|
|
||||||
|
**Implementation** (`internal/pdf/generator.go` lines 154-215):
|
||||||
|
```go
|
||||||
|
// Check if this is a short version (to apply compact sidebar fonts)
|
||||||
|
isShortVersion := cookies["cv-length"] == "short"
|
||||||
|
|
||||||
|
compactFontCSS := ""
|
||||||
|
if isShortVersion {
|
||||||
|
compactFontCSS = `
|
||||||
|
/* Compact sidebar fonts (SHORT VERSION ONLY) */
|
||||||
|
.cv-sidebar * { font-size: 0.96em !important; line-height: 1.4 !important; }
|
||||||
|
.cv-sidebar h3 { font-size: 0.98em !important; margin: 0.4em 0 !important; }
|
||||||
|
.cv-sidebar h4 { font-size: 0.96em !important; margin: 0.35em 0 !important; }
|
||||||
|
.cv-sidebar p, .cv-sidebar li { font-size: 0.94em !important; line-height: 1.4 !important; }
|
||||||
|
.cv-sidebar ul, .cv-sidebar ol { margin: 0.4em 0 0.4em 1.2em !important; }
|
||||||
|
.cv-sidebar li { margin-bottom: 0.25em !important; }
|
||||||
|
.cv-sidebar section { margin-bottom: 0.8em !important; }
|
||||||
|
`
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Font Size Breakdown:**
|
||||||
|
|
||||||
|
| Element | Full-Size (Long) | Compact (Short) | Reduction |
|
||||||
|
|---------|------------------|-----------------|-----------|
|
||||||
|
| General text | 1.0em | 0.96em | 4% |
|
||||||
|
| H3 headings | 1.0em | 0.98em | 2% |
|
||||||
|
| H4 headings | 1.0em | 0.96em | 4% |
|
||||||
|
| Paragraphs & lists | 1.0em | 0.94em | 6% |
|
||||||
|
|
||||||
|
**Design Philosophy:**
|
||||||
|
- **Readability first**: 2-6% reduction is barely noticeable
|
||||||
|
- **Professional appearance**: No "squeezed" or cramped feel
|
||||||
|
- **Natural flow**: Content reflows organically, not forced
|
||||||
|
- **Consistent UX**: Main content uses full-size fonts
|
||||||
|
|
||||||
## Feature Specifications
|
## Feature Specifications
|
||||||
|
|
||||||
### Export Options
|
### Export Options
|
||||||
|
|||||||
@@ -1,411 +0,0 @@
|
|||||||
# Long PDF Generation with Skills Sidebars
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The long PDF generation feature creates a comprehensive CV that includes technical skills sidebars positioned on the left and right sides, while hiding UI elements for a clean, print-optimized output.
|
|
||||||
|
|
||||||
**Page counts**:
|
|
||||||
- **Long version** (9 pages) - Full-size fonts, comprehensive content
|
|
||||||
- **Short version with skills** (5 pages) - Compact sidebar fonts for reduced page count
|
|
||||||
|
|
||||||
## Key Features
|
|
||||||
|
|
||||||
- **9-page layout** with optimal content density
|
|
||||||
- **25% sidebars** for skills/competencies display
|
|
||||||
- **2-column approach** matching web layout (no wasted space)
|
|
||||||
- **Page breaks** between left and right sidebar sections
|
|
||||||
- **Hidden mobile UI elements** (accordion headers, navigation)
|
|
||||||
- **Print media CSS** for compact, professional typography
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### PDF Generation Flow
|
|
||||||
|
|
||||||
```
|
|
||||||
User clicks "Long CV (9 pages)" in PDF Modal
|
|
||||||
↓
|
|
||||||
Frontend: `/export/pdf?lang=es&length=long&icons=show&version=with_skills`
|
|
||||||
↓
|
|
||||||
Backend: GenerateFromURLWithOptions(url, cookies, RenderModeScreen)
|
|
||||||
↓
|
|
||||||
Chromedp: Navigate to URL with cookies
|
|
||||||
↓
|
|
||||||
CSS Injection: Override print.css + Show sidebars + 2-column layout
|
|
||||||
↓
|
|
||||||
PDF Generation: PrintToPDF with A4 dimensions
|
|
||||||
↓
|
|
||||||
Output: 9-page PDF with sidebars (or 5 pages with compact fonts for short version)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Critical Components
|
|
||||||
|
|
||||||
#### 1. PDF Generator (`internal/pdf/generator.go`)
|
|
||||||
|
|
||||||
**RenderMode**:
|
|
||||||
- `RenderModePrint` - Clean version (hides sidebars)
|
|
||||||
- `RenderModeScreen` - Long version (shows sidebars)
|
|
||||||
|
|
||||||
**CSS Injection Strategy**:
|
|
||||||
```javascript
|
|
||||||
// Override parent width constraints (full A4 width)
|
|
||||||
'.cv-page, .cv-paper, .cv-container { max-width: 100% !important; ... }'
|
|
||||||
|
|
||||||
// Show sidebars (override print.css hiding)
|
|
||||||
'.cv-sidebar, .cv-sidebar-left, .cv-sidebar-right { display: block !important; }'
|
|
||||||
|
|
||||||
// Hide mobile UI elements
|
|
||||||
'.sidebar-accordion-header { display: none !important; }'
|
|
||||||
|
|
||||||
// Force page break before page 2
|
|
||||||
'.page-2 { page-break-before: always !important; break-before: page !important; }'
|
|
||||||
|
|
||||||
// 2-column layouts (no wasted space)
|
|
||||||
'.page-1 .page-content { grid-template-columns: 25% 75% !important; }'
|
|
||||||
'.page-2 .page-content { grid-template-columns: 75% 25% !important; }'
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 2. HTML Structure (`templates/cv-content.html`)
|
|
||||||
|
|
||||||
**Page 1**: Left sidebar + Main content
|
|
||||||
```html
|
|
||||||
<div class="cv-page page-1">
|
|
||||||
<div class="page-content">
|
|
||||||
<aside class="cv-sidebar cv-sidebar-left">...</aside>
|
|
||||||
<main class="cv-main">...</main>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Page 2**: Main content + Right sidebar
|
|
||||||
```html
|
|
||||||
<div class="cv-page page-2">
|
|
||||||
<div class="page-content">
|
|
||||||
<main class="cv-main">...</main>
|
|
||||||
<aside class="cv-sidebar cv-sidebar-right">...</aside>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Frontend Integration (`templates/partials/modals/pdf-modal.html`)
|
|
||||||
|
|
||||||
**PDF Modal Options**:
|
|
||||||
- Short CV (4 pages) - `version=clean`
|
|
||||||
- **Long CV (9 pages)** - `version=with_skills` ← This feature
|
|
||||||
- **Short CV with skills (5 pages)** - `length=short&version=with_skills` with compact fonts
|
|
||||||
- Current View - Uses localStorage settings
|
|
||||||
|
|
||||||
## Why 2-Column Layout?
|
|
||||||
|
|
||||||
### ❌ Previous Approach (3-column - WRONG)
|
|
||||||
```css
|
|
||||||
.page-1, .page-2: 25% | 50% | 25% /* Always 3 columns */
|
|
||||||
```
|
|
||||||
- Page 1 had empty right column (25% wasted)
|
|
||||||
- Page 2 had empty left column (25% wasted)
|
|
||||||
- Result: 10-19 pages
|
|
||||||
|
|
||||||
### ✅ Current Approach (2-column - CORRECT)
|
|
||||||
```css
|
|
||||||
.page-1: 25% | 75% /* Left sidebar + Main, NO right space */
|
|
||||||
.page-2: 75% | 25% /* Main + Right sidebar, NO left space */
|
|
||||||
```
|
|
||||||
- No wasted space on either page
|
|
||||||
- Matches web's actual layout exactly
|
|
||||||
- Result: **9 pages**
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
### Sidebar Width Tuning
|
|
||||||
|
|
||||||
Sidebar width affects page count:
|
|
||||||
|
|
||||||
| Width | Layout | Pages | Notes |
|
|
||||||
|-------|--------|-------|-------|
|
|
||||||
| 18% | 18% \| 82% | 9 pages | Too narrow |
|
|
||||||
| 20% | 20% \| 80% | 8 pages | Minimal sidebars |
|
|
||||||
| **25%** | **25% \| 75%** | **9 pages** | ✅ **Current** (optimal balance) |
|
|
||||||
| 30% | 30% \| 70% | 10+ pages | Too wide |
|
|
||||||
|
|
||||||
**Current Setting**: 25% sidebars (`internal/pdf/generator.go:176,181`)
|
|
||||||
|
|
||||||
### Adjusting Sidebar Width
|
|
||||||
|
|
||||||
To change sidebar width, update two lines in `internal/pdf/generator.go`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
// Page 1: Left sidebar (XX%) + Main (YY%) - NO right space
|
|
||||||
'.page-1 .page-content { ' +
|
|
||||||
'grid-template-columns: XX% YY% !important; ' +
|
|
||||||
'} ' +
|
|
||||||
|
|
||||||
// Page 2: Main (YY%) + Right sidebar (XX%) - NO left space
|
|
||||||
'.page-2 .page-content { ' +
|
|
||||||
'grid-template-columns: YY% XX% !important; ' +
|
|
||||||
'} ' +
|
|
||||||
```
|
|
||||||
|
|
||||||
Where `XX + YY = 100`
|
|
||||||
|
|
||||||
## Print Media CSS
|
|
||||||
|
|
||||||
The extended PDF uses `@media print` from `static/css/08-contexts/_print.css` for:
|
|
||||||
- Compact fonts and spacing
|
|
||||||
- Hiding UI chrome (navigation, buttons, footer)
|
|
||||||
- Professional typography
|
|
||||||
|
|
||||||
**Overridden in PDF**:
|
|
||||||
- Sidebar hiding (`.cv-sidebar { display: none }` → `display: block !important`)
|
|
||||||
- Accordion headers (`.sidebar-accordion-header { display: none !important }`)
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Unit Tests
|
|
||||||
|
|
||||||
The long PDF feature has comprehensive test coverage in `internal/handlers/pdf_test.go`:
|
|
||||||
|
|
||||||
**Test Functions:**
|
|
||||||
1. `TestExportPDF_LongWithSkills` - Tests long PDF with multiple language/icon combinations
|
|
||||||
2. `TestPDFGenerator_RenderModes` - Tests both `RenderModePrint` and `RenderModeScreen`
|
|
||||||
3. `TestExportPDF_SkillsSidebarFeatures` - Tests specific skills sidebar features:
|
|
||||||
- Version parameter validation (`clean`, `with_skills`)
|
|
||||||
- PDF modal integration URLs
|
|
||||||
- Frontend button parameter correctness
|
|
||||||
4. `TestPDFGenerator_CompactSidebarFonts` - Tests compact font feature for short version
|
|
||||||
|
|
||||||
Run the tests:
|
|
||||||
```bash
|
|
||||||
go test ./internal/handlers -v -run TestExportPDF
|
|
||||||
```
|
|
||||||
|
|
||||||
### Integration Testing
|
|
||||||
|
|
||||||
Check page count and PDF generation:
|
|
||||||
```bash
|
|
||||||
# Download long PDF (9 pages with sidebars)
|
|
||||||
curl "http://localhost:1999/export/pdf?lang=es&length=long&icons=show&version=with_skills" -o test-long.pdf
|
|
||||||
|
|
||||||
# Download short PDF with skills (5 pages with compact fonts)
|
|
||||||
curl "http://localhost:1999/export/pdf?lang=es&length=short&icons=show&version=with_skills" -o test-short-skills.pdf
|
|
||||||
|
|
||||||
# Download short PDF clean (4 pages, no sidebars)
|
|
||||||
curl "http://localhost:1999/export/pdf?lang=es&length=short&icons=show&version=clean" -o test-short.pdf
|
|
||||||
|
|
||||||
# Verify page counts
|
|
||||||
pdfinfo test-long.pdf | grep Pages
|
|
||||||
# Expected: Pages: 9
|
|
||||||
|
|
||||||
pdfinfo test-short-skills.pdf | grep Pages
|
|
||||||
# Expected: Pages: 5
|
|
||||||
|
|
||||||
pdfinfo test-short.pdf | grep Pages
|
|
||||||
# Expected: Pages: 4
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Verification
|
|
||||||
|
|
||||||
**Long CV (9 pages):**
|
|
||||||
1. Open http://localhost:1999 in browser
|
|
||||||
2. Click "Descargar PDF" button
|
|
||||||
3. Select "CV Largo (9 páginas)" / "Long CV (9 pages)"
|
|
||||||
4. Click "Descargar PDF"
|
|
||||||
5. Verify downloaded PDF has:
|
|
||||||
- 9 pages total
|
|
||||||
- 25% sidebars on left (page 1) and right (page 2+)
|
|
||||||
- Full-size fonts in sidebars
|
|
||||||
- No "Competencias Técnicas" accordion header visible
|
|
||||||
- Page break between page 1 and page 2
|
|
||||||
- Skills content displayed in sidebars
|
|
||||||
|
|
||||||
**Short CV with skills (5 pages with compact fonts):**
|
|
||||||
1. Toggle to short view and with_skills theme
|
|
||||||
2. Download PDF
|
|
||||||
3. Verify:
|
|
||||||
- 5 pages total
|
|
||||||
- Compact sidebar fonts (0.94-0.98em)
|
|
||||||
- All content fits naturally without overflow
|
|
||||||
- Maintained readability
|
|
||||||
|
|
||||||
## API Endpoint
|
|
||||||
|
|
||||||
**URL**: `/export/pdf`
|
|
||||||
|
|
||||||
**Query Parameters**:
|
|
||||||
- `lang` - Language (`es`, `en`)
|
|
||||||
- `length` - CV length (`short`, `long`)
|
|
||||||
- `icons` - Show icons (`show`, `hide`)
|
|
||||||
- `version` - Layout version (`clean`, `with_skills`)
|
|
||||||
|
|
||||||
**Examples**:
|
|
||||||
```bash
|
|
||||||
# Long CV with skills (9 pages, full-size fonts)
|
|
||||||
GET /export/pdf?lang=es&length=long&icons=show&version=with_skills
|
|
||||||
|
|
||||||
# Short CV with skills (5 pages, compact sidebar fonts)
|
|
||||||
GET /export/pdf?lang=es&length=short&icons=show&version=with_skills
|
|
||||||
|
|
||||||
# Short CV clean (4 pages, no sidebars)
|
|
||||||
GET /export/pdf?lang=es&length=short&icons=show&version=clean
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Issue: Sidebars not showing
|
|
||||||
**Solution**: Check `RenderModeScreen` is being used (not `RenderModePrint`)
|
|
||||||
|
|
||||||
### Issue: Wrong page count
|
|
||||||
**Solution**:
|
|
||||||
1. Check sidebar width percentage (should be 25%)
|
|
||||||
2. Verify CSS injection is working
|
|
||||||
3. Check for browser console errors
|
|
||||||
|
|
||||||
### Issue: Accordion header visible
|
|
||||||
**Solution**: Ensure `.sidebar-accordion-header { display: none !important; }` in CSS injection
|
|
||||||
|
|
||||||
### Issue: No page break between pages
|
|
||||||
**Solution**: Verify `.page-2 { page-break-before: always !important; }` is applied
|
|
||||||
|
|
||||||
## Compact Sidebar Fonts Feature
|
|
||||||
|
|
||||||
### Overview
|
|
||||||
|
|
||||||
The compact sidebar fonts feature automatically reduces sidebar font sizes by 2-6% **only for short CVs with skills** (`length=short&version=with_skills`), reducing page count from 6 pages to 5 pages while maintaining excellent readability.
|
|
||||||
|
|
||||||
**Impact:**
|
|
||||||
- **Page count reduction**: 6 pages → 5 pages (16.7% reduction)
|
|
||||||
- **Font size reduction**: 2-6% (very subtle, 0.94-0.98em)
|
|
||||||
- **Readability**: Maintained - fonts remain professional and readable
|
|
||||||
- **Only for short version**: Long version uses full-size fonts
|
|
||||||
|
|
||||||
### When It Activates
|
|
||||||
|
|
||||||
The feature automatically activates when **both** conditions are met:
|
|
||||||
1. `length=short` (detected via `cv-length` cookie)
|
|
||||||
2. `version=with_skills` (RenderModeScreen with sidebars)
|
|
||||||
|
|
||||||
**Does NOT activate for:**
|
|
||||||
- Long CVs (`length=long`) - always use full-size fonts
|
|
||||||
- Clean version (`version=clean`) - no sidebars shown
|
|
||||||
- Short clean version - no sidebars to compact
|
|
||||||
|
|
||||||
### Implementation
|
|
||||||
|
|
||||||
**Location**: `internal/pdf/generator.go` (lines 154-215)
|
|
||||||
|
|
||||||
**Cookie Detection**:
|
|
||||||
```go
|
|
||||||
// Check if this is a short version (to apply compact sidebar fonts)
|
|
||||||
// The length parameter is passed as a cookie, not in the URL
|
|
||||||
isShortVersion := cookies["cv-length"] == "short"
|
|
||||||
```
|
|
||||||
|
|
||||||
**CSS Injection** (only when `isShortVersion == true`):
|
|
||||||
```go
|
|
||||||
compactFontCSS := ""
|
|
||||||
if isShortVersion {
|
|
||||||
compactFontCSS = ` +
|
|
||||||
// Compact sidebar fonts (SHORT VERSION ONLY) - very subtle reduction
|
|
||||||
'.cv-sidebar * { font-size: 0.96em !important; line-height: 1.4 !important; } ' +
|
|
||||||
'.cv-sidebar h3 { font-size: 0.98em !important; margin: 0.4em 0 !important; } ' +
|
|
||||||
'.cv-sidebar h4 { font-size: 0.96em !important; margin: 0.35em 0 !important; } ' +
|
|
||||||
'.cv-sidebar p, .cv-sidebar li { font-size: 0.94em !important; line-height: 1.4 !important; } ' +
|
|
||||||
'.cv-sidebar ul, .cv-sidebar ol { margin: 0.4em 0 0.4em 1.2em !important; } ' +
|
|
||||||
'.cv-sidebar li { margin-bottom: 0.25em !important; } ' +
|
|
||||||
'.cv-sidebar section { margin-bottom: 0.8em !important; } '`
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Font Size Breakdown
|
|
||||||
|
|
||||||
| Element | Full-Size (Long) | Compact (Short) | Reduction |
|
|
||||||
|---------|------------------|-----------------|-----------|
|
|
||||||
| General text | 1.0em | 0.96em | 4% |
|
|
||||||
| H3 headings | 1.0em | 0.98em | 2% |
|
|
||||||
| H4 headings | 1.0em | 0.96em | 4% |
|
|
||||||
| Paragraphs & lists | 1.0em | 0.94em | 6% |
|
|
||||||
|
|
||||||
**Line height**: Consistent 1.4 for improved readability
|
|
||||||
|
|
||||||
### Design Philosophy
|
|
||||||
|
|
||||||
**Why subtle reduction?**
|
|
||||||
1. **Readability first**: 2-6% reduction is barely noticeable
|
|
||||||
2. **Professional appearance**: No "squeezed" or cramped feel
|
|
||||||
3. **Natural flow**: Content reflows organically, not forced
|
|
||||||
4. **Consistent UX**: Main content uses full-size fonts
|
|
||||||
|
|
||||||
**Why only short version?**
|
|
||||||
- Short CV has less content → compact fonts sufficient
|
|
||||||
- Long CV needs maximum readability for extensive content
|
|
||||||
- Consistent with "short = concise, long = comprehensive" semantics
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
|
|
||||||
**Test function**: `TestPDFGenerator_CompactSidebarFonts` in `internal/handlers/pdf_test.go`
|
|
||||||
|
|
||||||
**Test coverage:**
|
|
||||||
1. Cookie-based detection (`cv-length=short` vs `cv-length=long`)
|
|
||||||
2. PDF generation with compact fonts
|
|
||||||
3. Version parameter validation (`with_skills` vs `clean`)
|
|
||||||
4. Page count verification (5 pages for short with skills)
|
|
||||||
|
|
||||||
**Run tests**:
|
|
||||||
```bash
|
|
||||||
go test ./internal/handlers -v -run TestPDFGenerator_CompactSidebarFonts
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Verification
|
|
||||||
|
|
||||||
1. Navigate to http://localhost:1999
|
|
||||||
2. Toggle to **short view** (localStorage: `cv-length=short`)
|
|
||||||
3. Toggle to **with_skills theme** (localStorage: `cv-theme=default` or `with_skills`)
|
|
||||||
4. Download PDF
|
|
||||||
5. Verify:
|
|
||||||
- **5 pages total** (not 6)
|
|
||||||
- Sidebar fonts slightly smaller than main content
|
|
||||||
- Still professional and readable
|
|
||||||
- No content overflow or truncation
|
|
||||||
|
|
||||||
**Compare with long version:**
|
|
||||||
1. Toggle to **long view** (`cv-length=long`)
|
|
||||||
2. Download PDF
|
|
||||||
3. Verify:
|
|
||||||
- **9 pages total**
|
|
||||||
- Sidebar fonts same size as short version main content
|
|
||||||
- Full-size fonts throughout
|
|
||||||
|
|
||||||
### Troubleshooting
|
|
||||||
|
|
||||||
#### Issue: Short PDF still has 6 pages
|
|
||||||
**Solution**:
|
|
||||||
1. Verify `cv-length` cookie is set to `short` (check browser DevTools)
|
|
||||||
2. Ensure `isShortVersion` detection works in generator.go:156
|
|
||||||
3. Check CSS injection is applied (add debug logging)
|
|
||||||
|
|
||||||
#### Issue: Fonts too small or hard to read
|
|
||||||
**Solution**:
|
|
||||||
1. Adjust font size percentages in generator.go:206-214
|
|
||||||
2. Increase from 0.94em to 0.96em for paragraphs
|
|
||||||
3. Test with actual content to verify readability
|
|
||||||
|
|
||||||
#### Issue: Long version also has compact fonts
|
|
||||||
**Solution**:
|
|
||||||
1. Check cookie detection logic - must be `cookies["cv-length"] == "short"`
|
|
||||||
2. Verify compactFontCSS is only appended when `isShortVersion == true`
|
|
||||||
3. Ensure long version passes `cv-length=long` cookie
|
|
||||||
|
|
||||||
## Future Improvements
|
|
||||||
|
|
||||||
- [ ] Make sidebar width configurable via query parameter
|
|
||||||
- [ ] Add option to customize page break positioning
|
|
||||||
- [ ] Support for different paper sizes (Letter, Legal)
|
|
||||||
- [ ] Transparent background option
|
|
||||||
- [ ] Custom padding/margin configuration
|
|
||||||
|
|
||||||
## Related Files
|
|
||||||
|
|
||||||
- `internal/pdf/generator.go` - PDF generation logic
|
|
||||||
- `templates/cv-content.html` - HTML structure
|
|
||||||
- `templates/partials/modals/pdf-modal.html` - Frontend UI
|
|
||||||
- `static/css/08-contexts/_print.css` - Print media CSS
|
|
||||||
- `internal/handlers/pdf.go` - HTTP handler
|
|
||||||
- `tests/mjs/24-pdf-download-params.test.mjs` - Frontend tests
|
|
||||||
Reference in New Issue
Block a user