Skip to content
Back to skills

279 Workflow A7a306ce

ASecurity

Complete guide for the 4-phase conversion process.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 31, 2026
businesspythongobash

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned May 31, 2026

npx -y skills add tools-only/X-Skills --skill 279-workflow_a7a306ce --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 279 Workflow A7a306ce?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 279 Workflow A7a306ce
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-279-workflow-a7a306ce/badge)](https://www.skillsdirectory.com/skills/tools-only-279-workflow-a7a306ce)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
# PDF to EPUB Workflow

Complete guide for the 4-phase conversion process.

## Phase 1: Analyze PDF

### Goal
Understand the PDF structure before conversion to generate optimal configuration.

### Automated analysis (recommended)
Use the built-in analyzer to produce an analysis report and suggested config:

```bash
python -m scripts.analyze input.pdf --output analysis.json
```

```python
from conversion.pdf_analyzer import PDFAnalyzer

analyzer = PDFAnalyzer("input.pdf")
analysis = analyzer.analyze()
config = analyzer.generate_config()
```

### Steps

1. **Open PDF and get basic info**
```python
import fitz
doc = fitz.open("input.pdf")
print(f"Pages: {len(doc)}")
print(f"Title: {doc.metadata.get('title', 'Unknown')}")
print(f"Author: {doc.metadata.get('author', 'Unknown')}")
```

2. **Detect layout type**
```python
# Sample a few pages (e.g., pages 5, 10, 15)
for page_num in [5, 10, 15]:
    page = doc[page_num]
    blocks = page.get_text("dict")["blocks"]

    # Check x-coordinates of text blocks
    x_coords = [b["bbox"][0] for b in blocks if b["type"] == 0]

    # If blocks cluster at 2+ distinct x positions → multi-column
    if len(set(round(x/50)*50 for x in x_coords)) > 1:
        print(f"Page {page_num}: Multi-column detected")
```

3. **Check for images**
```python
total_images = 0
for page in doc:
    images = page.get_images()
    total_images += len(images)
print(f"Total images: {total_images}")
```

4. **Detect footnotes/endnotes**
```python
import re
# Look for patterns like [1], (1), superscript numbers
footnote_pattern = re.compile(r'\[\d{1,2}\]|\(\d{1,2}\)')
for page in doc:
    text = page.get_text()
    matches = footnote_pattern.findall(text)
    if matches:
        print(f"Footnote references found: {matches[:5]}")
        break
```

5. **Analyze font sizes**
```python
# Find dominant body font size
font_sizes = []
for page in doc[:10]:
    blocks = page.get_text("dict")["blocks"]
    for block in blocks:
        if block["type"] == 0:  # text block
            for line in block["lines"]:
                for span in line["spans"]:
                    font_sizes.append(span["size"])

from collections import Counter
body_size = Counter(font_sizes).most_common(1)[0][0]
print(f"Body font size: {body_size}")
```

### Output: Proposed Configuration

Based on analysis, generate a config:

```python
from conversion.models import (
    ConversionConfig, PageRanges, ExcludeRegions,
    HeadingConfig, ImageOptimizationConfig
)

config = ConversionConfig(
    page_ranges=PageRanges(
        skip=[1, 2],  # Skip title pages
        content=(3, -3),  # Main content
        endnotes=(-2, -1),  # Last 2 pages for endnotes
    ),
    exclude_regions=ExcludeRegions(
        top=0.05,  # 5% for headers
        bottom=0.05,  # 5% for footers/page numbers
    ),
    reading_order_strategy="y_sort",  # or "xy_cut" if multi-column
    heading_detection=HeadingConfig(
        font_size_threshold=1.2,  # 20% larger than body = heading
    ),
    image_optimization=ImageOptimizationConfig(
        enabled=True,
        max_width=1200,
        jpeg_quality=85,
    ),
)
```

### User Confirmation

Before proceeding, show the proposed config and ask:

> "I've analyzed the PDF. Here's my proposed configuration:
> - Reading order: Y-sort (single column)
> - Skip pages: 1-2 (title pages)
> - Image optimization: Enabled
>
> Does this look correct? Any adjustments needed?"

---

## Phase 2: Convert

### Goal
Apply configuration and build EPUB file.

### Steps

1. **Initialize converter**
```python
from conversion.converter import Converter

converter = Converter(strategy="simple")
```

2. **Run conversion**
```python
from pathlib import Path

result = converter.convert(
    pdf_path=Path("input.pdf"),
    output_path=Path("output.epub"),
    config=config
)
```

3. **Check result**
```python
print(f"Chapters: {len(result.content.chapters)}")
print(f"Images: {len(result.content.images)}")
print(f"Reading order confidence: {result.reading_order_confidence:.2f}")

# Warn if low confidence
if result.reading_order_confidence < 0.7:
    print("WARNING: Low confidence in reading order. Consider xy_cut strategy.")
```

### What Happens Internally

```
PDF → extract() → TextBlocks + Images + Metadata
                        ↓
        order_blocks() → OrderedBlocks + Confidence
                        ↓
        detect_structure() → Chapters
                        ↓
        EPUBBuilder.build() → EPUB File
```

---

## Phase 3: Validate

### Goal
Verify conversion quality meets thresholds.

### Steps

1. **Extract text from both files**
```python
from core.pdf_extractor import PDFExtractor
from core.epub_extractor import EPUBExtractor

pdf_text = PDFExtractor().extract_text(pdf_path)
epub_text = EPUBExtractor().extract_text(epub_path)
```

2. **Check completeness**
```python
from validation.completeness_checker import CompletenessChecker

checker = CompletenessChecker()
result = checker.check(pdf_text, epub_text)

print(f"Completeness: {result.score:.1%}")
print(f"PDF words: {result.source_word_count}")
print(f"EPUB words: {result.target_word_count}")
print(f"Loss: {result.loss_percentage:.1f}%")
```

3. **Check reading order**
```python
from validation.order_checker import OrderChecker
from core.text_segmenter import TextSegmenter

segmenter = TextSegmenter()
pdf_chunks = segmenter.segment(pdf_text)
epub_chunks = segmenter.segment(epub_text)

order_checker = OrderChecker()
result = order_checker.check(pdf_chunks, epub_chunks)

print(f"Order score: {result.score:.1%}")
```

### Quality Gates

| Metric | Threshold | Action if Failed |
|--------|-----------|------------------|
| Completeness | > 95% | Check exclude_regions, page_ranges |
| Order score | > 80% | Try xy_cut, check multi_column |
| Confidence | > 0.6 | Review warnings, may need manual check |

### Validation Report

```python
def print_validation_report(completeness, order, confidence):
    print("=" * 50)
    print("VALIDATION REPORT")
    print("=" * 50)

    # Completeness
    status = "PASS" if completeness.score > 0.95 else "FAIL"
    print(f"Completeness: {completeness.score:.1%} [{status}]")

    # Order
    status = "PASS" if order.score > 0.80 else "FAIL"
    print(f"Order score: {order.score:.1%} [{status}]")

    # Confidence
    status = "PASS" if confidence > 0.6 else "WARNING"
    print(f"Confidence: {confidence:.2f} [{status}]")

    print("=" * 50)
```

---

## Phase 4: Adapt (If Needed)

### Goal
Fix issues identified in validation.

### Decision Process

```
1. Identify the problem (completeness? order? headings?)
2. Try configuration change first (Layer 2)
3. If config doesn't help after 2-3 attempts → modify code (Layer 3)
4. Never modify FROZEN files (Layer 1)
```

### Example: Fixing Text Loss

```python
# Problem: 8% text loss (>5% threshold)

# Step 1: Check what's being cut
# Look at exclude_regions - maybe too aggressive?
config.exclude_regions.top = 0.03  # Reduce from 0.05

# Step 2: Re-run conversion
result = converter.convert(pdf_path, epub_path, config)

# Step 3: Re-validate
# If still failing, check page_ranges
config.page_ranges.skip = []  # Don't skip any pages

# Step 4: If still failing, investigate specific pages
# Use debug mode to see what's happening on each page
```

### Example: Fixing Reading Order

```python
# Problem: Order score 65% (<80% threshold)

# Step 1: Switch to xy_cut for column detection
config.reading_order_strategy = "xy_cut"

# Step 2: Re-run and validate
result = converter.convert(pdf_path, epub_path, config)

# Step 3: If still wrong, tune threshold
config.multi_column.threshold = 0.3  # More sensitive

# Step 4: If still failing, may need custom sorter
# See reference/code-adaptation.md
```

---

## Complete Example

```python
from pathlib import Path
from conversion.converter import Converter
from conversion.models import *
from validation.completeness_checker import CompletenessChecker
from validation.order_checker import OrderChecker

# Phase 1: Configure
config = ConversionConfig(
    page_ranges=PageRanges(skip=[1, 2], content=(3, -3)),
    exclude_regions=ExcludeRegions(top=0.05, bottom=0.05),
    reading_order_strategy="y_sort",
    image_optimization=ImageOptimizationConfig(enabled=True),
)

# Phase 2: Convert
converter = Converter(strategy="simple")
pdf_path = Path("book.pdf")
epub_path = Path("book.epub")

result = converter.convert(pdf_path, epub_path, config)
print(f"Confidence: {result.reading_order_confidence:.2f}")

# Phase 3: Validate
# ... (run completeness and order checks)

# Phase 4: Adapt if needed
if completeness.score < 0.95:
    config.exclude_regions.top = 0.03
    result = converter.convert(pdf_path, epub_path, config)
    # Re-validate...
```

Files in this skill

  • README.md833 B
  • skill.md8.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.