Metadata-Version: 2.5
Name: betacalendars-printlint
Version: 0.1.0
Summary: Validate printable calendar grids, SVG/PDF page geometry, and Gregorian month fixtures.
Project-URL: Homepage, https://www.betacalendars.com/
Project-URL: Documentation, https://mateopedersen.github.io/betacalendars-printlint/
Project-URL: Source, https://github.com/mateopedersen/betacalendars-printlint
Project-URL: Issues, https://github.com/mateopedersen/betacalendars-printlint/issues
Project-URL: Changelog, https://github.com/mateopedersen/betacalendars-printlint/blob/main/CHANGELOG.md
Project-URL: Security, https://github.com/mateopedersen/betacalendars-printlint/blob/main/SECURITY.md
Author: Mateo Pedersen
License-Expression: MIT
License-File: LICENSE
Keywords: calendar,gregorian,layout,lint,pdf,printable,svg,validation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Printing
Classifier: Topic :: Software Development :: Testing
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: pypdf>=5.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: hatchling>=1.27; extra == 'dev'
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pytest>=8.3; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Requires-Dist: twine>=6.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocs>=1.6; extra == 'docs'
Description-Content-Type: text/markdown

# BetaCalendars PrintLint

BetaCalendars PrintLint is a typed Python library and command-line tool for checking printable calendar data and page artifacts before they are released. It validates Gregorian month grids, JSON manifests, blank layouts, SVG structure, PDF page boxes, and declared print geometry. It does not fetch web pages or depend on the current date, timezone, or locale.

## Human-Readable Calendar References

PrintLint calculates calendar topology independently. These human-readable Beta Calendars pages help developers manually compare a validated fixture with a printable layout.

