Module: Hecks::Forms::Escape
- Defined in:
- lib/hecks/forms/html.rb
Overview
Hand-rolled, on purpose — the repo has no ERB anywhere and no template
engine dependency (see docs/command-form-and-query-form-bluebook.md's survey). Every
other generator in this codebase (bin/reference's markdown, the IR's own
to_h) builds output as plain Ruby strings; this does the same for HTML,
with exactly one job: nothing that reaches Escape.html ever becomes a
tag. A feature developer's own domain data — a customer's name, an
account number a support rep typed into a form and got wrong — flows
through here on every render, so escaping is not optional decoration.
Class Method Summary collapse
-
.attr(value) ⇒ Object
Safe inside a double-quoted HTML attribute specifically —
htmlalready covers this (it escapes"), kept as a named alias so a call site reads "this value fills an attribute" rather than repeating the same escaping and leaving the reader to check they match. -
.html(value) ⇒ Object
Order matters —
&first, or every escape this method itself just wrote (&,<, ...) gets re-escaped a second time. -
.path(value) ⇒ Object
Same guard as
url, for a URL PATH segment instead of a query-string value. -
.url(value) ⇒ Object
L12 (docs/audits/2026-08-10-main-bug-audit.md) — safe as a query-string VALUE.
Class Method Details
.attr(value) ⇒ Object
Safe inside a double-quoted HTML attribute specifically — html
already covers this (it escapes "), kept as a named alias so a
call site reads "this value fills an attribute" rather than repeating
the same escaping and leaving the reader to check they match.
29 |
# File 'lib/hecks/forms/html.rb', line 29 def self.attr(value) = html(value) |
.html(value) ⇒ Object
Order matters — & first, or every escape this method itself just
wrote (&, <, ...) gets re-escaped a second time.
16 17 18 19 20 21 22 23 |
# File 'lib/hecks/forms/html.rb', line 16 def self.html(value) value.to_s .gsub("&", "&") .gsub("<", "<") .gsub(">", ">") .gsub('"', """) .gsub("'", "'") end |
.path(value) ⇒ Object
Same guard as url, for a URL PATH segment instead of a
query-string value. encode_www_form_component renders space as
+, which is only meaningful inside a query string — in a path
segment + is a literal plus, so an id like "John Smith" would
round-trip to "John+Smith" and 404 against the real id "John
Smith". Reuse the same percent-encoding and just correct that one
character back to %20.
58 |
# File 'lib/hecks/forms/html.rb', line 58 def self.path(value) = URI.encode_www_form_component(value.to_s).gsub("+", "%20") |
.url(value) ⇒ Object
L12 (docs/audits/2026-08-10-main-bug-audit.md) — safe as a
query-string VALUE. html/attr guard against the value becoming
markup, but say nothing about it staying inside the URL syntax
position it was placed in: an aggregate's identity is free-form
unless its value object declares a pattern: (see S3 in the same
audit), so &, +, ?, #, and / are all otherwise legal id
characters, and each would corrupt an href/Location built by naive
interpolation (a stray & smuggles a second query parameter, #
truncates the path at a fragment, / splits the path into an
extra segment, ...). Percent-encodes via
application/x-www-form-urlencoded (+ for space) — correct ONLY
for a query-string value (query_form_renderer.rb's quick_links,
record_renderer.rb's ?to=). For a URL PATH segment use path
below instead — + is a literal plus there, not an escaped space,
so this method would corrupt any id containing a space. Callers
still wrap the ASSEMBLED href/Location in attr (or html) as
usual — this only covers the id's own component, not the
surrounding markup.
49 |
# File 'lib/hecks/forms/html.rb', line 49 def self.url(value) = URI.encode_www_form_component(value.to_s) |