///|
/// Values that can render themselves to HTML strings.
///
/// Generated template implementations use this trait so callers can render
/// pages with `page.render()`. The method allows `raise` because template code
/// can call ordinary MoonBit functions that use checked errors. User-defined
/// page structs normally receive their implementation from `template_codegen`.
pub(open) trait Render {
fn render(Self) -> String raise
}
///|
/// Error values reserved for render-time failures.
///
/// The current generator mostly reports parse and codegen problems before
/// rendering, but this error type gives runtime integrations a stable place for
/// checked failures such as invalid dynamic includes.
pub(all) suberror RenderError {
Message(String)
InvalidInclude(String)
} derive(Eq, Debug)
///|
/// HTML that has already been validated by the caller.
///
/// `SafeHtml` is the trust boundary for raw output. Generated templates escape
/// ordinary values by default; wrapping a string in this type documents that the
/// caller intentionally wants the markup written without escaping.
pub struct SafeHtml {
value : String
}
///|
/// Wraps trusted HTML so it can be passed through raw template output.
///
/// Prefer constructing this value near the code that validates or produces the
/// markup, so the trust decision remains visible at the call site.
pub fn SafeHtml::new(value : String) -> SafeHtml {
{ value, }
}
///|
/// Returns the trusted HTML payload without escaping it.
///
/// This is useful when adapting `SafeHtml` to another renderer or writing tests
/// that need to inspect the exact trusted markup.
pub fn SafeHtml::to_string(self : SafeHtml) -> String {
self.value
}
///|
/// Creates a trusted HTML wrapper.
///
/// This convenience constructor is equivalent to `SafeHtml::new(value)` and is
/// exported for template-facing code that prefers function-style helpers.
pub fn safe_html(value : String) -> SafeHtml {
SafeHtml::new(value)
}
///|
/// Writes trusted HTML as-is when interpolated or rendered as a raw value.
pub impl Show for SafeHtml with fn output(self, logger) {
logger.write_string(self.value)
}
///|
/// Formats a value the same way MoonBit string interpolation does.
///
/// Generated templates call this for expression output before applying the
/// escaped or raw write path, so any type with a `Show` implementation can be
/// rendered consistently.
pub fn[T : Show] render_value(value : T) -> String {
"\{value}"
}
///|
/// Escapes the HTML-sensitive characters `&`, `<`, `>`, `"`, and `'`.
///
/// The returned string is safe to place in normal HTML text positions produced
/// by templates. Raw output must be requested explicitly through template syntax
/// or by rendering trusted `SafeHtml`.
pub fn escape_html(value : String) -> String {
let out = StringBuilder::new()
for ch in value {
match ch {
'&' => out.write_string("&")
'<' => out.write_string("<")
'>' => out.write_string(">")
'"' => out.write_string(""")
'\'' => out.write_string("'")
_ => out.write_char(ch)
}
}
out.to_string()
}
///|
/// Writes raw text into a template output buffer without escaping it.
///
/// Generated renderers use this path for trusted content and raw template
/// expressions. Prefer `write_escaped` for ordinary user-provided strings.
pub fn write_raw(out : StringBuilder, value : String) -> Unit {
out.write_string(value)
}
///|
/// Escapes text and writes it into a template output buffer.
///
/// This is the default output path for generated escaped expressions such as
/// `<%= value %>`.
pub fn write_escaped(out : StringBuilder, value : String) -> Unit {
out.write_string(escape_html(value))
}