struct
Components::SafeHTML
- Components::SafeHTML
- Struct
- Value
- Object
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:
SafeHTML.escape(text)— HTML-escapes text and wraps it (safe, always)SafeHTML.join(parts)— concatenates otherSafeHTMLvalues (safe, because every part already carries the invariant)- the
Elements/tag DSL (Components::Elements::*), which escapes text children and attribute values by construction and hands backSafeHTMLat theComponentboundary SafeHTML.unsafe(str, reason:)/ the top-levelraw(str, reason:)— the loud, greppable escape hatch.reason:is mandatory. Every call site is a visible admission "I built this HTML by hand and I am vouching for it" —grep -rn 'SafeHTML.unsafe\|raw(' src/finds every one, which is exactly what makes this auditable instead of a secondhtml_safe-style silent-trust label.
Defined in:
components/safe/safe_html.crConstant Summary
-
EMPTY =
new("")
Constructors
-
.escape(text : String) : SafeHTML
Escapes plain text for the HTML text-node context and wraps the result as safe.
-
.join(parts : Enumerable(SafeHTML)) : SafeHTML
Concatenates already-safe fragments.
- .join(*parts : SafeHTML) : SafeHTML
-
.unsafe(html : String, reason : String) : SafeHTML
THE escape hatch.
Instance Method Summary
-
#+(other : SafeHTML) : SafeHTML
Concatenation — both operands already carry the invariant, so the result does too.
- #==(other : SafeHTML) : Bool
- #==(other : String) : Bool
-
#=~(other) : Int32 | Nil
Pattern match.
- #empty? : Bool
- #ends_with?(suffix : String) : Bool
-
#hash(hasher)
See
Object#hash(hasher) -
#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).
-
#inspect(io : IO) : Nil
Appends this struct's name and instance variables names and values to the given IO.
- #size : Int32
- #starts_with?(prefix : String) : Bool
-
#to_json(json : JSON::Builder) : Nil
JSON embedding (e.g.
- #to_raw_html : Elements::RawHTML
-
#to_s(io : IO) : Nil
Same as
#inspect(io). -
#to_s : String
Returns a nicely readable and concise string representation of this object, typically intended for users.
Constructor Detail
Escapes plain text for the HTML text-node context and wraps the result as safe. The common, always-correct path for untrusted strings.
Concatenates already-safe fragments. No re-escaping happens — each
fragment is trusted because it already carries the SafeHTML invariant.
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.
Instance Method Detail
Concatenation — both operands already carry the invariant, so the result does too.
Pattern match.
Overridden by descendants (notably Regex and String) to provide meaningful
pattern-match semantics.
---- 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.
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)"
JSON embedding (e.g. reactive-component WebSocket/HTTP payloads): serialize as a plain JSON string of the safe HTML bytes.
Interop with the existing Elements children union — a SafeHTML is,
by construction, exactly a vouched-safe RawHTML.
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.