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

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("<", "&lt;")
       .gsub(">", "&gt;")
       .gsub('"', "&quot;")
       .gsub("'", "&#39;")
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)