@barefootjs/blade 0.18.3 → 0.18.5
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/blade-adapter.d.ts +8 -0
- package/dist/adapter/blade-adapter.d.ts.map +1 -1
- package/dist/adapter/emit-context.d.ts +2 -0
- package/dist/adapter/emit-context.d.ts.map +1 -1
- package/dist/adapter/expr/array-method.d.ts.map +1 -1
- package/dist/adapter/expr/emitters.d.ts +2 -2
- package/dist/adapter/expr/emitters.d.ts.map +1 -1
- package/dist/adapter/index.js +60 -17
- package/dist/adapter/lib/constants.d.ts.map +1 -1
- package/dist/build.js +60 -17
- package/dist/conformance-pins.d.ts.map +1 -1
- package/dist/index.js +62 -34
- package/dist/render-divergences.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/blade-adapter-unit.test.ts +21 -0
- package/src/adapter/blade-adapter.ts +71 -7
- package/src/adapter/emit-context.ts +3 -0
- package/src/adapter/expr/array-method.ts +19 -0
- package/src/adapter/expr/emitters.ts +28 -7
- package/src/adapter/lib/constants.ts +3 -0
- package/src/conformance-pins.ts +0 -5
- package/src/render-divergences.ts +1 -28
|
@@ -262,6 +262,14 @@ export declare class BladeAdapter extends BaseAdapter implements IRNodeEmitter<B
|
|
|
262
262
|
private options;
|
|
263
263
|
private errors;
|
|
264
264
|
private inLoop;
|
|
265
|
+
/**
|
|
266
|
+
* `IRLoop.depth` of the loop currently being rendered (save/restore
|
|
267
|
+
* around `renderChildren(loop.children)`, mirroring `inLoop` above).
|
|
268
|
+
* `renderAttributes` reads this to derive the `key` → `data-key`/
|
|
269
|
+
* `data-key-N` suffix — the depth is IR-computed (jsx-to-ir.ts), not
|
|
270
|
+
* re-derived here (#2168 nested-loop-outer-binding).
|
|
271
|
+
*/
|
|
272
|
+
private currentLoopKeyDepth;
|
|
265
273
|
/**
|
|
266
274
|
* SolidJS-style props identifier (`function(props: P)`) and the
|
|
267
275
|
* analyzer-extracted prop names. Stashed at `generate()` entry so the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blade-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/blade-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6OG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,MAAM,EACN,SAAS,EACT,MAAM,EACN,YAAY,EACZ,aAAa,EACb,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,OAAO,EAKP,yBAAyB,EAE1B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,sBAAsB,EAE3B,KAAK,aAAa,EAClB,KAAK,UAAU,EAyBhB,MAAM,iBAAiB,CAAA;AAKxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAkCpD,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACzD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAEzD,qBAAa,YAAa,SAAQ,WAAY,YAAW,aAAa,CAAC,cAAc,CAAC;IACpF,IAAI,SAAU;IACd,SAAS,SAAe;IACxB,qBAAqB,UAAO;IAG5B,kBAAkB,EAAG,cAAc,CAAS;IAE5C;;;;;OAKG;IACH,kBAAkB,EAAE,yBAAyB,CAA2B;IAExE,OAAO,CAAC,aAAa,CAAa;IAClC;;;uCAGmC;IACnC,OAAO,CAAC,cAAc,CAAyB;IAC/C,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAiB;IAC/B;;;;;OAKG;IACH,OAAO,CAAC,eAAe,CAAsB;IAC7C,OAAO,CAAC,WAAW,CAAyB;IAC5C,OAAO,CAAC,iBAAiB,CAAyB;IAClD;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB,CAAyB;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB,CAAiC;IAE3D;;;;;;;OAOG;IACH,OAAO,CAAC,mBAAmB,CAAyB;IAEpD;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB,CAAwB;IAEjD;;;;;OAKG;IACH,OAAO,CAAC,cAAc,CAAmC;IAEzD;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB,CAAyB;IAEtD,YAAY,OAAO,GAAE,mBAAwB,EAM5C;IAED,QAAQ,CAAC,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,aAAa,CA4EzE;IAMD,OAAO,CAAC,2BAA2B;IAuBnC;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/B;IAMD,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,UAAU,CAAC,cAAc,CAAC,GAAG,MAAM,CAE5F;IAED,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"blade-adapter.d.ts","sourceRoot":"","sources":["../../src/adapter/blade-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,6 +36,8 @@ export interface BladeEmitContext {
|
|
|
36
36
|
* (`variantClasses.ghost`) to its Blade value at compile time, or null.
|
|
37
37
|
*/
|
|
38
38
|
_resolveStaticRecordLiteral(objectName: string, key: string): string | null;
|
|
39
|
+
/** Whether a getter/prop name resolves to a string-typed SSR value. */
|
|
40
|
+
_isStringValueName(name: string): boolean;
|
|
39
41
|
/** Record a BF101 unsupported-expression diagnostic. */
|
|
40
42
|
_recordExprBF101(message: string, reason?: string): void;
|
|
41
43
|
/** Lower a filter/predicate body to its Blade form, bound to `param`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit-context.d.ts","sourceRoot":"","sources":["../../src/adapter/emit-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5E,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEtD,oFAAoF;IACpF,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEjD;;;OAGG;IACH,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAE3E,wDAAwD;IACxD,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAExD,yEAAyE;IACzE,4BAA4B,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;IAEhC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAA;IAErD,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAExC;;;;;;;;OAQG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;OAMG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CACjC"}
|
|
1
|
+
{"version":3,"file":"emit-context.d.ts","sourceRoot":"","sources":["../../src/adapter/emit-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5E,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEtD,oFAAoF;IACpF,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEjD;;;OAGG;IACH,2BAA2B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAE3E,uEAAuE;IACvE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAEzC,wDAAwD;IACxD,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAExD,yEAAyE;IACzE,4BAA4B,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;IAEhC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAA;IAErD,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAExC;;;;;;;;OAQG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;OAMG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;IAEtE;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;CACjC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAGxB,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,
|
|
1
|
+
{"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAGxB,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAgJR;AAqBD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAUf;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAkBf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,EAC/B,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,GAAG,IAAI,CAMf;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CASxE;AAGD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,SAAS,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,EACvC,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAmBR"}
|
|
@@ -111,7 +111,7 @@ export declare class BladeFilterEmitter implements ParsedExprEmitter {
|
|
|
111
111
|
constructor(param: string, localVarMap: Map<string, string>, isStringName?: (n: string) => boolean, onUnsupported?: ((message: string, reason?: string) => void) | undefined);
|
|
112
112
|
identifier(name: string): string;
|
|
113
113
|
literal(value: string | number | boolean | null, literalType: LiteralType): string;
|
|
114
|
-
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
|
|
114
|
+
member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string;
|
|
115
115
|
indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
116
116
|
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
117
117
|
unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
@@ -145,7 +145,7 @@ export declare class BladeTopLevelEmitter implements ParsedExprEmitter {
|
|
|
145
145
|
constructor(ctx: BladeEmitContext);
|
|
146
146
|
identifier(name: string): string;
|
|
147
147
|
literal(value: string | number | boolean | null, literalType: LiteralType): string;
|
|
148
|
-
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
|
|
148
|
+
member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string;
|
|
149
149
|
indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
150
150
|
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
151
151
|
unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emitters.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/emitters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"emitters.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/emitters.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter/index.js
CHANGED
|
@@ -187369,7 +187369,7 @@ function isAriaBooleanAttr(name) {
|
|
|
187369
187369
|
}
|
|
187370
187370
|
|
|
187371
187371
|
// src/adapter/blade-adapter.ts
|
|
187372
|
-
import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
|
|
187372
|
+
import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
|
|
187373
187373
|
|
|
187374
187374
|
// src/adapter/lib/constants.ts
|
|
187375
187375
|
var BLADE_TEMPLATE_PRIMITIVES = {
|
|
@@ -187378,7 +187378,10 @@ var BLADE_TEMPLATE_PRIMITIVES = {
|
|
|
187378
187378
|
Number: { arity: 1, emit: (args) => `$bf->number(${args[0]})` },
|
|
187379
187379
|
"Math.floor": { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
|
|
187380
187380
|
"Math.ceil": { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
|
|
187381
|
-
"Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` }
|
|
187381
|
+
"Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
|
|
187382
|
+
"Math.min": { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
|
|
187383
|
+
"Math.max": { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
|
|
187384
|
+
"Math.abs": { arity: 1, emit: (args) => `$bf->abs(${args[0]})` }
|
|
187382
187385
|
};
|
|
187383
187386
|
var BLADE_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(BLADE_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
|
|
187384
187387
|
|
|
@@ -187512,6 +187515,12 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
187512
187515
|
const recv = emit(object);
|
|
187513
187516
|
return `$bf->trim(${recv})`;
|
|
187514
187517
|
}
|
|
187518
|
+
case "trimStart":
|
|
187519
|
+
case "trimEnd": {
|
|
187520
|
+
const fn = method === "trimStart" ? "trim_start" : "trim_end";
|
|
187521
|
+
const recv = emit(object);
|
|
187522
|
+
return `$bf->${fn}(${recv})`;
|
|
187523
|
+
}
|
|
187515
187524
|
case "toFixed": {
|
|
187516
187525
|
const recv = emit(object);
|
|
187517
187526
|
const digits = args.length >= 1 ? emit(args[0]) : "0";
|
|
@@ -187545,6 +187554,12 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
187545
187554
|
const newS = emit(args[1]);
|
|
187546
187555
|
return `$bf->replace(${recv}, ${oldS}, ${newS})`;
|
|
187547
187556
|
}
|
|
187557
|
+
case "replaceAll": {
|
|
187558
|
+
const recv = emit(object);
|
|
187559
|
+
const oldS = emit(args[0]);
|
|
187560
|
+
const newS = emit(args[1]);
|
|
187561
|
+
return `$bf->replace_all(${recv}, ${oldS}, ${newS})`;
|
|
187562
|
+
}
|
|
187548
187563
|
case "repeat": {
|
|
187549
187564
|
const recv = emit(object);
|
|
187550
187565
|
const count = args.length === 0 ? "0" : emit(args[0]);
|
|
@@ -187641,6 +187656,8 @@ function renderFlatMethod(recv, depth, emit) {
|
|
|
187641
187656
|
|
|
187642
187657
|
// src/adapter/expr/emitters.ts
|
|
187643
187658
|
import {
|
|
187659
|
+
groupBinaryOperand,
|
|
187660
|
+
isStringConcatBinary,
|
|
187644
187661
|
identifierPath,
|
|
187645
187662
|
matchSearchParamsMethodCall,
|
|
187646
187663
|
sortComparatorFromArrow
|
|
@@ -187686,7 +187703,7 @@ class BladeFilterEmitter {
|
|
|
187686
187703
|
return "null";
|
|
187687
187704
|
return String(value);
|
|
187688
187705
|
}
|
|
187689
|
-
member(object, property, _computed, emit) {
|
|
187706
|
+
member(object, property, _computed, _optional, emit) {
|
|
187690
187707
|
if (property === "length") {
|
|
187691
187708
|
return `$bf->length(${emit(object)})`;
|
|
187692
187709
|
}
|
|
@@ -187709,12 +187726,15 @@ class BladeFilterEmitter {
|
|
|
187709
187726
|
return emit(argument);
|
|
187710
187727
|
}
|
|
187711
187728
|
binary(op, left, right, emit) {
|
|
187712
|
-
const l = emit(left);
|
|
187713
|
-
const r = emit(right);
|
|
187729
|
+
const l = groupBinaryOperand(left, emit(left));
|
|
187730
|
+
const r = groupBinaryOperand(right, emit(right));
|
|
187714
187731
|
if (op === "===")
|
|
187715
187732
|
return `$bf->eq(${l}, ${r})`;
|
|
187716
187733
|
if (op === "!==")
|
|
187717
187734
|
return `$bf->neq(${l}, ${r})`;
|
|
187735
|
+
if (isStringConcatBinary(op, left, right, this.isStringName)) {
|
|
187736
|
+
return `${l} . ${r}`;
|
|
187737
|
+
}
|
|
187718
187738
|
const opMap = {
|
|
187719
187739
|
">": ">",
|
|
187720
187740
|
"<": "<",
|
|
@@ -187794,7 +187814,7 @@ class BladeTopLevelEmitter {
|
|
|
187794
187814
|
return "null";
|
|
187795
187815
|
return String(value);
|
|
187796
187816
|
}
|
|
187797
|
-
member(object, property, _computed, emit) {
|
|
187817
|
+
member(object, property, _computed, _optional, emit) {
|
|
187798
187818
|
if (object.kind === "identifier" && object.name === "props") {
|
|
187799
187819
|
return bladeVar(property);
|
|
187800
187820
|
}
|
|
@@ -187840,12 +187860,15 @@ class BladeTopLevelEmitter {
|
|
|
187840
187860
|
return emit(argument);
|
|
187841
187861
|
}
|
|
187842
187862
|
binary(op, left, right, emit) {
|
|
187843
|
-
const l = emit(left);
|
|
187844
|
-
const r = emit(right);
|
|
187863
|
+
const l = groupBinaryOperand(left, emit(left));
|
|
187864
|
+
const r = groupBinaryOperand(right, emit(right));
|
|
187845
187865
|
if (op === "===")
|
|
187846
187866
|
return `$bf->eq(${l}, ${r})`;
|
|
187847
187867
|
if (op === "!==")
|
|
187848
187868
|
return `$bf->neq(${l}, ${r})`;
|
|
187869
|
+
if (isStringConcatBinary(op, left, right, (n) => this.ctx._isStringValueName(n))) {
|
|
187870
|
+
return `${l} . ${r}`;
|
|
187871
|
+
}
|
|
187849
187872
|
const opMap = {
|
|
187850
187873
|
">": ">",
|
|
187851
187874
|
"<": "<",
|
|
@@ -188215,6 +188238,7 @@ class BladeAdapter extends BaseAdapter {
|
|
|
188215
188238
|
options;
|
|
188216
188239
|
errors = [];
|
|
188217
188240
|
inLoop = false;
|
|
188241
|
+
currentLoopKeyDepth = 0;
|
|
188218
188242
|
propsObjectName = null;
|
|
188219
188243
|
propsParams = [];
|
|
188220
188244
|
booleanTypedProps = new Set;
|
|
@@ -188291,7 +188315,7 @@ class BladeAdapter extends BaseAdapter {
|
|
|
188291
188315
|
return this.renderElement(node);
|
|
188292
188316
|
}
|
|
188293
188317
|
emitText(node) {
|
|
188294
|
-
return node.value;
|
|
188318
|
+
return escapeHtml(node.value);
|
|
188295
188319
|
}
|
|
188296
188320
|
emitExpression(node) {
|
|
188297
188321
|
return this.renderExpression(node);
|
|
@@ -188521,7 +188545,7 @@ ${whenTrue}
|
|
|
188521
188545
|
const renderedChildren = this.renderChildren(loop.children);
|
|
188522
188546
|
const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
|
|
188523
188547
|
const indexLocalLines = [];
|
|
188524
|
-
if (loop.iterationShape === "keys") {
|
|
188548
|
+
if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
|
|
188525
188549
|
indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`);
|
|
188526
188550
|
} else if (loop.index) {
|
|
188527
188551
|
indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`);
|
|
@@ -188542,13 +188566,17 @@ ${whenTrue}
|
|
|
188542
188566
|
}
|
|
188543
188567
|
const prevInLoop = this.inLoop;
|
|
188544
188568
|
this.inLoop = true;
|
|
188569
|
+
const prevLoopKeyDepth = this.currentLoopKeyDepth;
|
|
188570
|
+
this.currentLoopKeyDepth = loop.depth;
|
|
188545
188571
|
const childrenUnderLoop = this.renderChildren(loop.children);
|
|
188572
|
+
this.currentLoopKeyDepth = prevLoopKeyDepth;
|
|
188546
188573
|
this.inLoop = prevInLoop;
|
|
188547
188574
|
const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{!! $bf->comment('loop-i:' . $bf->string(${this.convertExpressionToBlade(loop.key)})) !!}
|
|
188548
188575
|
${childrenUnderLoop}` : childrenUnderLoop;
|
|
188549
188576
|
const lines = [];
|
|
188550
188577
|
lines.push(`{!! $bf->comment("loop:${loop.markerId}") !!}`);
|
|
188551
|
-
|
|
188578
|
+
const forHeader = loop.objectIteration === "entries" ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})` : loop.objectIteration === "keys" ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})` : loop.objectIteration === "values" ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})` : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`;
|
|
188579
|
+
lines.push(forHeader);
|
|
188552
188580
|
for (const il of indexLocalLines)
|
|
188553
188581
|
lines.push(il);
|
|
188554
188582
|
if (loop.filterPredicate) {
|
|
@@ -188618,9 +188646,22 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188618
188646
|
renderComponent(comp) {
|
|
188619
188647
|
const segments = [{ kind: "entries", parts: [] }];
|
|
188620
188648
|
const currentEntries = () => this.componentPropSegmentEntries(segments);
|
|
188649
|
+
const namedSlotCaptures = [];
|
|
188621
188650
|
for (const p of comp.props) {
|
|
188622
188651
|
if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
|
|
188623
188652
|
continue;
|
|
188653
|
+
if (p.value.kind === "jsx-children" && p.name !== "children") {
|
|
188654
|
+
const prevInLoop = this.inLoop;
|
|
188655
|
+
this.inLoop = false;
|
|
188656
|
+
const slotBody = this.renderChildren(p.value.children);
|
|
188657
|
+
this.inLoop = prevInLoop;
|
|
188658
|
+
const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`);
|
|
188659
|
+
namedSlotCaptures.push(`@php(ob_start())
|
|
188660
|
+
${slotBody}
|
|
188661
|
+
` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`);
|
|
188662
|
+
currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`);
|
|
188663
|
+
continue;
|
|
188664
|
+
}
|
|
188624
188665
|
if (p.value.kind === "spread") {
|
|
188625
188666
|
const trimmed = p.value.expr.trim();
|
|
188626
188667
|
if (this.propsObjectName && this.propsObjectName === trimmed) {
|
|
@@ -188650,13 +188691,13 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188650
188691
|
const captureVar = bladeVar(`bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`);
|
|
188651
188692
|
currentEntries().push(`${bladeHashKey("children")} => ${captureVar}`);
|
|
188652
188693
|
const dict = this.combineComponentPropSegments(segments);
|
|
188653
|
-
return `@php(ob_start())
|
|
188694
|
+
return namedSlotCaptures.join("") + `@php(ob_start())
|
|
188654
188695
|
${childrenBody}
|
|
188655
188696
|
` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` + `{!! $bf->render_child('${tplName}', ${dict}) !!}`;
|
|
188656
188697
|
}
|
|
188657
188698
|
const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
|
|
188658
188699
|
const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
|
|
188659
|
-
return
|
|
188700
|
+
return `${namedSlotCaptures.join("")}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
|
|
188660
188701
|
}
|
|
188661
188702
|
childrenCaptureCounter = 0;
|
|
188662
188703
|
presenceVarCounter = 0;
|
|
@@ -188703,7 +188744,7 @@ ${fallback}
|
|
|
188703
188744
|
${children}`;
|
|
188704
188745
|
}
|
|
188705
188746
|
elementAttrEmitter = {
|
|
188706
|
-
emitLiteral: (value, name) => `${name}="${value.value}"`,
|
|
188747
|
+
emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
|
|
188707
188748
|
emitExpression: (value, name) => {
|
|
188708
188749
|
if (name === "style") {
|
|
188709
188750
|
const css = this.tryLowerStyleObject(value.expr);
|
|
@@ -188812,9 +188853,10 @@ ${name}="{!! e($bf->string(${val})) !!}"
|
|
|
188812
188853
|
let attrName;
|
|
188813
188854
|
if (attr.name === "className")
|
|
188814
188855
|
attrName = "class";
|
|
188815
|
-
else if (attr.name === "key")
|
|
188816
|
-
|
|
188817
|
-
|
|
188856
|
+
else if (attr.name === "key") {
|
|
188857
|
+
const depth = this.currentLoopKeyDepth;
|
|
188858
|
+
attrName = depth > 0 ? `data-key-${depth}` : "data-key";
|
|
188859
|
+
} else
|
|
188818
188860
|
attrName = attr.name;
|
|
188819
188861
|
const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
|
|
188820
188862
|
if (lowered)
|
|
@@ -188901,6 +188943,7 @@ ${reason}` : "";
|
|
|
188901
188943
|
_resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
|
|
188902
188944
|
_resolveLiteralConst: (name) => this._resolveLiteralConst(name),
|
|
188903
188945
|
_resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
|
|
188946
|
+
_isStringValueName: (name) => this._isStringValueName(name),
|
|
188904
188947
|
_recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
|
|
188905
188948
|
_renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p)
|
|
188906
188949
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/adapter/lib/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/adapter/lib/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAUnE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CAG7E,CAAA"}
|
package/dist/build.js
CHANGED
|
@@ -187369,7 +187369,7 @@ function isAriaBooleanAttr(name) {
|
|
|
187369
187369
|
}
|
|
187370
187370
|
|
|
187371
187371
|
// src/adapter/blade-adapter.ts
|
|
187372
|
-
import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
|
|
187372
|
+
import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
|
|
187373
187373
|
|
|
187374
187374
|
// src/adapter/lib/constants.ts
|
|
187375
187375
|
var BLADE_TEMPLATE_PRIMITIVES = {
|
|
@@ -187378,7 +187378,10 @@ var BLADE_TEMPLATE_PRIMITIVES = {
|
|
|
187378
187378
|
Number: { arity: 1, emit: (args) => `$bf->number(${args[0]})` },
|
|
187379
187379
|
"Math.floor": { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
|
|
187380
187380
|
"Math.ceil": { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
|
|
187381
|
-
"Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` }
|
|
187381
|
+
"Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
|
|
187382
|
+
"Math.min": { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
|
|
187383
|
+
"Math.max": { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
|
|
187384
|
+
"Math.abs": { arity: 1, emit: (args) => `$bf->abs(${args[0]})` }
|
|
187382
187385
|
};
|
|
187383
187386
|
var BLADE_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(BLADE_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
|
|
187384
187387
|
|
|
@@ -187512,6 +187515,12 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
187512
187515
|
const recv = emit(object);
|
|
187513
187516
|
return `$bf->trim(${recv})`;
|
|
187514
187517
|
}
|
|
187518
|
+
case "trimStart":
|
|
187519
|
+
case "trimEnd": {
|
|
187520
|
+
const fn = method === "trimStart" ? "trim_start" : "trim_end";
|
|
187521
|
+
const recv = emit(object);
|
|
187522
|
+
return `$bf->${fn}(${recv})`;
|
|
187523
|
+
}
|
|
187515
187524
|
case "toFixed": {
|
|
187516
187525
|
const recv = emit(object);
|
|
187517
187526
|
const digits = args.length >= 1 ? emit(args[0]) : "0";
|
|
@@ -187545,6 +187554,12 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
187545
187554
|
const newS = emit(args[1]);
|
|
187546
187555
|
return `$bf->replace(${recv}, ${oldS}, ${newS})`;
|
|
187547
187556
|
}
|
|
187557
|
+
case "replaceAll": {
|
|
187558
|
+
const recv = emit(object);
|
|
187559
|
+
const oldS = emit(args[0]);
|
|
187560
|
+
const newS = emit(args[1]);
|
|
187561
|
+
return `$bf->replace_all(${recv}, ${oldS}, ${newS})`;
|
|
187562
|
+
}
|
|
187548
187563
|
case "repeat": {
|
|
187549
187564
|
const recv = emit(object);
|
|
187550
187565
|
const count = args.length === 0 ? "0" : emit(args[0]);
|
|
@@ -187641,6 +187656,8 @@ function renderFlatMethod(recv, depth, emit) {
|
|
|
187641
187656
|
|
|
187642
187657
|
// src/adapter/expr/emitters.ts
|
|
187643
187658
|
import {
|
|
187659
|
+
groupBinaryOperand,
|
|
187660
|
+
isStringConcatBinary,
|
|
187644
187661
|
identifierPath,
|
|
187645
187662
|
matchSearchParamsMethodCall,
|
|
187646
187663
|
sortComparatorFromArrow
|
|
@@ -187686,7 +187703,7 @@ class BladeFilterEmitter {
|
|
|
187686
187703
|
return "null";
|
|
187687
187704
|
return String(value);
|
|
187688
187705
|
}
|
|
187689
|
-
member(object, property, _computed, emit) {
|
|
187706
|
+
member(object, property, _computed, _optional, emit) {
|
|
187690
187707
|
if (property === "length") {
|
|
187691
187708
|
return `$bf->length(${emit(object)})`;
|
|
187692
187709
|
}
|
|
@@ -187709,12 +187726,15 @@ class BladeFilterEmitter {
|
|
|
187709
187726
|
return emit(argument);
|
|
187710
187727
|
}
|
|
187711
187728
|
binary(op, left, right, emit) {
|
|
187712
|
-
const l = emit(left);
|
|
187713
|
-
const r = emit(right);
|
|
187729
|
+
const l = groupBinaryOperand(left, emit(left));
|
|
187730
|
+
const r = groupBinaryOperand(right, emit(right));
|
|
187714
187731
|
if (op === "===")
|
|
187715
187732
|
return `$bf->eq(${l}, ${r})`;
|
|
187716
187733
|
if (op === "!==")
|
|
187717
187734
|
return `$bf->neq(${l}, ${r})`;
|
|
187735
|
+
if (isStringConcatBinary(op, left, right, this.isStringName)) {
|
|
187736
|
+
return `${l} . ${r}`;
|
|
187737
|
+
}
|
|
187718
187738
|
const opMap = {
|
|
187719
187739
|
">": ">",
|
|
187720
187740
|
"<": "<",
|
|
@@ -187794,7 +187814,7 @@ class BladeTopLevelEmitter {
|
|
|
187794
187814
|
return "null";
|
|
187795
187815
|
return String(value);
|
|
187796
187816
|
}
|
|
187797
|
-
member(object, property, _computed, emit) {
|
|
187817
|
+
member(object, property, _computed, _optional, emit) {
|
|
187798
187818
|
if (object.kind === "identifier" && object.name === "props") {
|
|
187799
187819
|
return bladeVar(property);
|
|
187800
187820
|
}
|
|
@@ -187840,12 +187860,15 @@ class BladeTopLevelEmitter {
|
|
|
187840
187860
|
return emit(argument);
|
|
187841
187861
|
}
|
|
187842
187862
|
binary(op, left, right, emit) {
|
|
187843
|
-
const l = emit(left);
|
|
187844
|
-
const r = emit(right);
|
|
187863
|
+
const l = groupBinaryOperand(left, emit(left));
|
|
187864
|
+
const r = groupBinaryOperand(right, emit(right));
|
|
187845
187865
|
if (op === "===")
|
|
187846
187866
|
return `$bf->eq(${l}, ${r})`;
|
|
187847
187867
|
if (op === "!==")
|
|
187848
187868
|
return `$bf->neq(${l}, ${r})`;
|
|
187869
|
+
if (isStringConcatBinary(op, left, right, (n) => this.ctx._isStringValueName(n))) {
|
|
187870
|
+
return `${l} . ${r}`;
|
|
187871
|
+
}
|
|
187849
187872
|
const opMap = {
|
|
187850
187873
|
">": ">",
|
|
187851
187874
|
"<": "<",
|
|
@@ -188215,6 +188238,7 @@ class BladeAdapter extends BaseAdapter {
|
|
|
188215
188238
|
options;
|
|
188216
188239
|
errors = [];
|
|
188217
188240
|
inLoop = false;
|
|
188241
|
+
currentLoopKeyDepth = 0;
|
|
188218
188242
|
propsObjectName = null;
|
|
188219
188243
|
propsParams = [];
|
|
188220
188244
|
booleanTypedProps = new Set;
|
|
@@ -188291,7 +188315,7 @@ class BladeAdapter extends BaseAdapter {
|
|
|
188291
188315
|
return this.renderElement(node);
|
|
188292
188316
|
}
|
|
188293
188317
|
emitText(node) {
|
|
188294
|
-
return node.value;
|
|
188318
|
+
return escapeHtml(node.value);
|
|
188295
188319
|
}
|
|
188296
188320
|
emitExpression(node) {
|
|
188297
188321
|
return this.renderExpression(node);
|
|
@@ -188521,7 +188545,7 @@ ${whenTrue}
|
|
|
188521
188545
|
const renderedChildren = this.renderChildren(loop.children);
|
|
188522
188546
|
const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
|
|
188523
188547
|
const indexLocalLines = [];
|
|
188524
|
-
if (loop.iterationShape === "keys") {
|
|
188548
|
+
if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
|
|
188525
188549
|
indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`);
|
|
188526
188550
|
} else if (loop.index) {
|
|
188527
188551
|
indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`);
|
|
@@ -188542,13 +188566,17 @@ ${whenTrue}
|
|
|
188542
188566
|
}
|
|
188543
188567
|
const prevInLoop = this.inLoop;
|
|
188544
188568
|
this.inLoop = true;
|
|
188569
|
+
const prevLoopKeyDepth = this.currentLoopKeyDepth;
|
|
188570
|
+
this.currentLoopKeyDepth = loop.depth;
|
|
188545
188571
|
const childrenUnderLoop = this.renderChildren(loop.children);
|
|
188572
|
+
this.currentLoopKeyDepth = prevLoopKeyDepth;
|
|
188546
188573
|
this.inLoop = prevInLoop;
|
|
188547
188574
|
const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{!! $bf->comment('loop-i:' . $bf->string(${this.convertExpressionToBlade(loop.key)})) !!}
|
|
188548
188575
|
${childrenUnderLoop}` : childrenUnderLoop;
|
|
188549
188576
|
const lines = [];
|
|
188550
188577
|
lines.push(`{!! $bf->comment("loop:${loop.markerId}") !!}`);
|
|
188551
|
-
|
|
188578
|
+
const forHeader = loop.objectIteration === "entries" ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})` : loop.objectIteration === "keys" ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})` : loop.objectIteration === "values" ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})` : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`;
|
|
188579
|
+
lines.push(forHeader);
|
|
188552
188580
|
for (const il of indexLocalLines)
|
|
188553
188581
|
lines.push(il);
|
|
188554
188582
|
if (loop.filterPredicate) {
|
|
@@ -188618,9 +188646,22 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188618
188646
|
renderComponent(comp) {
|
|
188619
188647
|
const segments = [{ kind: "entries", parts: [] }];
|
|
188620
188648
|
const currentEntries = () => this.componentPropSegmentEntries(segments);
|
|
188649
|
+
const namedSlotCaptures = [];
|
|
188621
188650
|
for (const p of comp.props) {
|
|
188622
188651
|
if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
|
|
188623
188652
|
continue;
|
|
188653
|
+
if (p.value.kind === "jsx-children" && p.name !== "children") {
|
|
188654
|
+
const prevInLoop = this.inLoop;
|
|
188655
|
+
this.inLoop = false;
|
|
188656
|
+
const slotBody = this.renderChildren(p.value.children);
|
|
188657
|
+
this.inLoop = prevInLoop;
|
|
188658
|
+
const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`);
|
|
188659
|
+
namedSlotCaptures.push(`@php(ob_start())
|
|
188660
|
+
${slotBody}
|
|
188661
|
+
` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`);
|
|
188662
|
+
currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`);
|
|
188663
|
+
continue;
|
|
188664
|
+
}
|
|
188624
188665
|
if (p.value.kind === "spread") {
|
|
188625
188666
|
const trimmed = p.value.expr.trim();
|
|
188626
188667
|
if (this.propsObjectName && this.propsObjectName === trimmed) {
|
|
@@ -188650,13 +188691,13 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188650
188691
|
const captureVar = bladeVar(`bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`);
|
|
188651
188692
|
currentEntries().push(`${bladeHashKey("children")} => ${captureVar}`);
|
|
188652
188693
|
const dict = this.combineComponentPropSegments(segments);
|
|
188653
|
-
return `@php(ob_start())
|
|
188694
|
+
return namedSlotCaptures.join("") + `@php(ob_start())
|
|
188654
188695
|
${childrenBody}
|
|
188655
188696
|
` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` + `{!! $bf->render_child('${tplName}', ${dict}) !!}`;
|
|
188656
188697
|
}
|
|
188657
188698
|
const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
|
|
188658
188699
|
const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
|
|
188659
|
-
return
|
|
188700
|
+
return `${namedSlotCaptures.join("")}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
|
|
188660
188701
|
}
|
|
188661
188702
|
childrenCaptureCounter = 0;
|
|
188662
188703
|
presenceVarCounter = 0;
|
|
@@ -188703,7 +188744,7 @@ ${fallback}
|
|
|
188703
188744
|
${children}`;
|
|
188704
188745
|
}
|
|
188705
188746
|
elementAttrEmitter = {
|
|
188706
|
-
emitLiteral: (value, name) => `${name}="${value.value}"`,
|
|
188747
|
+
emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
|
|
188707
188748
|
emitExpression: (value, name) => {
|
|
188708
188749
|
if (name === "style") {
|
|
188709
188750
|
const css = this.tryLowerStyleObject(value.expr);
|
|
@@ -188812,9 +188853,10 @@ ${name}="{!! e($bf->string(${val})) !!}"
|
|
|
188812
188853
|
let attrName;
|
|
188813
188854
|
if (attr.name === "className")
|
|
188814
188855
|
attrName = "class";
|
|
188815
|
-
else if (attr.name === "key")
|
|
188816
|
-
|
|
188817
|
-
|
|
188856
|
+
else if (attr.name === "key") {
|
|
188857
|
+
const depth = this.currentLoopKeyDepth;
|
|
188858
|
+
attrName = depth > 0 ? `data-key-${depth}` : "data-key";
|
|
188859
|
+
} else
|
|
188818
188860
|
attrName = attr.name;
|
|
188819
188861
|
const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
|
|
188820
188862
|
if (lowered)
|
|
@@ -188901,6 +188943,7 @@ ${reason}` : "";
|
|
|
188901
188943
|
_resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
|
|
188902
188944
|
_resolveLiteralConst: (name) => this._resolveLiteralConst(name),
|
|
188903
188945
|
_resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
|
|
188946
|
+
_isStringValueName: (name) => this._isStringValueName(name),
|
|
188904
188947
|
_recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
|
|
188905
188948
|
_renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p)
|
|
188906
188949
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"conformance-pins.d.ts","sourceRoot":"","sources":["../src/conformance-pins.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,eAAO,MAAM,eAAe,EAAE,eA+E7B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -187369,7 +187369,7 @@ function isAriaBooleanAttr(name) {
|
|
|
187369
187369
|
}
|
|
187370
187370
|
|
|
187371
187371
|
// src/adapter/blade-adapter.ts
|
|
187372
|
-
import { BF_SLOT, BF_COND, BF_REGION } from "@barefootjs/shared";
|
|
187372
|
+
import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from "@barefootjs/shared";
|
|
187373
187373
|
|
|
187374
187374
|
// src/adapter/lib/constants.ts
|
|
187375
187375
|
var BLADE_TEMPLATE_PRIMITIVES = {
|
|
@@ -187378,7 +187378,10 @@ var BLADE_TEMPLATE_PRIMITIVES = {
|
|
|
187378
187378
|
Number: { arity: 1, emit: (args) => `$bf->number(${args[0]})` },
|
|
187379
187379
|
"Math.floor": { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
|
|
187380
187380
|
"Math.ceil": { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
|
|
187381
|
-
"Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` }
|
|
187381
|
+
"Math.round": { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
|
|
187382
|
+
"Math.min": { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
|
|
187383
|
+
"Math.max": { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
|
|
187384
|
+
"Math.abs": { arity: 1, emit: (args) => `$bf->abs(${args[0]})` }
|
|
187382
187385
|
};
|
|
187383
187386
|
var BLADE_PRIMITIVE_EMIT_MAP = Object.fromEntries(Object.entries(BLADE_TEMPLATE_PRIMITIVES).map(([k, v]) => [k, v.emit]));
|
|
187384
187387
|
|
|
@@ -187512,6 +187515,12 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
187512
187515
|
const recv = emit(object);
|
|
187513
187516
|
return `$bf->trim(${recv})`;
|
|
187514
187517
|
}
|
|
187518
|
+
case "trimStart":
|
|
187519
|
+
case "trimEnd": {
|
|
187520
|
+
const fn = method === "trimStart" ? "trim_start" : "trim_end";
|
|
187521
|
+
const recv = emit(object);
|
|
187522
|
+
return `$bf->${fn}(${recv})`;
|
|
187523
|
+
}
|
|
187515
187524
|
case "toFixed": {
|
|
187516
187525
|
const recv = emit(object);
|
|
187517
187526
|
const digits = args.length >= 1 ? emit(args[0]) : "0";
|
|
@@ -187545,6 +187554,12 @@ function renderArrayMethod(method, object, args, emit) {
|
|
|
187545
187554
|
const newS = emit(args[1]);
|
|
187546
187555
|
return `$bf->replace(${recv}, ${oldS}, ${newS})`;
|
|
187547
187556
|
}
|
|
187557
|
+
case "replaceAll": {
|
|
187558
|
+
const recv = emit(object);
|
|
187559
|
+
const oldS = emit(args[0]);
|
|
187560
|
+
const newS = emit(args[1]);
|
|
187561
|
+
return `$bf->replace_all(${recv}, ${oldS}, ${newS})`;
|
|
187562
|
+
}
|
|
187548
187563
|
case "repeat": {
|
|
187549
187564
|
const recv = emit(object);
|
|
187550
187565
|
const count = args.length === 0 ? "0" : emit(args[0]);
|
|
@@ -187641,6 +187656,8 @@ function renderFlatMethod(recv, depth, emit) {
|
|
|
187641
187656
|
|
|
187642
187657
|
// src/adapter/expr/emitters.ts
|
|
187643
187658
|
import {
|
|
187659
|
+
groupBinaryOperand,
|
|
187660
|
+
isStringConcatBinary,
|
|
187644
187661
|
identifierPath,
|
|
187645
187662
|
matchSearchParamsMethodCall,
|
|
187646
187663
|
sortComparatorFromArrow
|
|
@@ -187686,7 +187703,7 @@ class BladeFilterEmitter {
|
|
|
187686
187703
|
return "null";
|
|
187687
187704
|
return String(value);
|
|
187688
187705
|
}
|
|
187689
|
-
member(object, property, _computed, emit) {
|
|
187706
|
+
member(object, property, _computed, _optional, emit) {
|
|
187690
187707
|
if (property === "length") {
|
|
187691
187708
|
return `$bf->length(${emit(object)})`;
|
|
187692
187709
|
}
|
|
@@ -187709,12 +187726,15 @@ class BladeFilterEmitter {
|
|
|
187709
187726
|
return emit(argument);
|
|
187710
187727
|
}
|
|
187711
187728
|
binary(op, left, right, emit) {
|
|
187712
|
-
const l = emit(left);
|
|
187713
|
-
const r = emit(right);
|
|
187729
|
+
const l = groupBinaryOperand(left, emit(left));
|
|
187730
|
+
const r = groupBinaryOperand(right, emit(right));
|
|
187714
187731
|
if (op === "===")
|
|
187715
187732
|
return `$bf->eq(${l}, ${r})`;
|
|
187716
187733
|
if (op === "!==")
|
|
187717
187734
|
return `$bf->neq(${l}, ${r})`;
|
|
187735
|
+
if (isStringConcatBinary(op, left, right, this.isStringName)) {
|
|
187736
|
+
return `${l} . ${r}`;
|
|
187737
|
+
}
|
|
187718
187738
|
const opMap = {
|
|
187719
187739
|
">": ">",
|
|
187720
187740
|
"<": "<",
|
|
@@ -187794,7 +187814,7 @@ class BladeTopLevelEmitter {
|
|
|
187794
187814
|
return "null";
|
|
187795
187815
|
return String(value);
|
|
187796
187816
|
}
|
|
187797
|
-
member(object, property, _computed, emit) {
|
|
187817
|
+
member(object, property, _computed, _optional, emit) {
|
|
187798
187818
|
if (object.kind === "identifier" && object.name === "props") {
|
|
187799
187819
|
return bladeVar(property);
|
|
187800
187820
|
}
|
|
@@ -187840,12 +187860,15 @@ class BladeTopLevelEmitter {
|
|
|
187840
187860
|
return emit(argument);
|
|
187841
187861
|
}
|
|
187842
187862
|
binary(op, left, right, emit) {
|
|
187843
|
-
const l = emit(left);
|
|
187844
|
-
const r = emit(right);
|
|
187863
|
+
const l = groupBinaryOperand(left, emit(left));
|
|
187864
|
+
const r = groupBinaryOperand(right, emit(right));
|
|
187845
187865
|
if (op === "===")
|
|
187846
187866
|
return `$bf->eq(${l}, ${r})`;
|
|
187847
187867
|
if (op === "!==")
|
|
187848
187868
|
return `$bf->neq(${l}, ${r})`;
|
|
187869
|
+
if (isStringConcatBinary(op, left, right, (n) => this.ctx._isStringValueName(n))) {
|
|
187870
|
+
return `${l} . ${r}`;
|
|
187871
|
+
}
|
|
187849
187872
|
const opMap = {
|
|
187850
187873
|
">": ">",
|
|
187851
187874
|
"<": "<",
|
|
@@ -188215,6 +188238,7 @@ class BladeAdapter extends BaseAdapter {
|
|
|
188215
188238
|
options;
|
|
188216
188239
|
errors = [];
|
|
188217
188240
|
inLoop = false;
|
|
188241
|
+
currentLoopKeyDepth = 0;
|
|
188218
188242
|
propsObjectName = null;
|
|
188219
188243
|
propsParams = [];
|
|
188220
188244
|
booleanTypedProps = new Set;
|
|
@@ -188291,7 +188315,7 @@ class BladeAdapter extends BaseAdapter {
|
|
|
188291
188315
|
return this.renderElement(node);
|
|
188292
188316
|
}
|
|
188293
188317
|
emitText(node) {
|
|
188294
|
-
return node.value;
|
|
188318
|
+
return escapeHtml(node.value);
|
|
188295
188319
|
}
|
|
188296
188320
|
emitExpression(node) {
|
|
188297
188321
|
return this.renderExpression(node);
|
|
@@ -188521,7 +188545,7 @@ ${whenTrue}
|
|
|
188521
188545
|
const renderedChildren = this.renderChildren(loop.children);
|
|
188522
188546
|
const loopVar = loop.iterationShape === "keys" ? "__bf_item" : supportableDestructure ? "__bf_item" : param;
|
|
188523
188547
|
const indexLocalLines = [];
|
|
188524
|
-
if (loop.iterationShape === "keys") {
|
|
188548
|
+
if (loop.objectIteration) {} else if (loop.iterationShape === "keys") {
|
|
188525
188549
|
indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`);
|
|
188526
188550
|
} else if (loop.index) {
|
|
188527
188551
|
indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`);
|
|
@@ -188542,13 +188566,17 @@ ${whenTrue}
|
|
|
188542
188566
|
}
|
|
188543
188567
|
const prevInLoop = this.inLoop;
|
|
188544
188568
|
this.inLoop = true;
|
|
188569
|
+
const prevLoopKeyDepth = this.currentLoopKeyDepth;
|
|
188570
|
+
this.currentLoopKeyDepth = loop.depth;
|
|
188545
188571
|
const childrenUnderLoop = this.renderChildren(loop.children);
|
|
188572
|
+
this.currentLoopKeyDepth = prevLoopKeyDepth;
|
|
188546
188573
|
this.inLoop = prevInLoop;
|
|
188547
188574
|
const bodyChildren = loop.bodyIsItemConditional && loop.key ? `{!! $bf->comment('loop-i:' . $bf->string(${this.convertExpressionToBlade(loop.key)})) !!}
|
|
188548
188575
|
${childrenUnderLoop}` : childrenUnderLoop;
|
|
188549
188576
|
const lines = [];
|
|
188550
188577
|
lines.push(`{!! $bf->comment("loop:${loop.markerId}") !!}`);
|
|
188551
|
-
|
|
188578
|
+
const forHeader = loop.objectIteration === "entries" ? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})` : loop.objectIteration === "keys" ? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})` : loop.objectIteration === "values" ? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})` : `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`;
|
|
188579
|
+
lines.push(forHeader);
|
|
188552
188580
|
for (const il of indexLocalLines)
|
|
188553
188581
|
lines.push(il);
|
|
188554
188582
|
if (loop.filterPredicate) {
|
|
@@ -188618,9 +188646,22 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188618
188646
|
renderComponent(comp) {
|
|
188619
188647
|
const segments = [{ kind: "entries", parts: [] }];
|
|
188620
188648
|
const currentEntries = () => this.componentPropSegmentEntries(segments);
|
|
188649
|
+
const namedSlotCaptures = [];
|
|
188621
188650
|
for (const p of comp.props) {
|
|
188622
188651
|
if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
|
|
188623
188652
|
continue;
|
|
188653
|
+
if (p.value.kind === "jsx-children" && p.name !== "children") {
|
|
188654
|
+
const prevInLoop = this.inLoop;
|
|
188655
|
+
this.inLoop = false;
|
|
188656
|
+
const slotBody = this.renderChildren(p.value.children);
|
|
188657
|
+
this.inLoop = prevInLoop;
|
|
188658
|
+
const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`);
|
|
188659
|
+
namedSlotCaptures.push(`@php(ob_start())
|
|
188660
|
+
${slotBody}
|
|
188661
|
+
` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`);
|
|
188662
|
+
currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`);
|
|
188663
|
+
continue;
|
|
188664
|
+
}
|
|
188624
188665
|
if (p.value.kind === "spread") {
|
|
188625
188666
|
const trimmed = p.value.expr.trim();
|
|
188626
188667
|
if (this.propsObjectName && this.propsObjectName === trimmed) {
|
|
@@ -188650,13 +188691,13 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188650
188691
|
const captureVar = bladeVar(`bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`);
|
|
188651
188692
|
currentEntries().push(`${bladeHashKey("children")} => ${captureVar}`);
|
|
188652
188693
|
const dict = this.combineComponentPropSegments(segments);
|
|
188653
|
-
return `@php(ob_start())
|
|
188694
|
+
return namedSlotCaptures.join("") + `@php(ob_start())
|
|
188654
188695
|
${childrenBody}
|
|
188655
188696
|
` + `@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` + `{!! $bf->render_child('${tplName}', ${dict}) !!}`;
|
|
188656
188697
|
}
|
|
188657
188698
|
const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
|
|
188658
188699
|
const dictEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
|
|
188659
|
-
return
|
|
188700
|
+
return `${namedSlotCaptures.join("")}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`;
|
|
188660
188701
|
}
|
|
188661
188702
|
childrenCaptureCounter = 0;
|
|
188662
188703
|
presenceVarCounter = 0;
|
|
@@ -188703,7 +188744,7 @@ ${fallback}
|
|
|
188703
188744
|
${children}`;
|
|
188704
188745
|
}
|
|
188705
188746
|
elementAttrEmitter = {
|
|
188706
|
-
emitLiteral: (value, name) => `${name}="${value.value}"`,
|
|
188747
|
+
emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
|
|
188707
188748
|
emitExpression: (value, name) => {
|
|
188708
188749
|
if (name === "style") {
|
|
188709
188750
|
const css = this.tryLowerStyleObject(value.expr);
|
|
@@ -188812,9 +188853,10 @@ ${name}="{!! e($bf->string(${val})) !!}"
|
|
|
188812
188853
|
let attrName;
|
|
188813
188854
|
if (attr.name === "className")
|
|
188814
188855
|
attrName = "class";
|
|
188815
|
-
else if (attr.name === "key")
|
|
188816
|
-
|
|
188817
|
-
|
|
188856
|
+
else if (attr.name === "key") {
|
|
188857
|
+
const depth = this.currentLoopKeyDepth;
|
|
188858
|
+
attrName = depth > 0 ? `data-key-${depth}` : "data-key";
|
|
188859
|
+
} else
|
|
188818
188860
|
attrName = attr.name;
|
|
188819
188861
|
const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName);
|
|
188820
188862
|
if (lowered)
|
|
@@ -188901,6 +188943,7 @@ ${reason}` : "";
|
|
|
188901
188943
|
_resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
|
|
188902
188944
|
_resolveLiteralConst: (name) => this._resolveLiteralConst(name),
|
|
188903
188945
|
_resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
|
|
188946
|
+
_isStringValueName: (name) => this._isStringValueName(name),
|
|
188904
188947
|
_recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
|
|
188905
188948
|
_renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p)
|
|
188906
188949
|
};
|
|
@@ -189071,25 +189114,10 @@ var conformancePins = {
|
|
|
189071
189114
|
{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2038" }
|
|
189072
189115
|
],
|
|
189073
189116
|
"array-map-function-reference": [{ code: "BF101", severity: "error" }],
|
|
189074
|
-
"dangerous-inner-html": [{ code: "BF101", severity: "error" }]
|
|
189075
|
-
"string-replaceall": [{ code: "BF101", severity: "error" }]
|
|
189117
|
+
"dangerous-inner-html": [{ code: "BF101", severity: "error" }]
|
|
189076
189118
|
};
|
|
189077
189119
|
// src/render-divergences.ts
|
|
189078
|
-
var renderDivergences = {
|
|
189079
|
-
"arithmetic-text": "`(count() + 2) * 3` renders 10 instead of 18 — the parenthesised sub-expression loses its grouping (silent wrong arithmetic)",
|
|
189080
|
-
"string-concat-plus": "`'Hello, ' + name` is emitted as PHP `+`, which fatals with \"Unsupported operand types: string + string\" — needs PHP's `.` concat",
|
|
189081
|
-
"html-entity-text": "`©` in JSX literal text: Hono decodes to `©`, this adapter re-emits the raw entity — same DOM, different bytes",
|
|
189082
|
-
"math-methods": "Math.min/max/abs over a signal render empty (only Math.floor is in the template-primitive registry)",
|
|
189083
|
-
"boolean-attr-literals": 'camelCase boolean alias `readOnly`: Hono SSRs `readOnly="true"`, this adapter emits bare presence',
|
|
189084
|
-
"camelcase-attributes": "`htmlFor` is not lowered to `for` (Hono maps it)",
|
|
189085
|
-
"static-attr-escape": 'static attribute values are not HTML-escaped (`title="Fish & Chips"` emitted raw; Hono escapes)',
|
|
189086
|
-
"svg-icon": "SVG camelCase presentation attrs (`strokeWidth`, `strokeLinecap`) pass through unmapped; Hono lowers to kebab-case",
|
|
189087
|
-
"object-entries-map": "`Object.entries(prop).map(([k, v]) => …)` renders an EMPTY list — the object-shaped prop silently produces zero iterations",
|
|
189088
|
-
"nested-loop-outer-binding": "nested-loop inner items carry `data-key` where the reference emits the depth-suffixed `data-key-1`",
|
|
189089
|
-
"jsx-element-prop": "a JSX element passed as a NON-children prop renders an empty slot — the element value is silently dropped",
|
|
189090
|
-
"string-slice": "`.slice()` on a STRING renders empty (array-slice helper misfires on strings)",
|
|
189091
|
-
"string-trim-sided": "`.trimStart()` / `.trimEnd()` render empty (no lowering)"
|
|
189092
|
-
};
|
|
189120
|
+
var renderDivergences = {};
|
|
189093
189121
|
export {
|
|
189094
189122
|
renderDivergences,
|
|
189095
189123
|
conformancePins,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"render-divergences.d.ts","sourceRoot":"","sources":["../src/render-divergences.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,eAAO,MAAM,iBAAiB,EAAE,iBAAsB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/blade",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.5",
|
|
4
4
|
"description": "Laravel Blade (PHP) adapter for BarefootJS — compiles IR to .blade.php templates and ships the PHP BarefootJS rendering runtime on illuminate/view standalone",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -54,14 +54,14 @@
|
|
|
54
54
|
"directory": "packages/adapter-blade"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@barefootjs/shared": "0.18.
|
|
57
|
+
"@barefootjs/shared": "0.18.5"
|
|
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.18.
|
|
64
|
+
"@barefootjs/jsx": "0.18.5",
|
|
65
65
|
"typescript": "^5.0.0"
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -385,6 +385,27 @@ export function C(props: { count: number }) {
|
|
|
385
385
|
})
|
|
386
386
|
})
|
|
387
387
|
|
|
388
|
+
describe('BladeAdapter - named-slot capture identifier safety (#2168 jsx-element-prop)', () => {
|
|
389
|
+
// A JSX-valued prop under a hyphenated name (`data-slot`, a valid JSX
|
|
390
|
+
// attribute name) must not leak into the capture variable — `bladeIdent`
|
|
391
|
+
// only guards reserved words, not non-identifier characters like `-`, so
|
|
392
|
+
// a name-derived variable would emit invalid PHP. The capture variable is
|
|
393
|
+
// purely counter-based (never derived from the prop name); the hash KEY
|
|
394
|
+
// passed to `render_child` still carries the real name, quoted via
|
|
395
|
+
// `bladeHashKey`.
|
|
396
|
+
test('a hyphenated prop name does not appear in the capture variable', () => {
|
|
397
|
+
const { template } = compileAndGenerate(`
|
|
398
|
+
function Card(props) { return null }
|
|
399
|
+
export function Parent() {
|
|
400
|
+
return <Card data-slot={<strong>Title</strong>}>text</Card>
|
|
401
|
+
}
|
|
402
|
+
`)
|
|
403
|
+
expect(template).toContain('@php($bf_prop_0 = $bf->backend->mark_raw(')
|
|
404
|
+
expect(template).toContain("'data-slot' => $bf_prop_0")
|
|
405
|
+
expect(template).not.toContain('$bf_prop_data')
|
|
406
|
+
})
|
|
407
|
+
})
|
|
408
|
+
|
|
388
409
|
// #2038 nested-callback-predicate loudness is pinned at the shared
|
|
389
410
|
// conformance layer (workstream C): `filter-nested-callback-predicate` /
|
|
390
411
|
// `filter-nested-find-predicate` (BF101 via `expectedDiagnostics`) and
|
|
@@ -292,7 +292,7 @@ import {
|
|
|
292
292
|
} from '@barefootjs/jsx'
|
|
293
293
|
import { isAriaBooleanAttr, isBooleanResultExpr, isExplicitStringCall } from './boolean-result.ts'
|
|
294
294
|
import type { ParsedExpr, LoweringMatcher } from '@barefootjs/jsx'
|
|
295
|
-
import { BF_SLOT, BF_COND, BF_REGION } from '@barefootjs/shared'
|
|
295
|
+
import { BF_SLOT, BF_COND, BF_REGION, escapeHtml } from '@barefootjs/shared'
|
|
296
296
|
|
|
297
297
|
import type { BladeRenderCtx } from './lib/types.ts'
|
|
298
298
|
import { BLADE_PRIMITIVE_EMIT_MAP } from './lib/constants.ts'
|
|
@@ -356,6 +356,14 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
356
356
|
private options: Required<BladeAdapterOptions>
|
|
357
357
|
private errors: CompilerError[] = []
|
|
358
358
|
private inLoop: boolean = false
|
|
359
|
+
/**
|
|
360
|
+
* `IRLoop.depth` of the loop currently being rendered (save/restore
|
|
361
|
+
* around `renderChildren(loop.children)`, mirroring `inLoop` above).
|
|
362
|
+
* `renderAttributes` reads this to derive the `key` → `data-key`/
|
|
363
|
+
* `data-key-N` suffix — the depth is IR-computed (jsx-to-ir.ts), not
|
|
364
|
+
* re-derived here (#2168 nested-loop-outer-binding).
|
|
365
|
+
*/
|
|
366
|
+
private currentLoopKeyDepth = 0
|
|
359
367
|
/**
|
|
360
368
|
* SolidJS-style props identifier (`function(props: P)`) and the
|
|
361
369
|
* analyzer-extracted prop names. Stashed at `generate()` entry so the
|
|
@@ -550,7 +558,9 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
550
558
|
}
|
|
551
559
|
|
|
552
560
|
emitText(node: IRText): string {
|
|
553
|
-
|
|
561
|
+
// IRText carries the entity-DECODED value (Phase 1 decodes JSX
|
|
562
|
+
// character references); re-escape for direct HTML emission.
|
|
563
|
+
return escapeHtml(node.value)
|
|
554
564
|
}
|
|
555
565
|
|
|
556
566
|
emitExpression(node: IRExpression): string {
|
|
@@ -922,7 +932,11 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
922
932
|
// other than member-access / spread (already refused by the gate)
|
|
923
933
|
// can't observe a sibling field the pattern destructured explicitly.
|
|
924
934
|
const indexLocalLines: string[] = []
|
|
925
|
-
if (loop.
|
|
935
|
+
if (loop.objectIteration) {
|
|
936
|
+
// `key`/`value` bind directly in the `@foreach` header (see below)
|
|
937
|
+
// via `$bf->entries`/`$bf->keys`/`$bf->values` — no derived
|
|
938
|
+
// `$loop->index` local needed, unlike the array `iterationShape` cases.
|
|
939
|
+
} else if (loop.iterationShape === 'keys') {
|
|
926
940
|
indexLocalLines.push(`@php(${bladeVar(param)} = $loop->index)`)
|
|
927
941
|
} else if (loop.index) {
|
|
928
942
|
indexLocalLines.push(`@php(${bladeVar(loop.index)} = $loop->index)`)
|
|
@@ -950,10 +964,13 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
950
964
|
|
|
951
965
|
const prevInLoop = this.inLoop
|
|
952
966
|
this.inLoop = true
|
|
967
|
+
const prevLoopKeyDepth = this.currentLoopKeyDepth
|
|
968
|
+
this.currentLoopKeyDepth = loop.depth
|
|
953
969
|
// Re-render children now that inLoop is set (so nested components use the
|
|
954
970
|
// loop-child naming convention). renderedChildren above was computed with
|
|
955
971
|
// the previous flag; recompute under the loop flag.
|
|
956
972
|
const childrenUnderLoop = this.renderChildren(loop.children)
|
|
973
|
+
this.currentLoopKeyDepth = prevLoopKeyDepth
|
|
957
974
|
this.inLoop = prevInLoop
|
|
958
975
|
void renderedChildren
|
|
959
976
|
|
|
@@ -973,7 +990,23 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
973
990
|
// See this file's header, divergence 2: raw PHP `foreach` over a
|
|
974
991
|
// null/undefined array raises, unlike Twig's `strict_variables: false`
|
|
975
992
|
// tolerance — the `?? []` guard restores that same tolerance uniformly.
|
|
976
|
-
|
|
993
|
+
//
|
|
994
|
+
// `objectIteration` (#2168 object-entries-map): PHP's native `foreach`
|
|
995
|
+
// CAN iterate a `stdClass` object's public properties directly (unlike
|
|
996
|
+
// Twig's `for` tag, which needs `Traversable`) — but this still routes
|
|
997
|
+
// through `$bf->entries`/`$bf->keys`/`$bf->values` for the same
|
|
998
|
+
// defensive non-object guard Twig needs and for a single source of
|
|
999
|
+
// truth on "is this a JS object" (`isJsObject`, `BarefootJS.php`); the
|
|
1000
|
+
// `(array)` cast those methods do preserves the object's own insertion
|
|
1001
|
+
// order either way.
|
|
1002
|
+
const forHeader = loop.objectIteration === 'entries'
|
|
1003
|
+
? `@foreach($bf->entries(${array} ?? []) as ${bladeVar(loop.index ?? param)} => ${bladeVar(param)})`
|
|
1004
|
+
: loop.objectIteration === 'keys'
|
|
1005
|
+
? `@foreach($bf->keys(${array} ?? []) as ${bladeVar(param)})`
|
|
1006
|
+
: loop.objectIteration === 'values'
|
|
1007
|
+
? `@foreach($bf->values(${array} ?? []) as ${bladeVar(param)})`
|
|
1008
|
+
: `@foreach((${array} ?? []) as ${bladeVar(loopVar)})`
|
|
1009
|
+
lines.push(forHeader)
|
|
977
1010
|
for (const il of indexLocalLines) lines.push(il)
|
|
978
1011
|
|
|
979
1012
|
// Handle filter().map() pattern by wrapping children in if-condition
|
|
@@ -1114,11 +1147,37 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
1114
1147
|
type Segment = { kind: 'entries'; parts: string[] } | { kind: 'spread'; expr: string }
|
|
1115
1148
|
const segments: Segment[] = [{ kind: 'entries', parts: [] }]
|
|
1116
1149
|
const currentEntries = () => this.componentPropSegmentEntries(segments)
|
|
1150
|
+
// Named JSX-valued props OTHER than the reserved `children`
|
|
1151
|
+
// (`header={<strong>Title</strong>}`, #2168 jsx-element-prop) each get
|
|
1152
|
+
// their own output-buffering capture, prepended to the final returned
|
|
1153
|
+
// string below — same mechanism as the reserved children capture,
|
|
1154
|
+
// just keyed by the prop's own name instead of `children`.
|
|
1155
|
+
const namedSlotCaptures: string[] = []
|
|
1117
1156
|
|
|
1118
1157
|
for (const p of comp.props) {
|
|
1119
1158
|
// Skip callback props (onXxx) and `ref` — both are client-only for
|
|
1120
1159
|
// SSR (Hono renders neither; the client JS wires them at hydration).
|
|
1121
1160
|
if ((p.name.match(/^on[A-Z]/) || p.name === 'ref') && p.value.kind === 'expression') continue
|
|
1161
|
+
if (p.value.kind === 'jsx-children' && p.name !== 'children') {
|
|
1162
|
+
const prevInLoop = this.inLoop
|
|
1163
|
+
this.inLoop = false
|
|
1164
|
+
const slotBody = this.renderChildren(p.value.children)
|
|
1165
|
+
this.inLoop = prevInLoop
|
|
1166
|
+
// Purely counter-based — NOT derived from `p.name` or `comp.slotId`.
|
|
1167
|
+
// A JSX prop name can contain characters (`data-slot`) `bladeIdent`
|
|
1168
|
+
// doesn't sanitize (it only guards reserved words), producing an
|
|
1169
|
+
// invalid PHP variable name; `comp.slotId` alone would also collide
|
|
1170
|
+
// across two named-slot props on the same component invocation
|
|
1171
|
+
// (unlike the reserved children slot, there's only ever one of
|
|
1172
|
+
// those per invocation).
|
|
1173
|
+
const captureVar = bladeVar(`bf_prop_${this.childrenCaptureCounter++}`)
|
|
1174
|
+
namedSlotCaptures.push(
|
|
1175
|
+
`@php(ob_start())\n${slotBody}\n` +
|
|
1176
|
+
`@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))`,
|
|
1177
|
+
)
|
|
1178
|
+
currentEntries().push(`${bladeHashKey(p.name)} => ${captureVar}`)
|
|
1179
|
+
continue
|
|
1180
|
+
}
|
|
1122
1181
|
if (p.value.kind === 'spread') {
|
|
1123
1182
|
const trimmed = p.value.expr.trim()
|
|
1124
1183
|
// SolidJS-style props identifier (`function(props: P)`) has no
|
|
@@ -1193,6 +1252,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
1193
1252
|
currentEntries().push(`${bladeHashKey('children')} => ${captureVar}`)
|
|
1194
1253
|
const dict = this.combineComponentPropSegments(segments)
|
|
1195
1254
|
return (
|
|
1255
|
+
namedSlotCaptures.join('') +
|
|
1196
1256
|
`@php(ob_start())\n${childrenBody}\n` +
|
|
1197
1257
|
`@php(${captureVar} = $bf->backend->mark_raw(preg_replace('/\\n\\z/', '', ob_get_clean(), 1)))` +
|
|
1198
1258
|
`{!! $bf->render_child('${tplName}', ${dict}) !!}`
|
|
@@ -1201,7 +1261,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
1201
1261
|
|
|
1202
1262
|
const isEmpty = segments.every(s => s.kind === 'entries' && s.parts.length === 0)
|
|
1203
1263
|
const dictEntries = isEmpty ? '' : `, ${this.combineComponentPropSegments(segments)}`
|
|
1204
|
-
return
|
|
1264
|
+
return `${namedSlotCaptures.join('')}{!! $bf->render_child('${tplName}'${dictEntries}) !!}`
|
|
1205
1265
|
}
|
|
1206
1266
|
|
|
1207
1267
|
private childrenCaptureCounter = 0
|
|
@@ -1291,7 +1351,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
1291
1351
|
* AttrValue lowering for intrinsic-element attributes (Blade).
|
|
1292
1352
|
*/
|
|
1293
1353
|
private readonly elementAttrEmitter: AttrValueEmitter = {
|
|
1294
|
-
emitLiteral: (value, name) => `${name}="${value.value}"`,
|
|
1354
|
+
emitLiteral: (value, name) => `${name}="${escapeHtml(value.value)}"`,
|
|
1295
1355
|
emitExpression: (value, name) => {
|
|
1296
1356
|
// `style={{ … }}` object literal → a CSS string with dynamic values
|
|
1297
1357
|
// interpolated, instead of refusing the bare object with BF101 (#1322).
|
|
@@ -1497,7 +1557,10 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
1497
1557
|
// Rewrite JSX special-prop names to their HTML-attribute counterparts.
|
|
1498
1558
|
let attrName: string
|
|
1499
1559
|
if (attr.name === 'className') attrName = 'class'
|
|
1500
|
-
else if (attr.name === 'key')
|
|
1560
|
+
else if (attr.name === 'key') {
|
|
1561
|
+
const depth = this.currentLoopKeyDepth
|
|
1562
|
+
attrName = depth > 0 ? `data-key-${depth}` : 'data-key'
|
|
1563
|
+
}
|
|
1501
1564
|
else attrName = attr.name
|
|
1502
1565
|
const lowered = emitAttrValue(attr.value, this.elementAttrEmitter, attrName)
|
|
1503
1566
|
if (lowered) parts.push(lowered)
|
|
@@ -1659,6 +1722,7 @@ export class BladeAdapter extends BaseAdapter implements IRNodeEmitter<BladeRend
|
|
|
1659
1722
|
_resolveModuleStringConst: (name) => this._resolveModuleStringConst(name),
|
|
1660
1723
|
_resolveLiteralConst: (name) => this._resolveLiteralConst(name),
|
|
1661
1724
|
_resolveStaticRecordLiteral: (o, k) => this._resolveStaticRecordLiteral(o, k),
|
|
1725
|
+
_isStringValueName: (name) => this._isStringValueName(name),
|
|
1662
1726
|
_recordExprBF101: (message, reason) => this._recordExprBF101(message, reason),
|
|
1663
1727
|
_renderBladeFilterExprPublic: (e, p) => this._renderBladeFilterExprPublic(e, p),
|
|
1664
1728
|
}
|
|
@@ -42,6 +42,9 @@ export interface BladeEmitContext {
|
|
|
42
42
|
*/
|
|
43
43
|
_resolveStaticRecordLiteral(objectName: string, key: string): string | null
|
|
44
44
|
|
|
45
|
+
/** Whether a getter/prop name resolves to a string-typed SSR value. */
|
|
46
|
+
_isStringValueName(name: string): boolean
|
|
47
|
+
|
|
45
48
|
/** Record a BF101 unsupported-expression diagnostic. */
|
|
46
49
|
_recordExprBF101(message: string, reason?: string): void
|
|
47
50
|
|
|
@@ -90,6 +90,15 @@ export function renderArrayMethod(
|
|
|
90
90
|
const recv = emit(object)
|
|
91
91
|
return `$bf->trim(${recv})`
|
|
92
92
|
}
|
|
93
|
+
case 'trimStart':
|
|
94
|
+
case 'trimEnd': {
|
|
95
|
+
// `.trimStart()` / `.trimEnd()` — the one-sided siblings of
|
|
96
|
+
// `.trim()` (#2183 follow-up). Dedicated `$bf->trim_start` /
|
|
97
|
+
// `$bf->trim_end` helpers, not `$bf->trim` with a flag.
|
|
98
|
+
const fn = method === 'trimStart' ? 'trim_start' : 'trim_end'
|
|
99
|
+
const recv = emit(object)
|
|
100
|
+
return `$bf->${fn}(${recv})`
|
|
101
|
+
}
|
|
93
102
|
case 'toFixed': {
|
|
94
103
|
// `.toFixed(digits?)` — `$bf->to_fixed` mirrors JS rounding +
|
|
95
104
|
// zero-padding (default 0 digits). #1897.
|
|
@@ -125,6 +134,16 @@ export function renderArrayMethod(
|
|
|
125
134
|
const newS = emit(args[1])
|
|
126
135
|
return `$bf->replace(${recv}, ${oldS}, ${newS})`
|
|
127
136
|
}
|
|
137
|
+
case 'replaceAll': {
|
|
138
|
+
// `.replaceAll(old, new)` — string-pattern form, EVERY occurrence,
|
|
139
|
+
// via the dedicated `$bf->replace_all` helper (not `$bf->replace`
|
|
140
|
+
// with a flag) — the regex-pattern form is refused upstream at
|
|
141
|
+
// the parser, same as `.replace`. See #2182.
|
|
142
|
+
const recv = emit(object)
|
|
143
|
+
const oldS = emit(args[0])
|
|
144
|
+
const newS = emit(args[1])
|
|
145
|
+
return `$bf->replace_all(${recv}, ${oldS}, ${newS})`
|
|
146
|
+
}
|
|
128
147
|
case 'repeat': {
|
|
129
148
|
const recv = emit(object)
|
|
130
149
|
const count = args.length === 0 ? '0' : emit(args[0])
|
|
@@ -82,7 +82,8 @@
|
|
|
82
82
|
* entry point `_renderBladeFilterExprPublic`.
|
|
83
83
|
*/
|
|
84
84
|
|
|
85
|
-
import {
|
|
85
|
+
import { groupBinaryOperand,
|
|
86
|
+
isStringConcatBinary,
|
|
86
87
|
type ParsedExprEmitter,
|
|
87
88
|
type HigherOrderMethod,
|
|
88
89
|
type ArrayMethod,
|
|
@@ -175,7 +176,7 @@ export class BladeFilterEmitter implements ParsedExprEmitter {
|
|
|
175
176
|
return String(value)
|
|
176
177
|
}
|
|
177
178
|
|
|
178
|
-
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string {
|
|
179
|
+
member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string {
|
|
179
180
|
// `.length` — route through `$bf->length` (handles both array element
|
|
180
181
|
// count and string char count, JS-compatibly).
|
|
181
182
|
if (property === 'length') {
|
|
@@ -208,13 +209,22 @@ export class BladeFilterEmitter implements ParsedExprEmitter {
|
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string {
|
|
211
|
-
|
|
212
|
-
|
|
212
|
+
// Preserve source grouping: a compound operand re-emitted as infix
|
|
213
|
+
// text is otherwise re-parsed under THIS language's precedence —
|
|
214
|
+
// `(count() + 2) * 3` would silently become `count + 2 * 3` (#2173).
|
|
215
|
+
const l = groupBinaryOperand(left, emit(left))
|
|
216
|
+
const r = groupBinaryOperand(right, emit(right))
|
|
213
217
|
// See the file header, divergence 8: PHP's `==`/`!=`/`===`/`!==` are
|
|
214
218
|
// NEVER emitted for JS `===`/`!==`. `$bf->eq`/`$bf->neq` are the one
|
|
215
219
|
// shared JS-strict-equality implementation.
|
|
216
220
|
if (op === '===') return `$bf->eq(${l}, ${r})`
|
|
217
221
|
if (op === '!==') return `$bf->neq(${l}, ${r})`
|
|
222
|
+
// JS `+` with a string-typed operand is CONCATENATION, not addition —
|
|
223
|
+
// PHP's `+` fatals on non-numeric strings ("Unsupported operand
|
|
224
|
+
// types", #2176). Lower to PHP's `.` concat operator.
|
|
225
|
+
if (isStringConcatBinary(op, left, right, this.isStringName)) {
|
|
226
|
+
return `${l} . ${r}`
|
|
227
|
+
}
|
|
218
228
|
const opMap: Record<string, string> = {
|
|
219
229
|
'>': '>', '<': '<', '>=': '>=', '<=': '<=',
|
|
220
230
|
'+': '+', '-': '-', '*': '*', '/': '/',
|
|
@@ -336,7 +346,7 @@ export class BladeTopLevelEmitter implements ParsedExprEmitter {
|
|
|
336
346
|
return String(value)
|
|
337
347
|
}
|
|
338
348
|
|
|
339
|
-
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string {
|
|
349
|
+
member(object: ParsedExpr, property: string, _computed: boolean, _optional: boolean, emit: (e: ParsedExpr) => string): string {
|
|
340
350
|
// `props.x` flattens to the bare context var the SSR caller binds each
|
|
341
351
|
// prop to (props arrive as individual top-level context entries, not a
|
|
342
352
|
// nested `props` hash).
|
|
@@ -405,12 +415,23 @@ export class BladeTopLevelEmitter implements ParsedExprEmitter {
|
|
|
405
415
|
}
|
|
406
416
|
|
|
407
417
|
binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string {
|
|
408
|
-
|
|
409
|
-
|
|
418
|
+
// Preserve source grouping: a compound operand re-emitted as infix
|
|
419
|
+
// text is otherwise re-parsed under THIS language's precedence —
|
|
420
|
+
// `(count() + 2) * 3` would silently become `count + 2 * 3` (#2173).
|
|
421
|
+
const l = groupBinaryOperand(left, emit(left))
|
|
422
|
+
const r = groupBinaryOperand(right, emit(right))
|
|
410
423
|
// See the file header, divergence 8: PHP's `==`/`!=`/`===`/`!==` are
|
|
411
424
|
// NEVER emitted for JS `===`/`!==`.
|
|
412
425
|
if (op === '===') return `$bf->eq(${l}, ${r})`
|
|
413
426
|
if (op === '!==') return `$bf->neq(${l}, ${r})`
|
|
427
|
+
// JS `+` with a string-typed operand is CONCATENATION, not addition —
|
|
428
|
+
// PHP's `+` fatals on non-numeric strings ("Unsupported operand
|
|
429
|
+
// types", #2176). Lower to PHP's `.` concat operator. The adapter's
|
|
430
|
+
// string-value registry catches getter/prop operands with no literal
|
|
431
|
+
// present (`firstName() + lastName()`).
|
|
432
|
+
if (isStringConcatBinary(op, left, right, n => this.ctx._isStringValueName(n))) {
|
|
433
|
+
return `${l} . ${r}`
|
|
434
|
+
}
|
|
414
435
|
const opMap: Record<string, string> = {
|
|
415
436
|
'>': '>', '<': '<', '>=': '>=', '<=': '<=',
|
|
416
437
|
'+': '+', '-': '-', '*': '*',
|
|
@@ -22,6 +22,9 @@ export const BLADE_TEMPLATE_PRIMITIVES: Record<string, PrimitiveSpec> = {
|
|
|
22
22
|
'Math.floor': { arity: 1, emit: (args) => `$bf->floor(${args[0]})` },
|
|
23
23
|
'Math.ceil': { arity: 1, emit: (args) => `$bf->ceil(${args[0]})` },
|
|
24
24
|
'Math.round': { arity: 1, emit: (args) => `$bf->round(${args[0]})` },
|
|
25
|
+
'Math.min': { arity: 2, emit: (args) => `$bf->min(${args[0]}, ${args[1]})` },
|
|
26
|
+
'Math.max': { arity: 2, emit: (args) => `$bf->max(${args[0]}, ${args[1]})` },
|
|
27
|
+
'Math.abs': { arity: 1, emit: (args) => `$bf->abs(${args[0]})` },
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
/**
|
package/src/conformance-pins.ts
CHANGED
|
@@ -89,9 +89,4 @@ export const conformancePins: ConformancePins = {
|
|
|
89
89
|
// the shape loudly instead of emitting entity-escaped markup that
|
|
90
90
|
// silently renders tags as text.
|
|
91
91
|
'dangerous-inner-html': [{ code: 'BF101', severity: 'error' }],
|
|
92
|
-
// Edge-case sweep (Priority 12): `.replaceAll` has no lowering yet —
|
|
93
|
-
// only first-occurrence `.replace` is wired to the runtime helpers.
|
|
94
|
-
// Refused with BF101 rather than reusing the first-only lowering,
|
|
95
|
-
// which would silently change semantics.
|
|
96
|
-
'string-replaceall': [{ code: 'BF101', severity: 'error' }],
|
|
97
92
|
}
|
|
@@ -14,31 +14,4 @@
|
|
|
14
14
|
|
|
15
15
|
import type { RenderDivergences } from '@barefootjs/jsx'
|
|
16
16
|
|
|
17
|
-
export const renderDivergences: RenderDivergences = {
|
|
18
|
-
'arithmetic-text':
|
|
19
|
-
'`(count() + 2) * 3` renders 10 instead of 18 — the parenthesised sub-expression loses its grouping (silent wrong arithmetic)',
|
|
20
|
-
'string-concat-plus':
|
|
21
|
-
'`\'Hello, \' + name` is emitted as PHP `+`, which fatals with "Unsupported operand types: string + string" — needs PHP\'s `.` concat',
|
|
22
|
-
'html-entity-text':
|
|
23
|
-
'`©` in JSX literal text: Hono decodes to `©`, this adapter re-emits the raw entity — same DOM, different bytes',
|
|
24
|
-
'math-methods':
|
|
25
|
-
'Math.min/max/abs over a signal render empty (only Math.floor is in the template-primitive registry)',
|
|
26
|
-
'boolean-attr-literals':
|
|
27
|
-
'camelCase boolean alias `readOnly`: Hono SSRs `readOnly="true"`, this adapter emits bare presence',
|
|
28
|
-
'camelcase-attributes':
|
|
29
|
-
'`htmlFor` is not lowered to `for` (Hono maps it)',
|
|
30
|
-
'static-attr-escape':
|
|
31
|
-
'static attribute values are not HTML-escaped (`title="Fish & Chips"` emitted raw; Hono escapes)',
|
|
32
|
-
'svg-icon':
|
|
33
|
-
'SVG camelCase presentation attrs (`strokeWidth`, `strokeLinecap`) pass through unmapped; Hono lowers to kebab-case',
|
|
34
|
-
'object-entries-map':
|
|
35
|
-
'`Object.entries(prop).map(([k, v]) => …)` renders an EMPTY list — the object-shaped prop silently produces zero iterations',
|
|
36
|
-
'nested-loop-outer-binding':
|
|
37
|
-
'nested-loop inner items carry `data-key` where the reference emits the depth-suffixed `data-key-1`',
|
|
38
|
-
'jsx-element-prop':
|
|
39
|
-
'a JSX element passed as a NON-children prop renders an empty slot — the element value is silently dropped',
|
|
40
|
-
'string-slice':
|
|
41
|
-
'`.slice()` on a STRING renders empty (array-slice helper misfires on strings)',
|
|
42
|
-
'string-trim-sided':
|
|
43
|
-
'`.trimStart()` / `.trimEnd()` render empty (no lowering)',
|
|
44
|
-
}
|
|
17
|
+
export const renderDivergences: RenderDivergences = {}
|