From 943259a9990c49589ac001bf2699ea922315b5f3 Mon Sep 17 00:00:00 2001 From: Vasily Negrebetskiy Date: Tue, 9 Apr 2024 19:26:35 +0400 Subject: [PATCH] Font size choice --- muckraker/main.py | 5 +- muckraker/models.py | 18 ++++++-- muckraker/render.py | 56 +++++++++++++++-------- muckraker/static/style.css | 41 ++++++----------- muckraker/static/templates/newspaper.html | 30 ++++++------ static/index.html | 18 ++++---- static/main.js | 52 +++++++++++++-------- tests/conftest.py | 11 +++-- tests/test_api.py | 7 +-- 9 files changed, 133 insertions(+), 105 deletions(-) diff --git a/muckraker/main.py b/muckraker/main.py index 2921c07..ba043d0 100644 --- a/muckraker/main.py +++ b/muckraker/main.py @@ -106,9 +106,10 @@ async def get_s_issue(dir_path: Path = Depends(get_dir_path)): # Render PDF and write it to buffer pdf_path = dir_path / "out.pdf" render_issue( - config=issue_dict["config"], - heading=issue_dict["heading"], + page=issue_dict["page"], + header=issue_dict["header"], body=issue_dict["body"], + fonts=issue_dict["fonts"], output=pdf_path, image_dir=dir_path ) diff --git a/muckraker/models.py b/muckraker/models.py index 6c55311..fe36440 100644 --- a/muckraker/models.py +++ b/muckraker/models.py @@ -7,7 +7,7 @@ MAX_STR_LEN = 50 -class IssueHeading(BaseModel): +class IssueHeader(BaseModel): title: str = Field(max_length=MAX_STR_LEN) subtitle: Optional[str] = Field(default=None, max_length=MAX_STR_LEN) no: Optional[str] = Field(default=None, max_length=MAX_STR_LEN) @@ -15,7 +15,16 @@ class IssueHeading(BaseModel): cost: Optional[str] = Field(default=None, max_length=MAX_STR_LEN) -class IssueConfig(BaseModel): +class IssueFonts(BaseModel): + header_title_pt: Optional[int] = 38 + header_subtitle_pt: Optional[int] = 14 + header_details_pt: Optional[int] = 10 + main_title_pt: Optional[int] = 16 + main_subtitle_pt: Optional[int] = 14 + main_text_pt: Optional[int] = 10 + + +class IssuePage(BaseModel): bg: Optional[Literal["none", "bashcorpo_v5", "bashcorpo_v5_pale"]] = None size: Optional[Literal["a4", "a5", "demitab"]] = "a4" @@ -28,9 +37,10 @@ def set_to_none(cls, value): class Issue(BaseModel): - config: IssueConfig - heading: IssueHeading + page: IssuePage + header: IssueHeader body: str = Field(max_length=MAX_BODY_LEN) + fonts: Optional[IssueFonts] = IssueFonts() @model_validator(mode='before') @classmethod diff --git a/muckraker/render.py b/muckraker/render.py index 698e122..aa0919a 100644 --- a/muckraker/render.py +++ b/muckraker/render.py @@ -14,10 +14,17 @@ TAGS = set() +def font_size_css(selector: str, size_pt: int | None): + if size_pt is None: + return "" + return f"{selector} {{ font-size: {size_pt}pt !important; }}\n" + + def render_issue( - config: dict, - heading: dict, + page: dict, + header: dict, body: str, + fonts: dict, output: str, image_dir: str = "" ) -> None: @@ -31,32 +38,42 @@ def render_issue( ]) body = md.convert(body) - # Sanitize all str heading fields - for key, value in heading.items(): + # Sanitize all str header fields + for key, value in header.items(): if isinstance(value, str): - heading.update({key: nh3.clean(value, tags=TAGS)}) + header.update({key: nh3.clean(value, tags=TAGS)}) # Select background - if config.get("bg") is not None: - bg_path = STATIC / "bg" / (config["bg"] + ".jpg") + if page.get("bg") is not None: + bg_path = STATIC / "bg" / (page["bg"] + ".jpg") bg_file_str = "file://" + str(bg_path.resolve()) - config.update({"bg": bg_file_str}) + page.update({"bg": bg_file_str}) # Render HTML issue_template = jinja_env.get_template("newspaper.html") html = issue_template.render( - config=config, - heading=heading, + page=page, + header=header, body=body, static="file://" + str(STATIC.resolve()) ) - # Render PDF + # Configure fonts font_config = FontConfiguration() + fonts_css = "" + fonts_css += font_size_css("header h1", fonts.get("header_title_pt")) + fonts_css += font_size_css("header h2", fonts.get("header_subtitle_pt")) + fonts_css += font_size_css(".details", fonts.get("header_details_pt")) + fonts_css += font_size_css("main h1", fonts.get("main_title_pt")) + fonts_css += font_size_css("main h2", fonts.get("main_subtitle_pt")) + fonts_css += font_size_css("main p", fonts.get("main_text_pt")) + fonts_css = CSS(string=fonts_css, font_config=font_config) + + # Render PDF css = CSS(STATIC / "style.css", font_config=font_config) HTML(string=html).write_pdf( output, - stylesheets=[css], + stylesheets=[css, fonts_css], font_config=font_config ) @@ -65,18 +82,17 @@ def render_issue( import json import sys - # Load issue configuration + # Load issue config with open(sys.argv[1], "r") as fd: config = json.load(fd) - - # Load issue heading - with open(sys.argv[2], "r") as fd: - heading = json.load(fd) + page = config.get("page") + header = config.get("header") + fonts = config.get("fonts") # Load issue body - with open(sys.argv[3], "r") as fd: + with open(sys.argv[2], "r") as fd: body = fd.read() # Create PDF - output = sys.argv[4] - render_issue(config, heading, body, output, image_dir=".") + output = sys.argv[3] + render_issue(page, header, body, fonts, output, image_dir=".") diff --git a/muckraker/static/style.css b/muckraker/static/style.css index cd98589..8e47793 100644 --- a/muckraker/static/style.css +++ b/muckraker/static/style.css @@ -73,18 +73,15 @@ header h1, h2 { text-align: center; margin: 4mm; } - header h1 { string-set: title content(); font-family: KJV1611; font-size: 38pt; } - header h2 { font-size: 14pt; } - -header .issue-info { +header .details { column-count: 3; font-weight: bold; padding: 0; @@ -92,71 +89,59 @@ header .issue-info { border-bottom: 0.2mm solid black; margin: 2mm 0; } - -header .issue-info .issue-no { +header .details .issue-no { text-align: left; margin: 1mm; } - -header .issue-info .issue-date { +header .details .issue-date { text-align: center; margin: 1mm; } - -header .issue-info .issue-cost { +header .details .issue-cost { text-align: right; margin: 1mm; } -.columns { - column-count: 2; - column-rule: 0.2mm solid black; -} - -.columns h1, h2 { +main h1, h2 { text-align: center; margin: 2mm; page-break-after: avoid; } - -.columns h1 { - font-size: 16pt; -} - -.columns h2 { +main h2 { font-size: 14pt; } +main p{ + font-size: 10pt; +} +.columns { + column-count: 2; + column-rule: 0.2mm solid black; +} .columns img { width: 80%; margin: 0 auto; display: block; } - .columns p { margin: 2mm; text-indent: 2mm; line-height: 100%; } - .columns table { margin: 0 auto; border-spacing: 0; } - .columns table th { border-bottom: 0.2mm solid black; } - .columns table td, th { padding-left: 2mm; padding-right: 2mm; } - .columns table td:first-child, th:first-child { padding-left: 0; } - .columns table td:last-child, th:last-child { padding-right: 0; } diff --git a/muckraker/static/templates/newspaper.html b/muckraker/static/templates/newspaper.html index 7759313..e99bd64 100644 --- a/muckraker/static/templates/newspaper.html +++ b/muckraker/static/templates/newspaper.html @@ -6,19 +6,19 @@