| Resource | Reference |
| --- | --- |
| Beta Calendars | [betacalendars.com](https://www.betacalendars.com/) |
| Blank Calendar | [Blank Calendar](https://www.betacalendars.com/blank-calendar) |
| January Calendar | [January Calendar](https://www.betacalendars.com/january-calendar.html) |
| February Calendar | [February Calendar](https://www.betacalendars.com/february-calendar.html) |
| March Calendar | [March Calendar](https://www.betacalendars.com/march-calendar.html) |
| April Calendar | [April Calendar](https://www.betacalendars.com/april-calendar.html) |
| May Calendar | [May Calendar](https://www.betacalendars.com/may-calendar.html) |
| June Calendar | [June Calendar](https://www.betacalendars.com/june-calendar.html) |
| July Calendar | [July Calendar](https://www.betacalendars.com/july-calendar.html) |
| August Calendar | [August Calendar](https://www.betacalendars.com/august-calendar.html) |
| September Calendar | [September Calendar](https://www.betacalendars.com/september-calendar.html) |
| October Calendar | [October Calendar](https://www.betacalendars.com/october-calendar.html) |
| November Calendar | [November Calendar](https://www.betacalendars.com/november-calendar.html) |
| December Calendar | [December Calendar](https://www.betacalendars.com/december-calendar.html) |

## Installation

```console
python -m pip install betacalendars-printlint
```

The library supports Python 3.10 and later. PDF checks use the `pypdf` library. There is no network access during package execution.

## Quick Start

Generate a canonical January 2027 grid and validate an exported A4 SVG:

```console
betacal-printlint calendar --year 2027 --month 1 --week-start monday --grid-mode fixed-six-weeks
betacal-printlint check calendar.svg --year 2027 --month 1 --week-start monday --paper a4 --orientation portrait
```

Validate a JSON manifest or PDF:

```console
betacal-printlint manifest fixtures/2027/01-january.json --format json
betacal-printlint pdf calendar.pdf --paper a4 --orientation portrait
```

The `check` command selects a validator by file extension (`.json`, `.svg`, `.pdf`). JSON output has a stable machine-readable shape: `valid`, `errors`, `warnings`, `checks`, and `details`. SARIF 2.1.0 output is available for validation findings.

## What It Validates

- **Gregorian model and grid:** month length, first and last weekdays, all seven week starts, chronological date coverage, uniqueness, leading and trailing cells, row and column coordinates, natural grids, and exact 6 × 7 fixed grids.
- **JSON manifests:** calendar specification, cell dates and positions, paper presets, declared geometry, and optional metadata. See the [manifest schema](src/betacalendars_printlint/schemas/calendar-manifest.schema.json).
- **Print geometry:** A4, US Letter, A5, and Legal dimensions in millimeters; portrait and landscape; margins; grid bounds; and a configurable day-cell-height warning. These checks do not guarantee margins supported by every physical printer.
- **SVG:** well-formed XML, physical dimensions, viewBox, optional marked grid bounds (`data-printlint-grid="true"`), and active or remote content. The validator never executes SVG code or loads referenced resources.
- **PDF:** parseability, encryption state, page count, page orientation, and media-box dimensions within a documented millimeter tolerance. It does not use OCR or claim to validate the visual location of dates on a page.
- **Blank calendars:** rectangular cell count and absence of dates or day numbers.

## CLI

```console
betacal-printlint --help
betacal-printlint version
betacal-printlint explain geometry
betacal-printlint blank fixtures/blank-calendar.json
betacal-printlint fixture fixtures/2027/02-february.json
betacal-printlint pdf calendar.pdf --paper letter --format sarif
```

Exit status is `0` when there are no errors, `1` when validation finds errors, and `2` for invalid command-line options. Warnings are reported but do not invalidate a result. `check` accepts `.json`, `.svg`, and `.pdf`; use the specialized commands for explicit validation.

## Python API

```python
from betacalendars_printlint import CalendarSpec, build_month_grid, validate_manifest

grid = build_month_grid(CalendarSpec(2027, 1, "monday", "fixed-six-weeks"))
assert grid.rows == 6 and grid.columns == 7

report = validate_manifest("fixtures/2027/01-january.json")
if not report.valid:
    for issue in report.errors:
        print(issue.code, issue.message)
```

Public entry points include `CalendarSpec`, `build_month_grid`, `validate_calendar`, `validate_manifest`, `validate_blank_grid`, `validate_svg`, and `validate_pdf`. Reports expose typed checks, errors, warnings, details, and `to_dict()`.

## Gregorian Rules

Leap years are divisible by four, except century years that are not divisible by 400. PrintLint's tests cover the century cases 1900, 2000, 2024, 2027, 2100, and 2400. A broad regression checks every month from 1900 through 2100 under all seven week starts. No current time, timezone, daylight-saving rule, or translated locale enters the calculation.

## Manifest and Fixtures

The JSON manifest describes a month, a seven-column grid, optional paper dimensions, and per-cell dates. Adjacent-month cells carry `monthOffset`; hidden adjacent dates use `null` cells. The blank-grid fixture is intentionally date-free and is validated separately. Committed examples include twelve 2027 months and the November 2026–February 2027 year boundary.

```console
betacal-printlint manifest fixtures/year-boundary/2026-12.json
betacal-printlint manifest fixtures/year-boundary/2027-01.json
```

## SVG and PDF Safety

SVG input is parsed as XML after rejecting DTD/entity declarations. Scripts, event-handler attributes, `foreignObject`, remote `href`/`src` values, and external CSS resources are reported. Static SVG geometry remains declarative; no JavaScript or remote content is run. For optional grid-bound checking, mark an SVG rectangle or group with `data-printlint-grid="true"` and numeric `x`, `y`, `width`, and `height` attributes in viewBox units.

PDF processing reads page boxes using pypdf and does not execute embedded content, render pages, or perform OCR. Encrypted files are reported as unavailable for inspection without a password; PrintLint does not request or guess passwords.

## CI Integration

The GitHub Actions workflow runs lint, strict type checking, tests, the 1900–2100 regression, documentation build, distribution build, `twine check`, and clean installation checks from both wheel and source distribution. JSON and SARIF reports can be consumed by downstream CI jobs.

## Documentation

The [project documentation](https://mateopedersen.github.io/betacalendars-printlint/) covers installation, CLI usage, Python API, schema, validators, geometry, CI, fixtures, and security. Month reference pages link only to their corresponding printable calendar.

## Source and Issues

- Source: <https://github.com/mateopedersen/betacalendars-printlint>
- Issues: <https://github.com/mateopedersen/betacalendars-printlint/issues>
- Security policy: [SECURITY.md](SECURITY.md)
- Changelog: [CHANGELOG.md](CHANGELOG.md)

## License

MIT. See [LICENSE](LICENSE).
