struct Components::SafeHTML

Overview

SafeHTML is the output contract: a value that means "these bytes are already safe to write into an HTML response as markup." It is the type-level boundary Front A of the platform hardening proposal introduces (docs/SAFE_HTML_V1.md) — a plain String at a sink means text and gets escaped; a SafeHTML means markup and is trusted.

There is deliberately no public SafeHTML.new(String). initialize is protected, so the compiler-generated .new is protected too — nothing outside the Components namespace can mint a SafeHTML by construction. The only ways to get one are:

Defined in:

components/safe/safe_html.cr

Constant Summary

EMPTY = new("")

Constructors

Instance Method Summary

Constructor Detail

def self.escape(text : String) : SafeHTML #

Escapes plain text for the HTML text-node context and wraps the result as safe. The common, always-correct path for untrusted strings.


[View source]
def self.join(parts : Enumerable(SafeHTML)) : SafeHTML #

Concatenates already-safe fragments. No re-escaping happens — each fragment is trusted because it already carries the SafeHTML invariant.


[View source]
def self.join(*parts : SafeHTML) : SafeHTML #

[View source]
def self.unsafe(html : String, reason : String) : SafeHTML #

THE escape hatch. Loud and greppable by design: reason: is mandatory, not defaulted, so every call site documents why the string is trusted. Prefer .escape or the Elements/tag DSL over this.

This is also the mechanism Component#render uses internally to bridge un-migrated components (those that still implement the legacy render_content : String and have not overridden render_safe_content) — see docs/SAFE_HTML_V1.md "migration guide". Grep for reason: "legacy component to find every component still on the old path.


[View source]

Instance Method Detail

def +(other : SafeHTML) : SafeHTML #

Concatenation — both operands already carry the invariant, so the result does too.


[View source]
def ==(other : SafeHTML) : Bool #

[View source]
def ==(other : String) : Bool #

[View source]
def =~(other) : Int32 | Nil #
Description copied from class Object

Pattern match.

Overridden by descendants (notably Regex and String) to provide meaningful pattern-match semantics.


[View source]
def empty? : Bool #

[View source]
def ends_with?(suffix : String) : Bool #

[View source]
def hash(hasher) #
Description copied from struct Struct

See Object#hash(hasher)


[View source]
def includes?(needle : String) : Bool #

---- Minimal, read-only String-like surface ----------------------- Deliberately NOT the whole String API (that would re-blur the type boundary this struct exists to draw). Just enough for existing specs (rendered.should contain(...)) and common call sites to keep working without every caller having to say .to_s first.


[View source]
def inspect(io : IO) : Nil #
Description copied from struct Struct

Appends this struct's name and instance variables names and values to the given IO.

struct Point
  def initialize(@x : Int32, @y : Int32)
  end
end

p1 = Point.new 1, 2
p1.to_s    # "Point(@x=1, @y=2)"
p1.inspect # "Point(@x=1, @y=2)"

[View source]
def size : Int32 #

[View source]
def starts_with?(prefix : String) : Bool #

[View source]
def to_json(json : JSON::Builder) : Nil #

JSON embedding (e.g. reactive-component WebSocket/HTTP payloads): serialize as a plain JSON string of the safe HTML bytes.


[View source]
def to_raw_html : Elements::RawHTML #

Interop with the existing Elements children union — a SafeHTML is, by construction, exactly a vouched-safe RawHTML.


[View source]
def to_s(io : IO) : Nil #
Description copied from struct Struct

Same as #inspect(io).


[View source]
def to_s : String #
Description copied from class Object

Returns a nicely readable and concise string representation of this object, typically intended for users.

This method should usually not be overridden. It delegates to #to_s(IO) which can be overridden for custom implementations.

Also see #inspect.


[View source]