~homeworkprod/byceps

ref: 4d64fc328a86338ae76b38da85d5ddb965a81c61 byceps/byceps/services/news/html_service.py -rw-r--r-- 2.0 KiB
4d64fc32 — Jochen Kupperschmidt Import `Markup` from `markupsafe`, not `jinja2` 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
"""
byceps.services.news.html_service
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Render HTML fragments from news items and images.

:Copyright: 2006-2021 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

from __future__ import annotations
from functools import partial
from typing import Optional

from flask_babel import gettext
from markupsafe import Markup

from ...util.iterables import find
from ...util.templating import load_template

from .transfer.models import ChannelID, Image


def render_body(
    raw_body: str, channel_id: ChannelID, images: list[Image]
) -> str:
    """Render item's raw body to HTML."""
    template = load_template(raw_body)
    render_image = partial(_render_image, channel_id, images)
    return template.render(render_image=render_image)


def _render_image(
    channel_id: ChannelID,
    images: list[Image],
    number: int,
    *,
    width: Optional[int] = None,
    height: Optional[int] = None,
) -> str:
    """Render HTML for image."""
    image = find(images, lambda image: image.number == number)

    if image is None:
        raise Exception(f'Unknown image number "{number}"')

    figure_attrs = ''
    img_attrs = ''
    figcaption_attrs = ''

    if image.alt_text:
        img_attrs += f' alt="{image.alt_text}"'

    if width:
        img_attrs += f' width="{width}"'
        figcaption_attrs += f' style="max-width: {width}px;"'
    if height:
        img_attrs += f' height="{height}"'

    caption_elem = _render_image_caption(image, figcaption_attrs)

    html = f"""\
<figure{figure_attrs}>
  <img src="{image.url_path}"{img_attrs}>
  {caption_elem}
</figure>"""

    return Markup(html)


def _render_image_caption(image: Image, attrs: str) -> str:
    caption = image.caption or ''

    if image.attribution:
        if caption:
            caption += ' '
        credit_label = gettext('Image credit')
        caption += f'<small>{credit_label}: {image.attribution}</small>'

    if not caption:
        return ''

    return f'<figcaption{attrs}>{caption}</figcaption>'