Files
cv-site/doc/LONG-PDF-GENERATION.md
T
juanatsap b44f9b9a99 refactor: Rename 'extended' → 'long' + add compact sidebar fonts
BREAKING CHANGE: API parameter renamed from 'extended' to 'long'

## Breaking Change: Terminology Standardization

Renamed 'extended' to 'long' across entire codebase for consistency:

**Backend (Go):**
- internal/handlers/cv.go (7 locations)
  - Migration logic to auto-convert 'extended' → 'long' cookies
  - API validation now rejects 'extended', requires 'long'
  - Toggle state logic updated
- internal/handlers/pdf_test.go (17 occurrences)
  - Test function renamed: TestExportPDF_ExtendedWithSkills → TestExportPDF_LongWithSkills
  - All test cases, parameters, and expected filenames updated
- internal/pdf/generator.go (2 comment updates)

**Frontend:**
- PDF-EXPORT-FEATURE.md (3 occurrences)
- doc/3-API.md (parameter documentation)
- doc/7-CUSTOMIZATION.md (examples updated)
- templates/partials/modals/pdf-modal.html (button text, URLs)
- static/js/main.js (migration logic)
- static/hyperscript/toggles._hs (toggle logic)
- tests/mjs/24-pdf-download-params.test.mjs (test expectations)
- tests/mjs/test-preference-migration.test.mjs (NEW)
- tests/mjs/verify-migration.test.mjs (NEW)

**PDFs Renamed:**
- cv-extended-with_skills-jamr-2025-en.pdf → cv-long-with_skills-jamr-2025-en.pdf
- cv-extended-with_skills-jamr-2025-es.pdf → cv-long-with_skills-jamr-2025-es.pdf

**Migration:** Automatic cookie migration from 'extended' → 'long' for seamless UX

## New Feature: Compact Sidebar Fonts

Reduces page count for short CV with skills from 6 → 5 pages:

**Implementation:**
- Location: internal/pdf/generator.go (lines 154-215)
- Cookie detection: `cookies["cv-length"] == "short"`
- Font reduction: 2-6% (0.94-0.98em) - very subtle
- Only activates for: `length=short` + `version=with_skills`
- Long version: Always uses full-size fonts

**Impact:**
- Page count: 6 pages → 5 pages (16.7% reduction)
- Readability: Maintained - fonts remain professional
- Design philosophy: Subtle, natural content flow

**Testing:**
- New test: TestPDFGenerator_CompactSidebarFonts
- Comprehensive coverage of cookie detection and PDF generation
- Manual verification: 5-page PDF with compact but readable fonts

**Documentation:**
- doc/LONG-PDF-GENERATION.md (NEW, 13 KB)
  - Complete feature documentation
  - Implementation details with code examples
  - Font size breakdown table
  - Testing and troubleshooting guides
  - Compact sidebar fonts section (comprehensive)

**Files Changed:**
- 11 modified (backend + frontend + docs)
- 5 new files (2 PDFs, 1 doc, 2 tests)
- 2 files renamed (PDFs)

**Tests:** All Go tests passing, API validation verified, PDF generation tested
2025-11-20 11:21:43 +00:00

13 KiB

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:

// 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

<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

<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)

.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)

.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:

// 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:

go test ./internal/handlers -v -run TestExportPDF

Integration Testing

Check page count and PDF generation:

# 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:

# 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:

// 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):

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:

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
  • 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