Skip to main content

Validation

MD-Slides validates every slide before rendering. All errors are collected and reported together — you see every problem in one pass, not one at a time. No output is written until every slide passes.

✗ Validation failed:
- Slide 3: body exceeds max 12 lines (has 17)
- Slide 5: heading exceeds max 80 characters (has 94)
- Slide 7: image is missing alt text
- Slide 12: two-column left exceeds max 10 lines (has 13)

Fix them all, then re-render.

What gets validated

Structure: required slots present, template declared, frontmatter well-formed, two-column has exactly one ---column---.

Density:

TemplateHeadingBody
titleTitle ≤ 2 lines, subtitle ≤ 2 lines, author ≤ 80 chars
content≤ 80 chars≤ 12 lines, ≤ 150 words
section-title≤ 80 chars≤ 12 lines, ≤ 150 words
two-column≤ 80 charsEach column ≤ 10 lines, ≤ 75 words
closing≤ 80 chars≤ 12 lines, ≤ 150 words

Accessibility (WCAG 2.1 AA):

  • Images must have alt text
  • Text/background contrast ratios must meet 4.5:1 minimum

Accessibility flags

# Skip WCAG contrast checks (structural and density validation still runs)
java -jar md-slides.jar render my-talk --skip-accessibility

# Write validation results to a JSON file (useful in CI)
java -jar md-slides.jar render my-talk --accessibility-report report.json

Why all errors at once?

Stopping at the first error means a loop: fix, render, find next error, fix, render. Showing everything at once respects your time. The domain model uses Either[NonEmptyList[ValidationError], SlideDeck] — errors accumulate rather than short-circuit. An empty error list is a type-level impossibility.

Why density limits?

Dense slides are the most common presentation failure mode — content that looks fine in an editor is unreadable on a projector. MD-Slides enforces limits at render time so you catch the problem before you're standing in front of an audience. If you find yourself fighting the limits, that's usually a signal to split the slide.