277 lines
8.9 KiB
Python
277 lines
8.9 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from export.models import (
|
|
IDExportCharacterStyle,
|
|
IDExportDocument,
|
|
IDExportImageFrame,
|
|
IDExportPage,
|
|
IDExportPageNumber,
|
|
IDExportParagraph,
|
|
IDExportParagraphStyle,
|
|
IDExportRun,
|
|
IDExportShape,
|
|
IDExportTable,
|
|
IDExportTableCell,
|
|
IDExportTableRow,
|
|
IDExportTextFrame,
|
|
)
|
|
|
|
|
|
class IDExportDocumentFactory:
|
|
"""Builds IDExportDocument from a validated idconvert_export.json dict."""
|
|
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportDocument:
|
|
doc_info = data.get('document', {})
|
|
styles_data = data.get('styles', {})
|
|
|
|
paragraph_styles = [
|
|
IDExportParagraphStyleFactory.from_dict(s)
|
|
for s in styles_data.get('paragraph', [])
|
|
]
|
|
character_styles = [
|
|
IDExportCharacterStyleFactory.from_dict(s)
|
|
for s in styles_data.get('character', [])
|
|
]
|
|
|
|
pages = [
|
|
IDExportPageFactory.from_dict(p)
|
|
for p in data.get('pages', [])
|
|
]
|
|
|
|
# Find first page_number item across all pages for footer use
|
|
page_number_style: Optional[IDExportPageNumber] = None
|
|
for page in pages:
|
|
for item in page.items:
|
|
if isinstance(item, IDExportPageNumber):
|
|
page_number_style = item
|
|
break
|
|
if page_number_style:
|
|
break
|
|
|
|
return IDExportDocument(
|
|
name=doc_info.get('name', 'Document'),
|
|
page_width_pt=float(doc_info.get('page_width_pt', 595.28)),
|
|
page_height_pt=float(doc_info.get('page_height_pt', 841.89)),
|
|
page_count=int(doc_info.get('page_count', len(pages))),
|
|
facing_pages=bool(doc_info.get('facing_pages', False)),
|
|
paragraph_styles=paragraph_styles,
|
|
character_styles=character_styles,
|
|
colors=data.get('colors', {}),
|
|
fonts_used=data.get('fonts_used', []),
|
|
pages=pages,
|
|
page_number_style=page_number_style,
|
|
)
|
|
|
|
|
|
class IDExportParagraphStyleFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportParagraphStyle:
|
|
return IDExportParagraphStyle(
|
|
name=data.get('name', ''),
|
|
font=data.get('font'),
|
|
size_pt=_optional_float(data.get('size_pt')),
|
|
leading_pt=_optional_float(data.get('leading_pt')),
|
|
space_before_pt=float(data.get('space_before_pt', 0)),
|
|
space_after_pt=float(data.get('space_after_pt', 0)),
|
|
alignment=data.get('alignment', 'left'),
|
|
color_hex=data.get('color_hex'),
|
|
bold=bool(data.get('bold', False)),
|
|
italic=bool(data.get('italic', False)),
|
|
)
|
|
|
|
|
|
class IDExportCharacterStyleFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportCharacterStyle:
|
|
return IDExportCharacterStyle(
|
|
name=data.get('name', ''),
|
|
font=data.get('font'),
|
|
bold=bool(data.get('bold', False)),
|
|
italic=bool(data.get('italic', False)),
|
|
color_hex=data.get('color_hex'),
|
|
)
|
|
|
|
|
|
class IDExportPageFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportPage:
|
|
items = [
|
|
IDExportItemFactory.from_dict(item)
|
|
for item in data.get('items', [])
|
|
if item
|
|
]
|
|
items = [i for i in items if i is not None]
|
|
|
|
return IDExportPage(
|
|
page_number=data.get('page_number', 1),
|
|
width_pt=float(data.get('width_pt', 595.28)),
|
|
height_pt=float(data.get('height_pt', 841.89)),
|
|
items=items,
|
|
)
|
|
|
|
|
|
class IDExportItemFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict):
|
|
item_type = data.get('type', '')
|
|
if item_type == 'text_frame':
|
|
return IDExportTextFrameFactory.from_dict(data)
|
|
if item_type == 'image_frame':
|
|
return IDExportImageFrameFactory.from_dict(data)
|
|
if item_type == 'table':
|
|
return IDExportTableFactory.from_dict(data)
|
|
if item_type == 'page_number':
|
|
return IDExportPageNumberFactory.from_dict(data)
|
|
if item_type == 'shape':
|
|
return IDExportShapeFactory.from_dict(data)
|
|
# frame_group, column_break, and unknown types not converted
|
|
return None
|
|
|
|
|
|
class IDExportShapeFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportShape:
|
|
return IDExportShape(
|
|
id=str(data.get('id', '')),
|
|
x_pt=float(data.get('x_pt', 0)),
|
|
y_pt=float(data.get('y_pt', 0)),
|
|
width_pt=float(data.get('width_pt', 0)),
|
|
height_pt=float(data.get('height_pt', 0)),
|
|
shape_type=data.get('shape_type', 'rect'),
|
|
fill_hex=data.get('fill_hex'),
|
|
stroke_hex=data.get('stroke_hex'),
|
|
stroke_weight_pt=float(data.get('stroke_weight_pt', 0)),
|
|
)
|
|
|
|
|
|
class IDExportTextFrameFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportTextFrame:
|
|
paragraphs = [
|
|
IDExportParagraphFactory.from_dict(p)
|
|
for p in data.get('paragraphs', [])
|
|
]
|
|
return IDExportTextFrame(
|
|
id=str(data.get('id', '')),
|
|
thread_id=str(data.get('thread_id', '')),
|
|
thread_position=int(data.get('thread_position', 1)),
|
|
x_pt=float(data.get('x_pt', 0)),
|
|
y_pt=float(data.get('y_pt', 0)),
|
|
width_pt=float(data.get('width_pt', 0)),
|
|
height_pt=float(data.get('height_pt', 0)),
|
|
column_count=int(data.get('column_count', 1)),
|
|
paragraphs=paragraphs,
|
|
)
|
|
|
|
|
|
class IDExportParagraphFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportParagraph:
|
|
runs = [
|
|
IDExportRunFactory.from_dict(r)
|
|
for r in data.get('runs', [])
|
|
]
|
|
return IDExportParagraph(
|
|
style=data.get('style', ''),
|
|
text=data.get('text', ''),
|
|
runs=runs,
|
|
)
|
|
|
|
|
|
class IDExportRunFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportRun:
|
|
return IDExportRun(
|
|
text=data.get('text', ''),
|
|
style=data.get('style'),
|
|
bold=bool(data.get('bold', False)),
|
|
italic=bool(data.get('italic', False)),
|
|
color_hex=data.get('color_hex'),
|
|
font=data.get('font'),
|
|
size_pt=_optional_float(data.get('size_pt')),
|
|
)
|
|
|
|
|
|
class IDExportImageFrameFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportImageFrame:
|
|
return IDExportImageFrame(
|
|
id=str(data.get('id', '')),
|
|
x_pt=float(data.get('x_pt', 0)),
|
|
y_pt=float(data.get('y_pt', 0)),
|
|
width_pt=float(data.get('width_pt', 0)),
|
|
height_pt=float(data.get('height_pt', 0)),
|
|
image_name=data.get('image_name', 'image'),
|
|
image_data_b64=data.get('image_data_b64'),
|
|
fit_mode=data.get('fit_mode', 'fill_proportionally'),
|
|
)
|
|
|
|
|
|
class IDExportTableFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportTable:
|
|
rows = [
|
|
IDExportTableRowFactory.from_dict(r)
|
|
for r in data.get('rows', [])
|
|
]
|
|
return IDExportTable(
|
|
id=str(data.get('id', '')),
|
|
x_pt=float(data.get('x_pt', 0)),
|
|
y_pt=float(data.get('y_pt', 0)),
|
|
width_pt=float(data.get('width_pt', 0)),
|
|
column_widths_pt=[float(w) for w in data.get('column_widths_pt', [])],
|
|
rows=rows,
|
|
)
|
|
|
|
|
|
class IDExportTableRowFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportTableRow:
|
|
cells = [
|
|
IDExportTableCellFactory.from_dict(c)
|
|
for c in data.get('cells', [])
|
|
]
|
|
return IDExportTableRow(
|
|
is_header=bool(data.get('is_header', False)),
|
|
cells=cells,
|
|
)
|
|
|
|
|
|
class IDExportTableCellFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportTableCell:
|
|
return IDExportTableCell(
|
|
text=data.get('text', ''),
|
|
style=data.get('style'),
|
|
col_span=int(data.get('col_span', 1)),
|
|
row_span=int(data.get('row_span', 1)),
|
|
background_hex=data.get('background_hex'),
|
|
text_color_hex=data.get('text_color_hex'),
|
|
)
|
|
|
|
|
|
class IDExportPageNumberFactory:
|
|
@staticmethod
|
|
def from_dict(data: dict) -> IDExportPageNumber:
|
|
return IDExportPageNumber(
|
|
id=str(data.get('id', '')),
|
|
x_pt=float(data.get('x_pt', 0)),
|
|
y_pt=float(data.get('y_pt', 0)),
|
|
font=data.get('font'),
|
|
size_pt=float(data.get('size_pt', 9)),
|
|
color_hex=data.get('color_hex', '000000') or '000000',
|
|
alignment=data.get('alignment', 'center'),
|
|
)
|
|
|
|
|
|
def _optional_float(value) -> Optional[float]:
|
|
if value is None:
|
|
return None
|
|
try:
|
|
return float(value)
|
|
except (TypeError, ValueError):
|
|
return None
|