diff --git a/change/@microsoft-fast-build-96416f46-7e1a-4d19-ab7f-e5c83bc07aa6.json b/change/@microsoft-fast-build-96416f46-7e1a-4d19-ab7f-e5c83bc07aa6.json new file mode 100644 index 00000000000..13044ef5d4d --- /dev/null +++ b/change/@microsoft-fast-build-96416f46-7e1a-4d19-ab7f-e5c83bc07aa6.json @@ -0,0 +1,7 @@ +{ + "type": "minor", + "comment": "feat: auto-escape code samples inside `` elements during SSR — braces (`{`/`}`) everywhere and the angle brackets of FAST directive tags (``, ``) — so literal binding-like text and directive syntax render correctly while real HTML/custom elements inside `` remain live DOM elements. Also exposes a new `escape_code_samples(html)` WASM export so build-time tooling can apply the same escape to author HTML that is injected into a rendered page outside the normal render pipeline.", + "packageName": "@microsoft/fast-build", + "email": "7559015+janechu@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/change/@microsoft-fast-element-e20e07d7-c8d3-4207-b936-127afe6fe744.json b/change/@microsoft-fast-element-e20e07d7-c8d3-4207-b936-127afe6fe744.json new file mode 100644 index 00000000000..f76530084fa --- /dev/null +++ b/change/@microsoft-fast-element-e20e07d7-c8d3-4207-b936-127afe6fe744.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "feat: auto-escape `{` and `}` inside `` elements so binding-like syntax in code samples renders as literal text (mirrors webui-press and the server-side `escape_code_sample_elements` pass in `@microsoft/fast-build`, which additionally handles ``/`` directive tags)", + "packageName": "@microsoft/fast-element", + "email": "7559015+janechu@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/crates/microsoft-fast-build/DESIGN.md b/crates/microsoft-fast-build/DESIGN.md index cc18d314d15..b68e749815e 100644 --- a/crates/microsoft-fast-build/DESIGN.md +++ b/crates/microsoft-fast-build/DESIGN.md @@ -21,7 +21,7 @@ render_template(template, state_str) node::render_node(template, root, loop_vars, locator, hydration?) │ │ │ ├─ [hydration mode] scan HTML opening tags for attr bindings │ - │ └─ inject data-fe="N" attribute markers │ + │ └─ inject data-fe-c-{n}-{count} compact markers │ │ │ ├─ scan forward: next_directive() │ │ │ │ @@ -41,7 +41,7 @@ render_template(template, state_str) | Module | Role | |--------|------| | `lib.rs` | Public API surface — render functions, `pub use` re-exports, and config types | -| `renderer.rs` | Thin entry points converting the public API into `render_node` calls | +| `renderer.rs` | Thin entry points converting the public API into `render_node` calls. Preprocesses the top-level `template` string through `escape_code_sample_elements` so `{`/`}` characters (and the angle brackets of FAST directive tags such as `` / ``) inside any `` element are entity-escaped before binding/directive scanning | | `node.rs` | The main rendering loop — scans for directives, handles attribute bindings in hydration mode | | `directive.rs` | `Directive` enum, `next_directive` scanner, and all directive renderers | | `content.rs` | `{{expr}}` and `{{{expr}}}` binding renderers, `html_escape` | @@ -52,9 +52,10 @@ render_template(template, state_str) | `expression.rs` | Boolean expression evaluator for `` | | `hydration.rs` | `HydrationScope` — binding index tracking and named marker generation per template scope | | `json.rs` | Hand-rolled JSON parser producing `JsonValue` | -| `locator.rs` | `Locator` struct — maps element names to template strings; glob scanner; `` parser | +| `locator.rs` | `Locator` struct — maps element names to template strings; glob scanner; `` parser. Stored template bodies are first run through `escape_code_sample_elements` so `{`/`}` characters and the angle brackets of FAST directive tags (``, ``) inside `` elements are entity-escaped and therefore not interpreted as binding delimiters or directives. Also captures the inner `