wire.escape
import wire
wireexposes this aswire.escape, soimport wireis enough and the names are called aswire.escape.*.import wire.escapereaches the same definitions directly.
Turning a value into something safe to write at a particular place in a page.
Escaping HTML is not one operation, it is five. The same string that is
harmless between two tags will end a <script> early, or turn an href
into a code execution, or break out of a stylesheet. Wire knows which of
those places every interpolation sits in, because it compiles a real
parsed tree rather than substituting into text, so it applies the
escaping that place actually needs instead of one approximation
everywhere.
Nothing here is optional or discoverable at render time. A template that
wants unescaped output has to say so with the raw filter, or hand Wire
a Safe value.
Constants
CONTEXT_TEXT
wire.escape.CONTEXT_TEXT = 'text'
Text between tags.
CONTEXT_ATTRIBUTE
wire.escape.CONTEXT_ATTRIBUTE = 'attribute'
An ordinary attribute value.
CONTEXT_URL
wire.escape.CONTEXT_URL = 'url'
An attribute the browser resolves as a URL.
CONTEXT_SCRIPT
wire.escape.CONTEXT_SCRIPT = 'script'
A place the browser reads as JavaScript: the body of a <script>, or
the value of an on* handler attribute.
CONTEXT_STYLE
wire.escape.CONTEXT_STYLE = 'style'
The body of a <style> element.
URL_ATTRIBUTES
wire.escape.URL_ATTRIBUTES = [...]
The attributes whose value a browser resolves as a URL, and which therefore have to be checked for a dangerous scheme rather than merely escaped.
srcset and ping hold several URLs separated by commas or spaces and
are checked entry by entry.
URL_LIST_ATTRIBUTES
wire.escape.URL_LIST_ATTRIBUTES = [...]
URL attributes holding a list of URLs rather than a single one.
DEFAULT_URL_SCHEMES
wire.escape.DEFAULT_URL_SCHEMES = [...]
The URL schemes Wire lets through by default.
A URL with no scheme at all is always allowed, which covers every
relative link, every absolute path and every protocol-relative URL. A
scheme outside this list is replaced with about:blank, because
javascript: and vbscript: in an href are script execution dressed
as a link, and a data: document inherits the origin of the page that
opened it.
Wire.set_url_schemes() replaces this list when an application
genuinely needs another one, app: or mailto+-style custom handlers
being the usual reason.
BLOCKED_URL
wire.escape.BLOCKED_URL = 'about:blank'
What a blocked URL is replaced with. A blocked link stays a link so the page does not fall apart, but it goes nowhere.
STYLE_SAFE
wire.escape.STYLE_SAFE = '/[^-a-zA-Z0-9 \t\n\r#%.,()_\/:;+*!@]/'
The characters a value may contain inside a <style> body.
Everything else is dropped rather than escaped, because a stylesheet has
no escape syntax that would make a < harmless: the tokenizer that
finds </style> runs before CSS is ever parsed.
Functions
escape()
wire.escape.escape(value, context: string, schemes: ?list) -> string
Escapes value for the given context.
A Safe value is written out unchanged in every context. That is the
whole point of it, and it is why raw must only ever be applied to
markup you built yourself.
schemes is the URL scheme allowlist, and is only consulted for
CONTEXT_URL. Passing nil uses DEFAULT_URL_SCHEMES.
Parameters
value(any)context(string) — One of theCONTEXT_*constants.schemes(?list)
Returns string
text()
wire.escape.text(value) -> string
Escapes value for text between tags, turning &, < and > into
character references.
Parameters
value(any)
Returns string
attribute()
wire.escape.attribute(value) -> string
Escapes value for a double quoted attribute value, turning & and "
into character references.
A < needs no escaping inside an attribute and is left alone, which is
what the HTML serialization algorithm does too.
Parameters
value(any)
Returns string
script()
wire.escape.script(value) -> string
Escapes value for a place the browser reads as JavaScript, by encoding it as JSON and then hiding the characters that would end the surrounding element or start a comment.
The result carries its own quotes when the value is a string, so an interpolation in a script must not be quoted by hand:
<script>
var user = {{ name }}; // right: renders as "Ada"
var user = '{{ name }}'; // wrong: renders as '"Ada"'
</script>
U+2028 and U+2029 are escaped as well. They are legal inside a JSON
string but end a line in JavaScript, and an unescaped one turns a valid
script into a syntax error.
Parameters
value(any)
Returns string
style()
wire.escape.style(value) -> string
Escapes value for the body of a <style> element by dropping every
character outside a conservative CSS-safe set.
Dropping rather than escaping is deliberate. There is no escape sequence
that stops a < inside a stylesheet from being found by the HTML
tokenizer looking for </style>, so the only safe answer is for the
character not to be there.
Parameters
value(any)
Returns string
url()
wire.escape.url(value, schemes: ?list) -> string
Escapes value for an attribute the browser resolves as a URL,
replacing it with about:blank when its scheme is not in schemes.
The scheme is read the way a browser reads it: leading and embedded
whitespace and control characters are ignored, and the comparison folds
case, so Java\tscript:alert(1) is caught along with the plain
spelling.
Parameters
value(any)schemes(?list) — The allowlist.nilmeansDEFAULT_URL_SCHEMES.
Returns string
url_list()
wire.escape.url_list(value, schemes: ?list, descriptors: bool) -> string
Escapes value for an attribute holding several URLs, checking each entry’s scheme on its own.
The two attributes that hold a list spell it differently. ping is
whitespace separated and every token in it is a URL. srcset is comma
separated and only the first token of each entry is a URL; what follows
is a descriptor such as 2x or 640w and is left alone. descriptors
picks between them.
Every separator is preserved exactly as it was written, since a srcset
whose spaces went missing is no longer a srcset.
Parameters
value(any)schemes(?list)descriptors(bool) — True forsrcset, false forping.
Returns string
is_url_attribute()
wire.escape.is_url_attribute(name: string) -> bool
Whether name is an attribute the browser resolves as a single URL.
Parameters
name(string)
Returns bool
is_url_list_attribute()
wire.escape.is_url_list_attribute(name: string) -> bool
Whether name is an attribute holding a list of URLs.
Parameters
name(string)
Returns bool
uses_descriptors()
wire.escape.uses_descriptors(name: string) -> bool
Whether a URL list attribute allows a descriptor after each URL, which
srcset does and ping does not.
Parameters
name(string)
Returns bool
is_script_attribute()
wire.escape.is_script_attribute(name: string) -> bool
Whether name is an event handler attribute, whose value a browser reads as JavaScript.
Every one of them starts with on, and treating the whole prefix as
script rather than keeping a list means a handler HTML gains next year
is covered the day it ships.
Parameters
name(string)
Returns bool
attribute_context()
wire.escape.attribute_context(name: string) -> string
The escaping context an attribute named name calls for.
Parameters
name(string)
Returns string
text_context()
wire.escape.text_context(tag: string) -> string
The escaping context text inside an element named tag calls for.
Parameters
tag(string)
Returns string
2026, Richard Ore and The Zuri Contributors