6. Strings and HTML
Use strings for text and HTML. A string literal and an HTML literal both yield a string value.
Escape dynamic text
<?= value ?> selects an encoding from its location. HTML text and quoted attributes escape &, <, >, quotes, and apostrophes.
function RENDER(request : dval) {
var value := "<Ada>"
print(<><p title="<?= value ?>"><?= value ?></p></>, "\n")
}
Output
<p title="<Ada>"><Ada></p>
Inside a script element, a string becomes one JavaScript literal. The encoder protects the closing tag and JavaScript line separators. Inside a style element, a string becomes one CSS literal. Integer and Boolean values remain scalar values. f64 interpolation is not supported in these elements.
function RENDER(request : dval) {
var name := string(request.query.name, {fallback: "guest"})
print(<>
<script>const name = <?= name ?>;</script>
<style>.name::before { content: <?= name ?>; }</style>
</>)
}
Script and style interpolation must start at a value boundary. Static source after it can apply an operator or a CSS unit. Do not put interpolation inside a string, template literal, or comment. Attribute values must use quotes. Tag and attribute names cannot contain interpolation.
URL, event-handler, and inline-style attributes use HTML attribute escaping. Validate these values for their application context before interpolation.
A dval cannot go directly in an HTML literal. Convert it to a string first. The name value in the previous example follows this rule.
String literals
String literals use double quotes:
function RENDER(request : dval) {
var message := "Hello"
var line := "first\nsecond"
print(message, " ", line, "\n")
}
The supported escapes include \n, \r, \t, \", and \\. String positions and lengths count bytes, not Unicode characters.
Use + to join strings:
function RENDER(request : dval) {
var name := "Ada"
var greeting := "Hello, " + name
print(greeting, "\n")
}
Use a constructor to convert a scalar when a function does not already accept as string:
function RENDER(request : dval) {
var label := "Count: " + string(3)
print(label, "\n")
}
HTML literals
An HTML literal starts with <> and ends with </>. It yields a string. Store it, pass it, return it, or print it like any other string.
function badge(label : string) string {
-> <><strong><?= label ?></strong></>
}
function RENDER(request : dval) {
var page := <><main><?= badge("Ready") ?></main></>
print(page, "\n")
}
<?= value ?> escapes output at the interpolation site. The interpolation form selects escaping. The value type does not.
When one HTML literal interpolates another with <?=, the outer literal escapes the inner string. This double escape is expected. Build one final string instead of nesting HTML fragments through escaped interpolation.
function RENDER(request : dval) {
var inner := <><em><?= "<Ada>" ?></em></>
print(<><p><?= inner ?></p></>, "\n")
}
Output
<p><em>&lt;Ada&gt;</em></p>
Use <?: value ?> only for source-controlled HTML text. Raw interpolation emits the string without escaping. It works only in HTML text. Do not use it for request data or other external input.
function RENDER(request : dval) {
var fragment := "<strong>Ready</strong>"
print(<><p><?: fragment ?></p></>, "\n")
}
Output
<p><strong>Ready</strong></p>
A dval cannot go directly in an HTML literal. Convert it with string() before <?= ?> escapes it.
function RENDER(request : dval) {
var value := dval("<Ada>")
print(<><p><?= string(value) ?></p></>, "\n")
}
Output
<p><Ada></p>
Common string operations
Use length, substr, find, contains, replace, lower, upper, split, and join for ordinary text work. Use html_escape when an API needs an HTML-escaped string.
Strings use automatic reference counting. Assignment and function calls preserve their lifetime. Most programs do not need to call clone.