78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from core.exceptions import FileValidationError
|
|
|
|
MAX_FILE_SIZE_MB = 100
|
|
SUPPORTED_VERSIONS = {'1.0', '2.0'}
|
|
REQUIRED_FIELDS = {'document', 'styles', 'pages', 'fonts_used'}
|
|
|
|
|
|
class ExportValidator:
|
|
"""Validates idconvert_export.json before any parsing occurs."""
|
|
|
|
def validate(self, content: bytes) -> dict:
|
|
"""Run all validation checks. Returns parsed dict on success.
|
|
Raises FileValidationError on any failure.
|
|
"""
|
|
# 1. File size
|
|
size_mb = len(content) / (1024 * 1024)
|
|
if size_mb > MAX_FILE_SIZE_MB:
|
|
raise FileValidationError(
|
|
f'File exceeds {MAX_FILE_SIZE_MB}MB limit.',
|
|
'FILE_TOO_LARGE',
|
|
)
|
|
|
|
# 2. Valid JSON
|
|
try:
|
|
data = json.loads(content)
|
|
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
raise FileValidationError(
|
|
'This does not appear to be a valid IDexport file. '
|
|
'Please run IDexport.jsx in InDesign and upload the '
|
|
'idconvert_export.json file it produces.',
|
|
'INVALID_JSON',
|
|
)
|
|
|
|
if not isinstance(data, dict):
|
|
raise FileValidationError(
|
|
'IDexport file has an unexpected format.',
|
|
'INVALID_FORMAT',
|
|
)
|
|
|
|
# 3. Generator signature
|
|
if data.get('generator') != 'IDexport':
|
|
raise FileValidationError(
|
|
'This JSON file was not produced by IDexport. '
|
|
'Please run IDexport.jsx in InDesign to generate '
|
|
'a compatible export file.',
|
|
'WRONG_GENERATOR',
|
|
)
|
|
|
|
# 4. Version check
|
|
if data.get('version') not in SUPPORTED_VERSIONS:
|
|
raise FileValidationError(
|
|
'This IDexport file was created with an incompatible version. '
|
|
'Please download the latest IDexport.jsx from IDconvert.',
|
|
'VERSION_MISMATCH',
|
|
)
|
|
|
|
# 5. Required top-level fields
|
|
for f in REQUIRED_FIELDS:
|
|
if f not in data:
|
|
raise FileValidationError(
|
|
f'IDexport file is missing required field: {f}. '
|
|
'Please re-run IDexport.jsx and try again.',
|
|
'MISSING_FIELD',
|
|
)
|
|
|
|
# 6. Pages must be a non-empty list
|
|
if not isinstance(data.get('pages'), list) or len(data['pages']) == 0:
|
|
raise FileValidationError(
|
|
'IDexport file contains no pages.',
|
|
'NO_PAGES',
|
|
)
|
|
|
|
return data
|