Context-Aware Escaping #

Sugar automatically applies the right escaping based on where your output appears.

Sugar analyzes output context at compile time and applies the appropriate escape routine. You write plain <?= $value ?> and get safe output by default.

<div data-user="<?= $name ?>">
<script>const user = <?= $userData ?>;</script>
<style>.user::before { content: '<?= $prefix ?>'; }</style>
<a href="/search?q=<?= $query ?>">Search</a>
<div data-user="<?= \Sugar\Escape\Escaper::attr($name) ?>">
<script>const user = <?= \Sugar\Escape\Escaper::js($userData) ?>;</script>
<style>.user::before { content: '<?= \Sugar\Escape\Escaper::css($prefix) ?>'; }</style>
<a href="/search?q=<?= \Sugar\Escape\Escaper::url($query) ?>">Search</a>

What Sugar Detects #

Escaping is context-aware, not string-aware. The same variable can be escaped differently depending on where it appears.

Context Example Escaper Notes
HTML text <p><?= $title ?></p> Escaper::html() Default for plain text nodes.
HTML attribute <div title="<?= $title ?>"> Escaper::attr() Protects quotes and attribute breaks.
URL <a href="/q?search=<?= $query ?>"> Escaper::url() Uses rawurlencode.
JavaScript <script>const u = <?= $data ?>;</script> Escaper::js() Uses JSON encoding with hex flags.
CSS <style>.x{content:'<?= $label ?>'}</style> Escaper::css() Escapes unsafe CSS chars.

Common Patterns #

<button data-id="<?= $id ?>">Open</button>
<input value="<?= $value ?>">
<a href="/search?q=<?= $query ?>">Search</a>
<script>
	const payload = <?= $payload ?>;
</script>
<style>
	.badge::before { content: '<?= $label ?>'; }
</style>

When to Override Escaping #

Only bypass escaping for trusted, pre-sanitized content. Never pass user input to raw output.

Raw Output (|> raw()) #

Use |> raw() for trusted HTML:

<div><?= $article->renderedBody |> raw() ?></div>

Only use raw output for trusted content. Never pass user input to |> raw().

JSON Output (|> json()) #

Use |> json() when you want JSON output with context-aware escaping. In HTML, it compiles to Escaper::json(). Inside attributes it compiles to Escaper::attrJson() so quotes stay safe.

<script>
	const payload = <?= $payload |> json() ?>;
</script>

<div x-data="{ data: <?= $payload |> json() ?> }"></div>

Use |> json() for arrays/objects. It keeps escaping enabled, unlike |> raw().

Need a reminder of the escape helpers?

  • Escaper::html() for text nodes
  • Escaper::attr() for attribute values
  • Escaper::url() for URL parts
  • Escaper::js() for JavaScript
  • Escaper::css() for CSS
  • Escaper::json() for JSON output