Skip to content

markers

markers

Marker building utilities.

markers.build_icon_marker

build_icon_marker(
    icon: str,
    css: dict[str, str],
    caption: str | None,
    caption_css: dict[str, str],
    caption_id: str | None = None,
) -> DivIcon

Build an icon-based DivIcon marker with optional caption.

Parameters:

  • icon (str) –

    Icon name or full CSS class string. Strings containing a space (e.g. "fa-solid fa-house") are used verbatim. Bare names starting with "fa-" get an "fa-solid" prefix; other bare names (e.g. "home") get a "glyphicon" prefix.

  • css (dict[str, str]) –

    CSS property overrides for the icon element.

  • caption (str | None) –

    Optional caption text below the icon.

  • caption_css (dict[str, str]) –

    CSS property overrides for the caption.

  • caption_id (str | None, default: None ) –

    Optional DOM id on the caption <div>, used by zoom-dependent visibility JS to target the caption independently of its marker.

Returns:

  • DivIcon
Source code in mapyta/markers.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
def build_icon_marker(
    icon: str,
    css: dict[str, str],
    caption: str | None,
    caption_css: dict[str, str],
    caption_id: str | None = None,
) -> folium.DivIcon:
    """Build an icon-based DivIcon marker with optional caption.

    Parameters
    ----------
    icon : str
        Icon name or full CSS class string.  Strings containing a space
        (e.g. ``"fa-solid fa-house"``) are used verbatim.  Bare names
        starting with ``"fa-"`` get an ``"fa-solid"`` prefix; other bare
        names (e.g. ``"home"``) get a ``"glyphicon"`` prefix.
    css : dict[str, str]
        CSS property overrides for the icon element.
    caption : str | None
        Optional caption text below the icon.
    caption_css : dict[str, str]
        CSS property overrides for the caption.
    caption_id : str | None
        Optional DOM ``id`` on the caption ``<div>``, used by zoom-dependent
        visibility JS to target the caption independently of its marker.

    Returns
    -------
    folium.DivIcon
    """
    merged = {**DEFAULT_ICON_CSS, **css}
    style_str = css_to_style(merged)
    # Full CSS class string (contains a space) → use as-is
    # Bare name starting with "fa-" → FontAwesome 6 (fa-solid prefix)
    # Other bare name → Glyphicon
    if " " in icon:
        icon_class = icon
    elif icon.startswith("fa-"):
        icon_class = f"fa-solid {icon}"
    else:
        icon_class = f"glyphicon glyphicon-{icon}"
    fs = px_to_int(merged.get("font-size", "20px"), 20)
    glyph_html = f'<i class="{icon_class}" style="{style_str};line-height:1;vertical-align:top;"></i>'
    caption_html = _absolute_caption_html(caption, caption_css, top_px=fs + 2, element_id=caption_id) if caption else ""
    w = fs
    h = fs
    html = _marker_wrapper_html(f"{glyph_html}{caption_html}", w, h)
    return folium.DivIcon(
        html=html,
        icon_size=(w, h),
        icon_anchor=(w // 2, h // 2),
    )

markers.build_text_marker

build_text_marker(
    text: str,
    css: dict[str, str],
    caption: str | None,
    caption_css: dict[str, str],
    caption_id: str | None = None,
) -> DivIcon

Build a text/emoji DivIcon marker with optional caption.

Parameters:

  • text (str) –

    The actual text/emoji to render.

  • css (dict[str, str]) –

    CSS property overrides for the text element.

  • caption (str | None) –

    Optional caption text below the text.

  • caption_css (dict[str, str]) –

    CSS property overrides for the caption.

  • caption_id (str | None, default: None ) –

    Optional DOM id on the caption <div>, used by zoom-dependent visibility JS to target the caption independently of its marker.

Returns:

  • DivIcon

    A DivIcon rendering the text and optional caption.

Source code in mapyta/markers.py
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
def build_text_marker(
    text: str,
    css: dict[str, str],
    caption: str | None,
    caption_css: dict[str, str],
    caption_id: str | None = None,
) -> folium.DivIcon:
    """Build a text/emoji DivIcon marker with optional caption.

    Parameters
    ----------
    text : str
        The actual text/emoji to render.
    css : dict[str, str]
        CSS property overrides for the text element.
    caption : str | None
        Optional caption text below the text.
    caption_css : dict[str, str]
        CSS property overrides for the caption.
    caption_id : str | None
        Optional DOM ``id`` on the caption ``<div>``, used by zoom-dependent
        visibility JS to target the caption independently of its marker.

    Returns
    -------
    folium.DivIcon
        A DivIcon rendering the text and optional caption.
    """
    merged = {**DEFAULT_TEXT_CSS, **css}
    style_str = css_to_style(merged) + ";text-align:center;line-height:1"
    fs = px_to_int(merged.get("font-size", "16px"), 16)
    glyph_html = f'<div style="{style_str}">{text}</div>'
    caption_html = _absolute_caption_html(caption, caption_css, top_px=fs + 2, element_id=caption_id) if caption else ""
    w = fs + 10
    h = fs + 10
    html = _marker_wrapper_html(f"{glyph_html}{caption_html}", w, h)
    return folium.DivIcon(
        html=html,
        icon_size=(w, h),
        icon_anchor=(w // 2, h // 2),
    )

markers.classify_marker

classify_marker(s: str) -> Literal['emoji', 'icon_class', 'icon_name']

Classify a marker string.

Returns:

  • emoji

    Non-ASCII content (emojis, unicode symbols) → render as text.

  • icon_class

    Full CSS class string containing a space (e.g. "fa fa-home") → use as-is.

  • icon_name

    Bare icon name (e.g. "home", "fa-arrow-right") → auto-prefix.

Source code in mapyta/markers.py
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
def classify_marker(s: str) -> Literal["emoji", "icon_class", "icon_name"]:
    """Classify a marker string.

    Returns
    -------
    "emoji"
        Non-ASCII content (emojis, unicode symbols) → render as text.
    "icon_class"
        Full CSS class string containing a space (e.g. ``"fa fa-home"``) → use as-is.
    "icon_name"
        Bare icon name (e.g. ``"home"``, ``"fa-arrow-right"``) → auto-prefix.
    """
    if not s or not all(c.isascii() for c in s):
        return "emoji"
    if " " in s:
        return "icon_class"
    return "icon_name"

markers.css_to_style

css_to_style(css: dict[str, str]) -> str

Convert a CSS property dict to an inline style string.

Source code in mapyta/markers.py
38
39
40
def css_to_style(css: dict[str, str]) -> str:
    """Convert a CSS property dict to an inline style string."""
    return ";".join(f"{k}:{v}" for k, v in css.items())

markers.px_to_int

px_to_int(value: str, default: int) -> int

Convert a CSS length string like "12px" or "12.5px" to an int.

Falls back to default for non-px units ("1em", "medium") and malformed values so icon size estimation never raises.

Source code in mapyta/markers.py
43
44
45
46
47
48
49
50
51
52
def px_to_int(value: str, default: int) -> int:
    """Convert a CSS length string like ``"12px"`` or ``"12.5px"`` to an int.

    Falls back to ``default`` for non-``px`` units (``"1em"``, ``"medium"``)
    and malformed values so icon size estimation never raises.
    """
    try:
        return int(float(value.strip().removesuffix("px")))
    except (ValueError, AttributeError):
        return default