GameServer.Content (game_server_core v1.0.941)

Copy Markdown

Reads and renders Markdown content from project files and directories.

Lookup is path-based rather than theme-config driven. Hosts register named content sources, and this module resolves whichever configured files or directories exist for those sources.

All content is cached in :persistent_term after the first read. Call reload/0 to invalidate everything (e.g. after a config change).

Summary

Functions

Returns the absolute path for an asset relative to a registered content source. Returns nil when not found or path traversal is attempted.

Returns {prev_post, next_post} neighbours for the given slug (newest-first order). Either may be nil.

Renders a blog post's markdown to HTML, or nil.

Groups blog posts by {year, month} (newest first). Returns a list of {year, [{month, [posts]}]}.

Returns the rendered changelog HTML, or nil when the changelog path is not configured or the file doesn't exist.

Returns a single blog post map by slug, or nil.

Lists all blog posts sorted newest-first.

Returns the resolved absolute path for a registered content source, or nil.

Registers a named content source.

Clears all cached content so the next call re-reads from disk.

Returns the rendered roadmap HTML, or nil when the roadmap path is not configured or the file doesn't exist.

Functions

asset_path(name, relative)

@spec asset_path(atom() | String.t(), String.t()) :: String.t() | nil

Returns the absolute path for an asset relative to a registered content source. Returns nil when not found or path traversal is attempted.

blog_neighbours(slug)

@spec blog_neighbours(String.t()) :: {map() | nil, map() | nil}

Returns {prev_post, next_post} neighbours for the given slug (newest-first order). Either may be nil.

blog_post_html(slug)

@spec blog_post_html(String.t()) :: String.t() | nil

Renders a blog post's markdown to HTML, or nil.

blog_posts_grouped()

@spec blog_posts_grouped() :: [{integer(), [{integer(), [map()]}]}]

Groups blog posts by {year, month} (newest first). Returns a list of {year, [{month, [posts]}]}.

changelog_html()

@spec changelog_html() :: String.t() | nil

Returns the rendered changelog HTML, or nil when the changelog path is not configured or the file doesn't exist.

get_blog_post(slug)

@spec get_blog_post(String.t()) :: map() | nil

Returns a single blog post map by slug, or nil.

list_blog_posts()

@spec list_blog_posts() :: [map()]

Lists all blog posts sorted newest-first.

Each post is a map with keys:

  • :slug – URL-safe identifier derived from the filename
  • :title – extracted from the first # heading (or humanised slug)
  • :dateDate.t() parsed from filename prefix or file mtime
  • :path – absolute path to the .md file
  • :excerpt – first non-heading paragraph (≤ 200 chars)

path(name)

@spec path(atom() | String.t()) :: String.t() | nil

Returns the resolved absolute path for a registered content source, or nil.

register_path(name, opts)

@spec register_path(
  atom() | String.t(),
  keyword()
) :: :ok

Registers a named content source.

Supported options:

  • :kind - :file or :dir
  • :path - single candidate path
  • :candidates - ordered candidate paths
  • :asset_root - :self or :dirname when serving assets

reload()

@spec reload() :: :ok

Clears all cached content so the next call re-reads from disk.

roadmap_html()

@spec roadmap_html() :: String.t() | nil

Returns the rendered roadmap HTML, or nil when the roadmap path is not configured or the file doesn't exist.