feat(elc, elb): RBrace stop fix, html_raw/escape runtime, c_source manifest directive #46

Merged
will.anderson merged 2 commits from fix/elc-parser-elb-build into dev 2026-05-08 16:43:12 +00:00
3 changed files with 10101 additions and 0 deletions
Showing only changes of commit a7e6fbf2d2 - Show all commits
+37
View File
@@ -2242,6 +2242,43 @@ el_val_t url_decode(el_val_t sv) {
return el_wrap_str(out);
}
/* ── html_raw ────────────────────────────────────────────────────────────────
* Identity passthrough for raw HTML template interpolation.
* El's {raw(expr)} compiles to html_raw(expr) the value is output as-is
* without any escaping. The caller is responsible for safety.
*/
el_val_t html_raw(el_val_t s) {
return s;
}
/* ── html_escape ─────────────────────────────────────────────────────────────
* Escape < > " ' & for safe HTML text interpolation.
* El's {expr} in HTML templates compiles to html_escape(expr).
*/
el_val_t html_escape(el_val_t sv) {
const char* src = EL_CSTR(sv);
if (!src) return EL_STR("");
size_t len = strlen(src);
/* Worst case: every byte → 6 chars (&quot;) */
char* out = (char*)malloc(len * 6 + 1);
if (!out) return sv;
el_arena_track(out);
char* p = out;
for (size_t i = 0; i < len; i++) {
unsigned char c = (unsigned char)src[i];
switch (c) {
case '&': memcpy(p, "&amp;", 5); p += 5; break;
case '<': memcpy(p, "&lt;", 4); p += 4; break;
case '>': memcpy(p, "&gt;", 4); p += 4; break;
case '"': memcpy(p, "&quot;", 6); p += 6; break;
case '\'': memcpy(p, "&#39;", 5); p += 5; break;
default: *p++ = (char)c; break;
}
}
*p = '\0';
return el_wrap_str(out);
}
/* ── HTML allowlist sanitizer ────────────────────────────────────────────────
* el_html_sanitize(input, allowlist_json)
*
+2
View File
@@ -227,6 +227,8 @@ el_val_t url_decode(el_val_t s); /* '+' → space, %XX → byte */
* {"p":[],"a":["href","title"],"strong":[],...}
* where each value is the array of attribute names allowed for that tag. */
el_val_t el_html_sanitize(el_val_t input_html, el_val_t allowlist_json);
el_val_t html_raw(el_val_t s);
el_val_t html_escape(el_val_t s);
/* ── Filesystem ──────────────────────────────────────────────────────────── */
+10062
View File
File diff suppressed because it is too large Load Diff