@barefootjs/rust 0.19.0 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/index.js +5 -4
- package/dist/adapter/minijinja-adapter.d.ts +8 -7
- package/dist/adapter/minijinja-adapter.d.ts.map +1 -1
- package/dist/build.js +5 -4
- package/dist/index.js +5 -4
- package/package.json +3 -3
- package/runtime/src/runtime.rs +87 -1
- package/src/__tests__/minijinja-adapter.test.ts +1 -13
- package/src/adapter/minijinja-adapter.ts +13 -26
package/dist/adapter/index.js
CHANGED
|
@@ -188924,10 +188924,11 @@ ${name}="{{ bf.string(${val}) }}"
|
|
|
188924
188924
|
if (e.kind === "expr" && !isSupported(parseExpression2(e.expr)).supported)
|
|
188925
188925
|
return null;
|
|
188926
188926
|
}
|
|
188927
|
-
|
|
188928
|
-
|
|
188929
|
-
|
|
188930
|
-
|
|
188927
|
+
const args = entries.flatMap((e) => [
|
|
188928
|
+
JSON.stringify(e.cssKey),
|
|
188929
|
+
e.kind === "literal" ? JSON.stringify(e.value) : this.convertExpressionToJinja(e.expr)
|
|
188930
|
+
]);
|
|
188931
|
+
return `{{ bf.style_object(${args.join(", ")}) }}`;
|
|
188931
188932
|
}
|
|
188932
188933
|
renderAttributes(element) {
|
|
188933
188934
|
const parts = [];
|
|
@@ -327,15 +327,16 @@ export declare class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitt
|
|
|
327
327
|
*/
|
|
328
328
|
private readonly elementAttrEmitter;
|
|
329
329
|
/**
|
|
330
|
-
* Lower a `style={{ … }}` object literal to a
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
330
|
+
* Lower a `style={{ … }}` object literal to a `bf.style_object(...)` call,
|
|
331
|
+
* e.g. `{ backgroundColor: color }` → `{{ bf.style_object("background-color",
|
|
332
|
+
* color) }}`. `style_object` is the single oracle-matching sanitizer (ported
|
|
333
|
+
* from Hono's `hasUnsafeStyleValue`): it drops any key:value pair whose
|
|
334
|
+
* value could break out of a CSS declaration and HTML-escapes the rest,
|
|
335
|
+
* returning a safe string so the custom minijinja formatter doesn't
|
|
336
|
+
* re-escape it (#2261). Returns null when the shape is unsupported or any
|
|
337
|
+
* value can't be lowered (caller falls through to BF101). (#1322)
|
|
335
338
|
*/
|
|
336
339
|
private tryLowerStyleObject;
|
|
337
|
-
/** HTML-attribute escape for static text inlined into a `"..."` attribute. */
|
|
338
|
-
private escapeAttrText;
|
|
339
340
|
private renderAttributes;
|
|
340
341
|
renderScopeMarker(_instanceIdExpr: string): string;
|
|
341
342
|
renderSlotMarker(slotId: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"minijinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/minijinja-adapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"minijinja-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/minijinja-adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
CHANGED
|
@@ -188924,10 +188924,11 @@ ${name}="{{ bf.string(${val}) }}"
|
|
|
188924
188924
|
if (e.kind === "expr" && !isSupported(parseExpression2(e.expr)).supported)
|
|
188925
188925
|
return null;
|
|
188926
188926
|
}
|
|
188927
|
-
|
|
188928
|
-
|
|
188929
|
-
|
|
188930
|
-
|
|
188927
|
+
const args = entries.flatMap((e) => [
|
|
188928
|
+
JSON.stringify(e.cssKey),
|
|
188929
|
+
e.kind === "literal" ? JSON.stringify(e.value) : this.convertExpressionToJinja(e.expr)
|
|
188930
|
+
]);
|
|
188931
|
+
return `{{ bf.style_object(${args.join(", ")}) }}`;
|
|
188931
188932
|
}
|
|
188932
188933
|
renderAttributes(element) {
|
|
188933
188934
|
const parts = [];
|
package/dist/index.js
CHANGED
|
@@ -188924,10 +188924,11 @@ ${name}="{{ bf.string(${val}) }}"
|
|
|
188924
188924
|
if (e.kind === "expr" && !isSupported(parseExpression2(e.expr)).supported)
|
|
188925
188925
|
return null;
|
|
188926
188926
|
}
|
|
188927
|
-
|
|
188928
|
-
|
|
188929
|
-
|
|
188930
|
-
|
|
188927
|
+
const args = entries.flatMap((e) => [
|
|
188928
|
+
JSON.stringify(e.cssKey),
|
|
188929
|
+
e.kind === "literal" ? JSON.stringify(e.value) : this.convertExpressionToJinja(e.expr)
|
|
188930
|
+
]);
|
|
188931
|
+
return `{{ bf.style_object(${args.join(", ")}) }}`;
|
|
188931
188932
|
}
|
|
188932
188933
|
renderAttributes(element) {
|
|
188933
188934
|
const parts = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/rust",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "minijinja (Rust) adapter for BarefootJS — compiles IR to .j2 templates and ships a Rust rendering runtime (packages/adapter-rust/runtime/); runs under any Rust web framework (axum, etc.)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -54,14 +54,14 @@
|
|
|
54
54
|
"directory": "packages/adapter-rust"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@barefootjs/shared": "0.19.
|
|
57
|
+
"@barefootjs/shared": "0.19.1"
|
|
58
58
|
},
|
|
59
59
|
"peerDependencies": {
|
|
60
60
|
"@barefootjs/jsx": ">=0.2.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
63
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
64
|
-
"@barefootjs/jsx": "0.19.
|
|
64
|
+
"@barefootjs/jsx": "0.19.1",
|
|
65
65
|
"typescript": "^5.0.0"
|
|
66
66
|
}
|
|
67
67
|
}
|
package/runtime/src/runtime.rs
CHANGED
|
@@ -158,6 +158,17 @@ fn char_len(s: &str) -> usize {
|
|
|
158
158
|
s.chars().count()
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
// JS `String.prototype.length` counts UTF-16 CODE UNITS, not Rust's
|
|
162
|
+
// codepoint-counting `chars().count()` (#2255, used by `char_len` above for
|
|
163
|
+
// the char-indexed slice/pad helpers). A codepoint outside the Basic
|
|
164
|
+
// Multilingual Plane (astral, U+10000-U+10FFFF — e.g. '👍') is a surrogate
|
|
165
|
+
// PAIR in UTF-16, so it counts as 2, not 1; '日本語' is 3 either way
|
|
166
|
+
// (BMP-only). Used only by `length` below — `char_len`'s callers need a
|
|
167
|
+
// codepoint OFFSET for slicing, not this count.
|
|
168
|
+
fn utf16_len(s: &str) -> usize {
|
|
169
|
+
s.chars().map(|c| if c as u32 > 0xFFFF { 2 } else { 1 }).sum()
|
|
170
|
+
}
|
|
171
|
+
|
|
161
172
|
fn char_slice_from(s: &str, n: usize) -> String {
|
|
162
173
|
s.chars().skip(n).collect()
|
|
163
174
|
}
|
|
@@ -296,6 +307,80 @@ fn style_to_css(v: &JsValue) -> Option<String> {
|
|
|
296
307
|
}
|
|
297
308
|
}
|
|
298
309
|
|
|
310
|
+
/// Structural scan for characters that could break a value out of a CSS
|
|
311
|
+
/// declaration -- ported byte-for-byte from Hono's own `hasUnsafeStyleValue`
|
|
312
|
+
/// (`hono/jsx/utils.ts`), the ORACLE this adapter's dynamic `style={{...}}`
|
|
313
|
+
/// values must match (#2261). NOT real CSSOM property validation. Every
|
|
314
|
+
/// character this scan tests is ASCII, so scanning by byte agrees with
|
|
315
|
+
/// Hono's UTF-16-code-unit scan for every input -- a multibyte UTF-8
|
|
316
|
+
/// sequence has no byte in the ASCII range, so it can never spuriously
|
|
317
|
+
/// match one of these single-byte comparisons.
|
|
318
|
+
fn has_unsafe_style_value(value: &str) -> bool {
|
|
319
|
+
let bytes = value.as_bytes();
|
|
320
|
+
let mut quote: u8 = 0;
|
|
321
|
+
let mut block_stack: Vec<u8> = Vec::new();
|
|
322
|
+
let mut i = 0usize;
|
|
323
|
+
while i < bytes.len() {
|
|
324
|
+
let c = bytes[i];
|
|
325
|
+
if c == b'\\' {
|
|
326
|
+
if i == bytes.len() - 1 {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
i += 1;
|
|
330
|
+
} else if quote != 0 {
|
|
331
|
+
if c == b'\n' || c == b'\x0c' || c == b'\r' {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
if c == quote {
|
|
335
|
+
quote = 0;
|
|
336
|
+
}
|
|
337
|
+
} else if c == b'/' && i + 1 < bytes.len() && bytes[i + 1] == b'*' {
|
|
338
|
+
match value[i + 2..].find("*/") {
|
|
339
|
+
Some(end) => i = i + 2 + end + 1,
|
|
340
|
+
None => return true,
|
|
341
|
+
}
|
|
342
|
+
} else if c == b'"' || c == b'\'' {
|
|
343
|
+
quote = c;
|
|
344
|
+
} else if c == b'(' {
|
|
345
|
+
block_stack.push(b')');
|
|
346
|
+
} else if c == b'[' {
|
|
347
|
+
block_stack.push(b']');
|
|
348
|
+
} else if c == b'{' || c == b'}' {
|
|
349
|
+
return true;
|
|
350
|
+
} else if c == b')' || c == b']' {
|
|
351
|
+
if block_stack.last() != Some(&c) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
block_stack.pop();
|
|
355
|
+
} else if c == b';' && block_stack.is_empty() {
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
i += 1;
|
|
359
|
+
}
|
|
360
|
+
quote != 0 || !block_stack.is_empty()
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/// Builds the CSS string for a `style={{...}}` JSX object-literal attribute
|
|
364
|
+
/// (#2261). `pairs` alternates CSS key (always compile-time-known), then
|
|
365
|
+
/// value. A value that fails `has_unsafe_style_value` (after JS-`String()`-
|
|
366
|
+
/// style stringification) is DROPPED -- the whole `key:value` pair is
|
|
367
|
+
/// omitted -- matching Hono's oracle exactly. The joined string is STILL
|
|
368
|
+
/// HTML-escaped (mirroring Hono's `escapeToBuffer`) since a structurally
|
|
369
|
+
/// "safe" value can still carry a literal `"`/`'`/`&`.
|
|
370
|
+
fn style_object(pairs: &[JsValue]) -> String {
|
|
371
|
+
let mut parts = Vec::new();
|
|
372
|
+
let mut i = 0;
|
|
373
|
+
while i + 1 < pairs.len() {
|
|
374
|
+
let key = js_string(&pairs[i]);
|
|
375
|
+
let value = js_string(&pairs[i + 1]);
|
|
376
|
+
if !has_unsafe_style_value(&value) {
|
|
377
|
+
parts.push(format!("{}:{}", escape_html_chars(&key), escape_html_chars(&value)));
|
|
378
|
+
}
|
|
379
|
+
i += 2;
|
|
380
|
+
}
|
|
381
|
+
parts.join(";")
|
|
382
|
+
}
|
|
383
|
+
|
|
299
384
|
fn is_on_handler_skip(key: &str) -> bool {
|
|
300
385
|
// Skip when key starts `on` and the third character is its own
|
|
301
386
|
// uppercase form (matches `runtime.py`'s exact predicate, which is
|
|
@@ -1194,6 +1279,7 @@ impl Object for BfInstance {
|
|
|
1194
1279
|
"uc" => Ok(MjValue::from(js_string(a(0)).to_uppercase())),
|
|
1195
1280
|
"join" => Ok(MjValue::from(join(a(0), a(1)))),
|
|
1196
1281
|
"length" => Ok(MjValue::from(length(a(0)))),
|
|
1282
|
+
"style_object" => Ok(safe(style_object(&js_args))),
|
|
1197
1283
|
"index_of" => Ok(MjValue::from(array_index_of(a(0), a(1), false))),
|
|
1198
1284
|
"last_index_of" => Ok(MjValue::from(array_index_of(a(0), a(1), true))),
|
|
1199
1285
|
"at" => Ok(js_to_mj(&at(a(0), a(1)))),
|
|
@@ -1353,7 +1439,7 @@ pub fn length(recv: &JsValue) -> f64 {
|
|
|
1353
1439
|
match recv {
|
|
1354
1440
|
JsValue::Array(a) => a.len() as f64,
|
|
1355
1441
|
JsValue::Object(_) => 0.0,
|
|
1356
|
-
other =>
|
|
1442
|
+
other => utf16_len(&js_string(other)) as f64,
|
|
1357
1443
|
}
|
|
1358
1444
|
}
|
|
1359
1445
|
|
|
@@ -56,19 +56,7 @@ runAdapterConformanceTests({
|
|
|
56
56
|
// Same `/* @client */` keyed-map elision (data-table).
|
|
57
57
|
'data-table',
|
|
58
58
|
]),
|
|
59
|
-
skipDataPoints: new Set<string>(
|
|
60
|
-
// #2255 — minijinja's length counts chars (codepoints); JS counts
|
|
61
|
-
// UTF-16 code units, so a surrogate-pair character is 2 in JS, 1 here.
|
|
62
|
-
'string-length-text:astral',
|
|
63
|
-
// #2260 — controlled boolean props: the SSR seed evaluates only the
|
|
64
|
-
// static fallback of `props.X ?? internal()` chains.
|
|
65
|
-
'toggle:gen:pressed:true',
|
|
66
|
-
'switch:gen:checked:true',
|
|
67
|
-
'checkbox:gen:checked:true',
|
|
68
|
-
// #2261 — invalid dynamic CSS value kept (escaped) where the oracle
|
|
69
|
-
// drops the property.
|
|
70
|
-
'style-object-dynamic:gen:color:markup',
|
|
71
|
-
]),
|
|
59
|
+
skipDataPoints: new Set<string>(),
|
|
72
60
|
onRenderError: (err, id) => {
|
|
73
61
|
if (err instanceof RustNotAvailableError) {
|
|
74
62
|
console.log(`Skipping [${id}]: ${err.message}`)
|
|
@@ -1453,11 +1453,14 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
|
|
|
1453
1453
|
}
|
|
1454
1454
|
|
|
1455
1455
|
/**
|
|
1456
|
-
* Lower a `style={{ … }}` object literal to a
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
1459
|
-
*
|
|
1460
|
-
*
|
|
1456
|
+
* Lower a `style={{ … }}` object literal to a `bf.style_object(...)` call,
|
|
1457
|
+
* e.g. `{ backgroundColor: color }` → `{{ bf.style_object("background-color",
|
|
1458
|
+
* color) }}`. `style_object` is the single oracle-matching sanitizer (ported
|
|
1459
|
+
* from Hono's `hasUnsafeStyleValue`): it drops any key:value pair whose
|
|
1460
|
+
* value could break out of a CSS declaration and HTML-escapes the rest,
|
|
1461
|
+
* returning a safe string so the custom minijinja formatter doesn't
|
|
1462
|
+
* re-escape it (#2261). Returns null when the shape is unsupported or any
|
|
1463
|
+
* value can't be lowered (caller falls through to BF101). (#1322)
|
|
1461
1464
|
*/
|
|
1462
1465
|
private tryLowerStyleObject(expr: string): string | null {
|
|
1463
1466
|
const entries = parseStyleObjectEntries(expr)
|
|
@@ -1465,27 +1468,11 @@ export class MinijinjaAdapter extends BaseAdapter implements IRNodeEmitter<Jinja
|
|
|
1465
1468
|
for (const e of entries) {
|
|
1466
1469
|
if (e.kind === 'expr' && !isSupported(parseExpression(e.expr)).supported) return null
|
|
1467
1470
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
return
|
|
1473
|
-
.map(e =>
|
|
1474
|
-
e.kind === 'literal'
|
|
1475
|
-
? `${this.escapeAttrText(e.cssKey)}:${this.escapeAttrText(e.value)}`
|
|
1476
|
-
: `${this.escapeAttrText(e.cssKey)}:{{ bf.string(${this.convertExpressionToJinja(e.expr)}) }}`,
|
|
1477
|
-
)
|
|
1478
|
-
.join(';')
|
|
1479
|
-
}
|
|
1480
|
-
|
|
1481
|
-
/** HTML-attribute escape for static text inlined into a `"..."` attribute. */
|
|
1482
|
-
private escapeAttrText(s: string): string {
|
|
1483
|
-
return s
|
|
1484
|
-
.replace(/&/g, '&')
|
|
1485
|
-
.replace(/"/g, '"')
|
|
1486
|
-
.replace(/'/g, ''')
|
|
1487
|
-
.replace(/</g, '<')
|
|
1488
|
-
.replace(/>/g, '>')
|
|
1471
|
+
const args = entries.flatMap(e => [
|
|
1472
|
+
JSON.stringify(e.cssKey),
|
|
1473
|
+
e.kind === 'literal' ? JSON.stringify(e.value) : this.convertExpressionToJinja(e.expr),
|
|
1474
|
+
])
|
|
1475
|
+
return `{{ bf.style_object(${args.join(', ')}) }}`
|
|
1489
1476
|
}
|
|
1490
1477
|
|
|
1491
1478
|
private renderAttributes(element: IRElement): string {
|