HTML rendering functions for Publishing.Web.Controller.
Summary
Functions
Pre-computes date counts for timestamp-mode posts to avoid per-post DB queries.
Builds a post URL based on mode. Omits the locale prefix when the site is effectively single-language. Can also omit the default-language prefix when that setting is enabled.
Builds a public path with explicit date and time (always includes time). Used when redirecting from date-only URLs to full timestamp URLs.
Builds language data for the publishing_language_switcher component on public pages. Converts the @translations assign to the format expected by the component.
Extracts and renders an excerpt from post content. Returns content before <!-- more --> tag, or first paragraph if no tag. Renders markdown and strips HTML tags for plain text display.
Resolves a featured image URL for a post, falling back to the original variant.
Formats a date for display using locale-aware month names.
Formats a date for URL.
Formats a date with time for display. Used when multiple posts exist on the same date.
Formats a post's publication date, including time only when multiple posts exist on the same date.
Formats time for URL (HH:MM).
Builds the public URL for a group listing page. Omits the locale prefix when the site is effectively single-language. Can also omit the default-language prefix when that setting is enabled.
Checks if a post has a publication date to display. For timestamp mode, the date comes from the DB fields. For slug mode, it comes from metadata.published_at.
Renders the OpenGraph + Twitter Card meta tags for a public page from the
:og map the controller builds.
Pluralizes a word based on count.
Renders a post's publication date (calendar icon + formatted date).
Resolves the exact language-switcher code to highlight on public pages.
Renders a slim heading-anchor rail on post pages: a fixed side rail with a
tick per <h2>/<h3>/<h4> in the article; hover reveals the heading text,
click smooth-scrolls to it, and the current section is highlighted as you
scroll. Built client-side (assigns heading ids in the browser, so the cached
render pipeline is untouched) as a real <nav> of links — keyboard and
screen-reader accessible. Hidden on narrow screens; honors reduced-motion.
Renders a thin reading-progress bar fixed to the top of the viewport that
fills as the reader scrolls the article. Decorative (aria-hidden), pointer
transparent, and honors prefers-reduced-motion.
Renders a date-timeline rail on the group listing: a fixed side rail with a
marker per distinct year found across the rendered post cards (which carry a
data-post-date); click a year to smooth-scroll to its first post, and the
current year highlights as you scroll. Only appears when 2+ years are present.
Built client-side as an accessible <nav> of links; hidden on narrow screens.
Emits a <style> that recolors the page's native scrollbar to the daisyUI
theme when the group opts into "branded"/"thin". "default" renders nothing
(the browser's native bar is untouched). Only recolors/resizes the real
scrollbar — scrolling stays native.
Functions
Pre-computes date counts for timestamp-mode posts to avoid per-post DB queries.
Returns a map of %{date_string => count} for use with build_post_url/4
and format_post_date/3.
Builds a post URL based on mode. Omits the locale prefix when the site is effectively single-language. Can also omit the default-language prefix when that setting is enabled.
For slug mode posts, uses the language-specific URL slug (from post.url_slug or post.language_slugs[language]) for SEO-friendly localized URLs.
For timestamp mode posts:
- If only one post exists on the date, uses date-only URL (e.g., /group/2025-12-09)
- If multiple posts exist on the date, includes time (e.g., /group/2025-12-09/16:26)
Builds a public path with explicit date and time (always includes time). Used when redirecting from date-only URLs to full timestamp URLs.
Builds language data for the publishing_language_switcher component on public pages. Converts the @translations assign to the format expected by the component.
Extracts and renders an excerpt from post content. Returns content before <!-- more --> tag, or first paragraph if no tag. Renders markdown and strips HTML tags for plain text display.
Resolves a featured image URL for a post, falling back to the original variant.
Formats a date for display using locale-aware month names.
Formats a date for URL.
Formats a date with time for display. Used when multiple posts exist on the same date.
Formats a post's publication date, including time only when multiple posts exist on the same date.
Formats time for URL (HH:MM).
Builds the public URL for a group listing page. Omits the locale prefix when the site is effectively single-language. Can also omit the default-language prefix when that setting is enabled.
Checks if a post has a publication date to display. For timestamp mode, the date comes from the DB fields. For slug mode, it comes from metadata.published_at.
Renders the OpenGraph + Twitter Card meta tags for a public page from the
:og map the controller builds.
These are emitted in-page (inside the rendered body) so a social preview
works out of the box even when the host's root layout doesn't render the
forwarded :og assign in <head> — most host apps ship their own root
layout. The same :og map is ALSO forwarded via module_assigns, so a host
that does render it in <head> gets the strictly-correct placement; such a
host disables the in-page copy via publishing_render_og_tags to avoid
duplicate tags. Renders nothing when :og is absent (e.g. the groups index).
Attributes
og(:map) - Defaults tonil.
Pluralizes a word based on count.
Renders a post's publication date (calendar icon + formatted date).
Attributes
post(:map) (required)group_slug(:string) (required)class(:any) - Defaults tonil.
Resolves the exact language-switcher code to highlight on public pages.
Renders a slim heading-anchor rail on post pages: a fixed side rail with a
tick per <h2>/<h3>/<h4> in the article; hover reveals the heading text,
click smooth-scrolls to it, and the current section is highlighted as you
scroll. Built client-side (assigns heading ids in the browser, so the cached
render pipeline is untouched) as a real <nav> of links — keyboard and
screen-reader accessible. Hidden on narrow screens; honors reduced-motion.
Attributes
enabled(:boolean) - Defaults tofalse.
Renders a thin reading-progress bar fixed to the top of the viewport that
fills as the reader scrolls the article. Decorative (aria-hidden), pointer
transparent, and honors prefers-reduced-motion.
Attributes
enabled(:boolean) - Defaults tofalse.
Renders a date-timeline rail on the group listing: a fixed side rail with a
marker per distinct year found across the rendered post cards (which carry a
data-post-date); click a year to smooth-scroll to its first post, and the
current year highlights as you scroll. Only appears when 2+ years are present.
Built client-side as an accessible <nav> of links; hidden on narrow screens.
Attributes
enabled(:boolean) - Defaults tofalse.granularity(:string) - Defaults to"auto".
Emits a <style> that recolors the page's native scrollbar to the daisyUI
theme when the group opts into "branded"/"thin". "default" renders nothing
(the browser's native bar is untouched). Only recolors/resizes the real
scrollbar — scrolling stays native.
Attributes
style(:string) - Defaults to"default".