Capy-Bearer Documentation

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()
{
	var value := "<Ada>"
	print(<><p title="<?= value ?>"><?= value ?></p></>, "\n")
}

Output

<p title="&lt;Ada&gt;">&lt;Ada&gt;</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()
{
	var name := string(request.query.name, fallback: "guest")
	print(<>
        <script>const name = <?= name ?>;</script>
        <style>.name::before { content: <?= name ?>; }</style>
    </>)
}

Output


        <script>const name = "guest";</script>
        <style>.name::before { content: "guest"; }</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.

An any uses its string conversion before escaping. The earlier string() call supplies a fallback for a missing query value.

String literals

String literals use double quotes:

function RENDER()
{
	var message := "Hello"
	var line := "first\nsecond"
	print(message, " ", line, "\n")
}

Output

Hello first
second

The supported escapes include \n, \r, \t, \", and \\. String positions and lengths count bytes, not Unicode characters.

Use + to join strings:

function RENDER()
{
	var name := "Ada"
	var greeting := "Hello, " + name
	print(greeting, "\n")
}

Output

Hello, Ada

Use a constructor to convert a scalar when a function does not already accept as string:

function RENDER()
{
	var label := "Count: " + string(3)
	print(label, "\n")
}

Output

Count: 3

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()
{
	var page := <><main><?= badge("Ready") ?></main></>
	print(page, "\n")
}

Output

<main>&lt;strong&gt;Ready&lt;/strong&gt;</main>

<?= 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()
{
	var inner := <><em><?= "<Ada>" ?></em></>
	print(<><p><?= inner ?></p></>, "\n")
}

Output

<p>&lt;em&gt;&amp;lt;Ada&amp;gt;&lt;/em&gt;</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()
{
	var fragment := "<strong>Ready</strong>"
	print(<><p><?: fragment ?></p></>, "\n")
}

Output

<p><strong>Ready</strong></p>

<?= value ?> converts an any to a string, then escapes it for its HTML context.

function RENDER()
{
	var value := any("<Ada>")
	print(<><p><?= value ?></p></>, "\n")
}

Output

<p>&lt;Ada&gt;</p>

Common string operations

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.