@barefootjs/xslate 0.17.0 → 0.18.0
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/expr/array-method.d.ts +13 -1
- package/dist/adapter/expr/array-method.d.ts.map +1 -1
- package/dist/adapter/expr/emitters.d.ts +13 -10
- package/dist/adapter/expr/emitters.d.ts.map +1 -1
- package/dist/adapter/index.js +132 -85
- package/dist/adapter/lib/ir-scope.d.ts +0 -5
- package/dist/adapter/lib/ir-scope.d.ts.map +1 -1
- package/dist/adapter/memo/seed.d.ts +14 -14
- package/dist/adapter/memo/seed.d.ts.map +1 -1
- package/dist/adapter/xslate-adapter.d.ts +30 -0
- package/dist/adapter/xslate-adapter.d.ts.map +1 -1
- package/dist/build.js +132 -85
- package/dist/conformance-pins.d.ts +10 -0
- package/dist/conformance-pins.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +151 -85
- package/lib/BarefootJS/Backend/Xslate.pm +1 -1
- package/package.json +3 -3
- package/src/__tests__/xslate-adapter.test.ts +138 -91
- package/src/adapter/expr/array-method.ts +43 -1
- package/src/adapter/expr/emitters.ts +53 -23
- package/src/adapter/lib/ir-scope.ts +0 -11
- package/src/adapter/memo/seed.ts +25 -72
- package/src/adapter/xslate-adapter.ts +254 -52
- package/src/conformance-pins.ts +112 -0
- package/src/index.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -187291,23 +187291,24 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
|
|
|
187291
187291
|
import {
|
|
187292
187292
|
BaseAdapter,
|
|
187293
187293
|
isBooleanAttr,
|
|
187294
|
-
parseExpression as
|
|
187294
|
+
parseExpression as parseExpression2,
|
|
187295
187295
|
stringifyParsedExpr as stringifyParsedExpr2,
|
|
187296
187296
|
exprToString,
|
|
187297
187297
|
parseProviderObjectLiteral,
|
|
187298
187298
|
parseStyleObjectEntries,
|
|
187299
|
-
isSupported
|
|
187299
|
+
isSupported,
|
|
187300
187300
|
emitParsedExpr,
|
|
187301
187301
|
emitIRNode,
|
|
187302
187302
|
emitAttrValue,
|
|
187303
187303
|
augmentInheritedPropAccesses,
|
|
187304
187304
|
collectModuleStringConsts,
|
|
187305
|
-
isLowerableObjectRestDestructure,
|
|
187306
187305
|
lookupStaticRecordLiteral,
|
|
187307
187306
|
searchParamsLocalNames,
|
|
187308
187307
|
prepareLoweringMatchers,
|
|
187309
187308
|
queryHrefArgs,
|
|
187310
|
-
|
|
187309
|
+
isValidHelperId,
|
|
187310
|
+
sortComparatorFromArrow as sortComparatorFromArrow2,
|
|
187311
|
+
isLowerableLoopDestructure
|
|
187311
187312
|
} from "@barefootjs/jsx";
|
|
187312
187313
|
|
|
187313
187314
|
// src/adapter/boolean-result.ts
|
|
@@ -187417,13 +187418,6 @@ function collectRootScopeNodes(node) {
|
|
|
187417
187418
|
visit(node);
|
|
187418
187419
|
return out;
|
|
187419
187420
|
}
|
|
187420
|
-
function referencedVarsAreAvailable(expr, available) {
|
|
187421
|
-
for (const m of expr.matchAll(/\$([A-Za-z_]\w*)/g)) {
|
|
187422
|
-
if (!available.has(m[1]))
|
|
187423
|
-
return false;
|
|
187424
|
-
}
|
|
187425
|
-
return true;
|
|
187426
|
-
}
|
|
187427
187421
|
|
|
187428
187422
|
// src/adapter/expr/array-method.ts
|
|
187429
187423
|
import {
|
|
@@ -187593,6 +187587,13 @@ function renderFlatMapEval(recv, body, param, emit) {
|
|
|
187593
187587
|
const env = emitEvalEnvArg(body, [param], emit);
|
|
187594
187588
|
return `$bf.flat_map_eval(${recv}, '${escapePerlSingleQuote(json)}', '${param}', ${env})`;
|
|
187595
187589
|
}
|
|
187590
|
+
function renderMapEval(recv, body, param, emit) {
|
|
187591
|
+
const json = serializeParsedExpr(body);
|
|
187592
|
+
if (json === null)
|
|
187593
|
+
return null;
|
|
187594
|
+
const env = emitEvalEnvArg(body, [param], emit);
|
|
187595
|
+
return `$bf.map_eval(${recv}, '${escapePerlSingleQuote(json)}', '${param}', ${env})`;
|
|
187596
|
+
}
|
|
187596
187597
|
function renderSortMethod(recv, c) {
|
|
187597
187598
|
const keyHashes = c.keys.map((k) => {
|
|
187598
187599
|
const keyEntry = k.key.kind === "self" ? `key_kind => 'self'` : `key_kind => 'field', key => '${k.key.field}'`;
|
|
@@ -187600,7 +187601,10 @@ function renderSortMethod(recv, c) {
|
|
|
187600
187601
|
});
|
|
187601
187602
|
return `$bf.sort(${recv}, { keys => [${keyHashes.join(", ")}] })`;
|
|
187602
187603
|
}
|
|
187603
|
-
function renderFlatMethod(recv, depth) {
|
|
187604
|
+
function renderFlatMethod(recv, depth, emit) {
|
|
187605
|
+
if (typeof depth === "object") {
|
|
187606
|
+
return `$bf.flat_dynamic(${recv}, ${emit(depth.expr)})`;
|
|
187607
|
+
}
|
|
187604
187608
|
const d = depth === "infinity" ? -1 : depth;
|
|
187605
187609
|
return `$bf.flat(${recv}, ${d})`;
|
|
187606
187610
|
}
|
|
@@ -187625,10 +187629,12 @@ class XslateFilterEmitter {
|
|
|
187625
187629
|
param;
|
|
187626
187630
|
localVarMap;
|
|
187627
187631
|
isStringName;
|
|
187628
|
-
|
|
187632
|
+
onUnsupported;
|
|
187633
|
+
constructor(param, localVarMap, isStringName = () => false, onUnsupported) {
|
|
187629
187634
|
this.param = param;
|
|
187630
187635
|
this.localVarMap = localVarMap;
|
|
187631
187636
|
this.isStringName = isStringName;
|
|
187637
|
+
this.onUnsupported = onUnsupported;
|
|
187632
187638
|
}
|
|
187633
187639
|
identifier(name) {
|
|
187634
187640
|
if (name === this.param)
|
|
@@ -187699,6 +187705,7 @@ class XslateFilterEmitter {
|
|
|
187699
187705
|
return `(${l} // ${r})`;
|
|
187700
187706
|
}
|
|
187701
187707
|
callbackMethod(method, object, _arrow, _restArgs, emit) {
|
|
187708
|
+
this.onUnsupported?.(`Filter predicate contains a nested '.${method}(...)' callback, which has no Kolon scalar form`, `Rewrite the predicate without a nested callback method, or add /* @client */ for client-only evaluation (no SSR).`);
|
|
187702
187709
|
return emit(object);
|
|
187703
187710
|
}
|
|
187704
187711
|
arrayLiteral(elements, emit) {
|
|
@@ -187708,7 +187715,7 @@ class XslateFilterEmitter {
|
|
|
187708
187715
|
return renderArrayMethod(method, object, args, emit);
|
|
187709
187716
|
}
|
|
187710
187717
|
flatMethod(object, depth, emit) {
|
|
187711
|
-
return renderFlatMethod(emit(object), depth);
|
|
187718
|
+
return renderFlatMethod(emit(object), depth, emit);
|
|
187712
187719
|
}
|
|
187713
187720
|
conditional(_test, _consequent, _alternate) {
|
|
187714
187721
|
return "1";
|
|
@@ -187859,6 +187866,13 @@ class XslateTopLevelEmitter {
|
|
|
187859
187866
|
this.ctx._recordExprBF101(`'.flatMap(...)' projection is outside the Xslate adapter's evaluable surface`, `Pre-compute the projected array, or move this position to a '/* @client */' boundary.`);
|
|
187860
187867
|
return "''";
|
|
187861
187868
|
}
|
|
187869
|
+
if (method === "map") {
|
|
187870
|
+
const evalForm = renderMapEval(recv, body, params[0], emit);
|
|
187871
|
+
if (evalForm !== null)
|
|
187872
|
+
return evalForm;
|
|
187873
|
+
this.ctx._recordExprBF101(`'.map(...)' projection is outside the Xslate adapter's evaluable surface`, `Pre-compute the projected array, or move this position to a '/* @client */' boundary.`);
|
|
187874
|
+
return "''";
|
|
187875
|
+
}
|
|
187862
187876
|
return recv;
|
|
187863
187877
|
}
|
|
187864
187878
|
_emitPredicateCallback(call, arrayExpr, emit) {
|
|
@@ -187901,7 +187915,7 @@ class XslateTopLevelEmitter {
|
|
|
187901
187915
|
return renderArrayMethod(method, object, args, emit);
|
|
187902
187916
|
}
|
|
187903
187917
|
flatMethod(object, depth, emit) {
|
|
187904
|
-
return renderFlatMethod(emit(object), depth);
|
|
187918
|
+
return renderFlatMethod(emit(object), depth, emit);
|
|
187905
187919
|
}
|
|
187906
187920
|
conditional(test, consequent, alternate, emit) {
|
|
187907
187921
|
return `(${emit(test)} ? ${emit(consequent)} : ${emit(alternate)})`;
|
|
@@ -187932,8 +187946,8 @@ class XslateTopLevelEmitter {
|
|
|
187932
187946
|
unsupported(_raw, _reason) {
|
|
187933
187947
|
return "''";
|
|
187934
187948
|
}
|
|
187935
|
-
objectLiteral(
|
|
187936
|
-
return "''";
|
|
187949
|
+
objectLiteral(properties, _raw, _emit) {
|
|
187950
|
+
return properties.length === 0 ? "{}" : "''";
|
|
187937
187951
|
}
|
|
187938
187952
|
}
|
|
187939
187953
|
|
|
@@ -188092,9 +188106,7 @@ function recordIndexAccessToKolon(ctx, val) {
|
|
|
188092
188106
|
// src/adapter/memo/seed.ts
|
|
188093
188107
|
import {
|
|
188094
188108
|
collectContextConsumers,
|
|
188095
|
-
|
|
188096
|
-
isSupported,
|
|
188097
|
-
parseExpression as parseExpression2
|
|
188109
|
+
computeSsrSeedPlan
|
|
188098
188110
|
} from "@barefootjs/jsx";
|
|
188099
188111
|
function contextDefaultKolon(c) {
|
|
188100
188112
|
const d = c.defaultValue;
|
|
@@ -188115,44 +188127,22 @@ function generateContextConsumerSeed(ir) {
|
|
|
188115
188127
|
`;
|
|
188116
188128
|
}
|
|
188117
188129
|
function generateDerivedMemoSeed(ctx, ir) {
|
|
188118
|
-
const
|
|
188119
|
-
const signals = ir.metadata.signals ?? [];
|
|
188120
|
-
if (memos.length === 0 && signals.length === 0)
|
|
188121
|
-
return "";
|
|
188122
|
-
const available = new Set(ir.metadata.propsParams.map((p) => p.name));
|
|
188130
|
+
const plan = ir.metadata.ssrSeedPlan ?? computeSsrSeedPlan(ir.metadata);
|
|
188123
188131
|
const lines = [];
|
|
188124
|
-
for (const
|
|
188125
|
-
|
|
188126
|
-
|
|
188127
|
-
|
|
188128
|
-
|
|
188129
|
-
|
|
188130
|
-
|
|
188131
|
-
|
|
188132
|
-
|
|
188133
|
-
if (body !== null) {
|
|
188134
|
-
const kolon = tryLowerToKolon(ctx, body, available);
|
|
188135
|
-
const refsSelf = kolon !== null && new RegExp(`\\$${memo.name}\\b`).test(kolon);
|
|
188136
|
-
if (kolon !== null && !refsSelf)
|
|
188137
|
-
lines.push(`: my $${memo.name} = ${kolon};`);
|
|
188138
|
-
}
|
|
188139
|
-
available.add(memo.name);
|
|
188132
|
+
for (const step of plan.steps) {
|
|
188133
|
+
if (step.kind !== "derived")
|
|
188134
|
+
continue;
|
|
188135
|
+
const kolon = ctx.convertExpressionToKolon(step.expr, step.parsed);
|
|
188136
|
+
if (kolon === "" || !/\$[A-Za-z_]\w*/.test(kolon))
|
|
188137
|
+
continue;
|
|
188138
|
+
if (new RegExp(`\\$${step.name}\\b`).test(kolon))
|
|
188139
|
+
continue;
|
|
188140
|
+
lines.push(`: my $${step.name} = ${kolon};`);
|
|
188140
188141
|
}
|
|
188141
188142
|
return lines.length > 0 ? lines.join(`
|
|
188142
188143
|
`) + `
|
|
188143
188144
|
` : "";
|
|
188144
188145
|
}
|
|
188145
|
-
function tryLowerToKolon(ctx, expr, available) {
|
|
188146
|
-
const trimmed = expr.trim();
|
|
188147
|
-
if (!trimmed)
|
|
188148
|
-
return null;
|
|
188149
|
-
if (!isSupported(parseExpression2(trimmed)).supported)
|
|
188150
|
-
return null;
|
|
188151
|
-
const kolon = ctx.convertExpressionToKolon(trimmed);
|
|
188152
|
-
if (kolon === "" || !/\$[A-Za-z_]\w*/.test(kolon))
|
|
188153
|
-
return null;
|
|
188154
|
-
return referencedVarsAreAvailable(kolon, available) ? kolon : null;
|
|
188155
|
-
}
|
|
188156
188146
|
|
|
188157
188147
|
// src/adapter/value/parsed-literal.ts
|
|
188158
188148
|
import { evalStringArrayJoin } from "@barefootjs/jsx";
|
|
@@ -188188,6 +188178,17 @@ function collectStringValueNames(ir) {
|
|
|
188188
188178
|
}
|
|
188189
188179
|
|
|
188190
188180
|
// src/adapter/xslate-adapter.ts
|
|
188181
|
+
function kolonSegmentAccessor(base, segments) {
|
|
188182
|
+
let expr = base;
|
|
188183
|
+
for (const seg of segments) {
|
|
188184
|
+
expr += seg.kind === "field" ? seg.isIdent ? `.${seg.key}` : `[${kolonHashKey(seg.key)}]` : `[${seg.index}]`;
|
|
188185
|
+
}
|
|
188186
|
+
return expr;
|
|
188187
|
+
}
|
|
188188
|
+
function kolonStringLiteral(s) {
|
|
188189
|
+
return `'${escapeKolonSingleQuoted(s)}'`;
|
|
188190
|
+
}
|
|
188191
|
+
|
|
188191
188192
|
class XslateAdapter extends BaseAdapter {
|
|
188192
188193
|
name = "xslate";
|
|
188193
188194
|
extension = ".tx";
|
|
@@ -188452,24 +188453,41 @@ ${whenTrue}
|
|
|
188452
188453
|
return `<: $bf.comment("cond-start:${condId}") | mark_raw :>${content}<: $bf.comment("cond-end:${condId}") | mark_raw :>`;
|
|
188453
188454
|
}
|
|
188454
188455
|
renderLoop(loop) {
|
|
188455
|
-
if (loop.clientOnly)
|
|
188456
|
-
return ""
|
|
188456
|
+
if (loop.clientOnly) {
|
|
188457
|
+
return `<: $bf.comment("loop:${loop.markerId}") | mark_raw :><: $bf.comment("/loop:${loop.markerId}") | mark_raw :>`;
|
|
188458
|
+
}
|
|
188457
188459
|
const destructure = !!(loop.paramBindings && loop.paramBindings.length > 0);
|
|
188458
|
-
const supportableDestructure = destructure &&
|
|
188460
|
+
const supportableDestructure = destructure && isLowerableLoopDestructure(loop);
|
|
188459
188461
|
if (destructure && !supportableDestructure) {
|
|
188460
188462
|
this.errors.push({
|
|
188461
188463
|
code: "BF104",
|
|
188462
188464
|
severity: "error",
|
|
188463
|
-
message: `Loop callback uses
|
|
188465
|
+
message: `Loop callback uses a destructure pattern (\`${loop.param}\`) that the Xslate adapter cannot lower — see the diagnostic detail for the specific shape.`,
|
|
188464
188466
|
loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
188465
188467
|
suggestion: {
|
|
188466
188468
|
message: `Options:
|
|
188467
|
-
` + ` 1.
|
|
188468
|
-
` + ` 2.
|
|
188469
|
-
` + ` 3.
|
|
188469
|
+
` + ` 1. If this is an object-rest binding (\`{ ...rest }\`), only reading \`rest.field\` or spreading \`{...rest}\` onto an intrinsic element lowers — other uses (passing \`rest\` to a function, rendering it as text) need the client runtime.
|
|
188470
|
+
` + ` 2. If this is chained \`.filter().map(({ ... }) => ...)\`, hoist the destructure into a variable inside the callback body instead.
|
|
188471
|
+
` + ` 3. Mark the loop position as @client-only so the destructure runs in JS on the client.
|
|
188472
|
+
` + ` 4. Move the loop into a primitive that the adapter registers explicitly.`
|
|
188470
188473
|
}
|
|
188471
188474
|
});
|
|
188472
188475
|
}
|
|
188476
|
+
const arrayName = loop.array.trim();
|
|
188477
|
+
if (/^[A-Za-z_$][\w$]*$/.test(arrayName)) {
|
|
188478
|
+
const arrayConst = (this.localConstants ?? []).find((c) => c.name === arrayName);
|
|
188479
|
+
if (arrayConst && !arrayConst.isModule && this._resolveLiteralConst(arrayName) === null) {
|
|
188480
|
+
this.errors.push({
|
|
188481
|
+
code: "BF101",
|
|
188482
|
+
severity: "error",
|
|
188483
|
+
message: `Loop array \`${arrayName}\` is a local computed value (\`${arrayConst.value}\`) that the Xslate adapter cannot bind as a template variable — only numeric/string-literal locals inline at their use site.`,
|
|
188484
|
+
loc: loop.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
188485
|
+
suggestion: {
|
|
188486
|
+
message: "Pre-compute the array server-side and pass it as a prop, or mark the loop position as @client-only so it runs in JS on the client."
|
|
188487
|
+
}
|
|
188488
|
+
});
|
|
188489
|
+
}
|
|
188490
|
+
}
|
|
188473
188491
|
const rawArray = this.convertExpressionToKolon(loop.array);
|
|
188474
188492
|
let array = rawArray;
|
|
188475
188493
|
if (loop.sortComparator) {
|
|
@@ -188491,7 +188509,15 @@ ${whenTrue}
|
|
|
188491
188509
|
}
|
|
188492
188510
|
if (supportableDestructure) {
|
|
188493
188511
|
for (const b of loop.paramBindings ?? []) {
|
|
188494
|
-
|
|
188512
|
+
const parent = kolonSegmentAccessor(`$${loopVar}`, b.segments ?? []);
|
|
188513
|
+
if (b.rest?.kind === "object") {
|
|
188514
|
+
const exclude = b.rest.exclude.map((k) => kolonStringLiteral(k.key)).join(", ");
|
|
188515
|
+
indexLocalLines.push(`: my $${b.name} = $bf.omit(${parent}, [${exclude}]);`);
|
|
188516
|
+
} else if (b.rest?.kind === "array") {
|
|
188517
|
+
indexLocalLines.push(`: my $${b.name} = $bf.slice(${parent}, ${b.rest.from}, nil);`);
|
|
188518
|
+
} else {
|
|
188519
|
+
indexLocalLines.push(`: my $${b.name} = ${kolonSegmentAccessor(`$${loopVar}`, b.segments ?? [])};`);
|
|
188520
|
+
}
|
|
188495
188521
|
}
|
|
188496
188522
|
}
|
|
188497
188523
|
const prevInLoop = this.inLoop;
|
|
@@ -188547,8 +188573,32 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188547
188573
|
emitBooleanShorthand: (_value, name) => `${kolonHashKey(name)} => 1`,
|
|
188548
188574
|
emitJsxChildren: () => ""
|
|
188549
188575
|
};
|
|
188576
|
+
componentPropSegmentEntries(segments) {
|
|
188577
|
+
const last = segments[segments.length - 1];
|
|
188578
|
+
if (last && last.kind === "entries")
|
|
188579
|
+
return last.parts;
|
|
188580
|
+
const seg = { kind: "entries", parts: [] };
|
|
188581
|
+
segments.push(seg);
|
|
188582
|
+
return seg.parts;
|
|
188583
|
+
}
|
|
188584
|
+
combineComponentPropSegments(segments) {
|
|
188585
|
+
let acc = null;
|
|
188586
|
+
for (const seg of segments) {
|
|
188587
|
+
if (seg.kind === "entries") {
|
|
188588
|
+
if (seg.parts.length === 0)
|
|
188589
|
+
continue;
|
|
188590
|
+
const text = `{ ${seg.parts.join(", ")} }`;
|
|
188591
|
+
acc = acc === null ? text : `${acc}.merge(${text})`;
|
|
188592
|
+
} else {
|
|
188593
|
+
const text = `(${seg.expr} // {})`;
|
|
188594
|
+
acc = acc === null ? text : `${acc}.merge(${text})`;
|
|
188595
|
+
}
|
|
188596
|
+
}
|
|
188597
|
+
return acc ?? "{}";
|
|
188598
|
+
}
|
|
188550
188599
|
renderComponent(comp) {
|
|
188551
|
-
const
|
|
188600
|
+
const segments = [{ kind: "entries", parts: [] }];
|
|
188601
|
+
const currentEntries = () => this.componentPropSegmentEntries(segments);
|
|
188552
188602
|
for (const p of comp.props) {
|
|
188553
188603
|
if ((p.name.match(/^on[A-Z]/) || p.name === "ref") && p.value.kind === "expression")
|
|
188554
188604
|
continue;
|
|
@@ -188556,27 +188606,19 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188556
188606
|
const trimmed = p.value.expr.trim();
|
|
188557
188607
|
if (this.propsObjectName && this.propsObjectName === trimmed) {
|
|
188558
188608
|
for (const pp of this.propsParams) {
|
|
188559
|
-
|
|
188609
|
+
currentEntries().push(`${pp.name} => $${pp.name}`);
|
|
188560
188610
|
}
|
|
188561
188611
|
continue;
|
|
188562
188612
|
}
|
|
188563
|
-
|
|
188564
|
-
code: "BF101",
|
|
188565
|
-
severity: "error",
|
|
188566
|
-
message: `Spread props (\`{...${trimmed}}\`) on a child component cannot be lowered to Kolon — Kolon hashref method args can't splat a runtime hash into named entries.`,
|
|
188567
|
-
loc: comp.loc ?? { file: this.componentName + ".tsx", start: { line: 1, column: 0 }, end: { line: 1, column: 0 } },
|
|
188568
|
-
suggestion: {
|
|
188569
|
-
message: "Pass the child component its props explicitly rather than spreading a runtime object."
|
|
188570
|
-
}
|
|
188571
|
-
});
|
|
188613
|
+
segments.push({ kind: "spread", expr: this.convertExpressionToKolon(p.value.expr) });
|
|
188572
188614
|
continue;
|
|
188573
188615
|
}
|
|
188574
188616
|
const lowered = emitAttrValue(p.value, this.componentPropEmitter, p.name);
|
|
188575
188617
|
if (lowered)
|
|
188576
|
-
|
|
188618
|
+
currentEntries().push(lowered);
|
|
188577
188619
|
}
|
|
188578
188620
|
if (comp.slotId && !this.inLoop) {
|
|
188579
|
-
|
|
188621
|
+
currentEntries().push(`_bf_slot => '${comp.slotId}'`);
|
|
188580
188622
|
}
|
|
188581
188623
|
const tplName = this.toTemplateName(comp.name);
|
|
188582
188624
|
const effectiveChildren = comp.children.length > 0 ? comp.children : resolveJsxChildrenProp(comp.props);
|
|
@@ -188586,11 +188628,12 @@ ${childrenUnderLoop}` : childrenUnderLoop;
|
|
|
188586
188628
|
const childrenBody = this.renderChildren(effectiveChildren);
|
|
188587
188629
|
this.inLoop = prevInLoop;
|
|
188588
188630
|
const macroName = `bf_children_${comp.slotId ?? "c" + this.childrenCaptureCounter++}`;
|
|
188589
|
-
|
|
188590
|
-
const
|
|
188591
|
-
return `<: macro ${macroName} -> () { :>${childrenBody}<: } :><: $bf.render_child('${tplName}',
|
|
188631
|
+
currentEntries().push(`children => ${macroName}()`);
|
|
188632
|
+
const dict = this.combineComponentPropSegments(segments);
|
|
188633
|
+
return `<: macro ${macroName} -> () { :>${childrenBody}<: } :><: $bf.render_child('${tplName}', ${dict}) | mark_raw :>`;
|
|
188592
188634
|
}
|
|
188593
|
-
const
|
|
188635
|
+
const isEmpty = segments.every((s) => s.kind === "entries" && s.parts.length === 0);
|
|
188636
|
+
const hashEntries = isEmpty ? "" : `, ${this.combineComponentPropSegments(segments)}`;
|
|
188594
188637
|
return `<: $bf.render_child('${tplName}'${hashEntries}) | mark_raw :>`;
|
|
188595
188638
|
}
|
|
188596
188639
|
childrenCaptureCounter = 0;
|
|
@@ -188709,7 +188752,7 @@ ${name}="<: ${val} :>"
|
|
|
188709
188752
|
if (localConst?.value !== undefined) {
|
|
188710
188753
|
const initTrimmed = localConst.value.trim();
|
|
188711
188754
|
if (!/^[A-Za-z_$][\w$]*$/.test(initTrimmed)) {
|
|
188712
|
-
const resolved = conditionalSpreadToKolon(this.spreadCtx,
|
|
188755
|
+
const resolved = conditionalSpreadToKolon(this.spreadCtx, parseExpression2(initTrimmed));
|
|
188713
188756
|
if (resolved !== null) {
|
|
188714
188757
|
return `<: $bf.spread_attrs(${resolved}) | mark_raw :>`;
|
|
188715
188758
|
}
|
|
@@ -188727,7 +188770,7 @@ ${name}="<: ${val} :>"
|
|
|
188727
188770
|
if (!entries)
|
|
188728
188771
|
return null;
|
|
188729
188772
|
for (const e of entries) {
|
|
188730
|
-
if (e.kind === "expr" && !
|
|
188773
|
+
if (e.kind === "expr" && !isSupported(parseExpression2(e.expr)).supported)
|
|
188731
188774
|
return null;
|
|
188732
188775
|
}
|
|
188733
188776
|
return entries.map((e) => e.kind === "literal" ? `${this.escapeAttrText(e.cssKey)}:${this.escapeAttrText(e.value)}` : `${this.escapeAttrText(e.cssKey)}:<: ${this.convertExpressionToKolon(e.expr)} :>`).join(";");
|
|
@@ -188763,7 +188806,7 @@ ${name}="<: ${val} :>"
|
|
|
188763
188806
|
return `${BF_COND}="${condId}"`;
|
|
188764
188807
|
}
|
|
188765
188808
|
renderKolonFilterExpr(expr, param, localVarMap = new Map) {
|
|
188766
|
-
return emitParsedExpr(expr, new XslateFilterEmitter(param, localVarMap, (n) => this._isStringValueName(n)));
|
|
188809
|
+
return emitParsedExpr(expr, new XslateFilterEmitter(param, localVarMap, (n) => this._isStringValueName(n), (message, reason) => this._recordExprBF101(message, reason)));
|
|
188767
188810
|
}
|
|
188768
188811
|
convertTemplateLiteralPartsToKolon(literalParts) {
|
|
188769
188812
|
const parts = [];
|
|
@@ -188808,8 +188851,8 @@ ${name}="<: ${val} :>"
|
|
|
188808
188851
|
const hasTaggedTemplate = /[A-Za-z_$][\w$]*\s*`/.test(probe);
|
|
188809
188852
|
if (!startsAsObjectLiteral && !hasTaggedTemplate)
|
|
188810
188853
|
return false;
|
|
188811
|
-
const parsed =
|
|
188812
|
-
const support =
|
|
188854
|
+
const parsed = parseExpression2(expr.trim());
|
|
188855
|
+
const support = isSupported(parsed);
|
|
188813
188856
|
if (parsed.kind !== "unsupported" && support.supported)
|
|
188814
188857
|
return false;
|
|
188815
188858
|
const reason = support.reason ?? (parsed.kind === "unsupported" ? parsed.reason : undefined);
|
|
@@ -188856,7 +188899,7 @@ ${reason}` : "";
|
|
|
188856
188899
|
const trimmed = expr.trim();
|
|
188857
188900
|
if (trimmed === "")
|
|
188858
188901
|
return "''";
|
|
188859
|
-
parsed =
|
|
188902
|
+
parsed = parseExpression2(trimmed);
|
|
188860
188903
|
}
|
|
188861
188904
|
if (parsed.kind === "call") {
|
|
188862
188905
|
for (const matcher of this._loweringMatchers) {
|
|
@@ -188865,9 +188908,13 @@ ${reason}` : "";
|
|
|
188865
188908
|
const qArgs = queryHrefArgs(node, (n) => this.renderParsedExprToKolon(n));
|
|
188866
188909
|
return `$bf.query(${qArgs.join(", ")})`;
|
|
188867
188910
|
}
|
|
188911
|
+
if (node?.kind === "helper-call" && isValidHelperId(node.helper)) {
|
|
188912
|
+
const argsX = node.args.map((a) => this.renderParsedExprToKolon(a));
|
|
188913
|
+
return `$bf.${node.helper}(${argsX.join(", ")})`;
|
|
188914
|
+
}
|
|
188868
188915
|
}
|
|
188869
188916
|
}
|
|
188870
|
-
const support =
|
|
188917
|
+
const support = isSupported(parsed);
|
|
188871
188918
|
if (!support.supported) {
|
|
188872
188919
|
this.errors.push({
|
|
188873
188920
|
code: "BF101",
|
|
@@ -188895,7 +188942,7 @@ Options:
|
|
|
188895
188942
|
return this.stringValueNames.has(name);
|
|
188896
188943
|
}
|
|
188897
188944
|
parseUndefinedAlternateTernary(expr) {
|
|
188898
|
-
const parsed =
|
|
188945
|
+
const parsed = parseExpression2(expr.trim());
|
|
188899
188946
|
if (parsed?.kind !== "conditional")
|
|
188900
188947
|
return null;
|
|
188901
188948
|
const alt = parsed.alternate;
|
|
@@ -188964,7 +189011,26 @@ Options:
|
|
|
188964
189011
|
}
|
|
188965
189012
|
}
|
|
188966
189013
|
var xslateAdapter = new XslateAdapter;
|
|
189014
|
+
// src/conformance-pins.ts
|
|
189015
|
+
var conformancePins = {
|
|
189016
|
+
"static-array-children": [{ code: "BF103", severity: "error" }],
|
|
189017
|
+
"todo-app": [{ code: "BF103", severity: "error" }],
|
|
189018
|
+
"todo-app-ssr": [{ code: "BF103", severity: "error" }],
|
|
189019
|
+
"static-array-from-props": [{ code: "BF101", severity: "error" }],
|
|
189020
|
+
"static-array-from-props-with-component": [
|
|
189021
|
+
{ code: "BF103", severity: "error" },
|
|
189022
|
+
{ code: "BF101", severity: "error" }
|
|
189023
|
+
],
|
|
189024
|
+
"filter-nested-callback-predicate": [
|
|
189025
|
+
{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2038" }
|
|
189026
|
+
],
|
|
189027
|
+
"filter-nested-find-predicate": [
|
|
189028
|
+
{ code: "BF101", severity: "error", issue: "https://github.com/piconic-ai/barefootjs/issues/2038" }
|
|
189029
|
+
],
|
|
189030
|
+
"array-map-function-reference": [{ code: "BF101", severity: "error" }]
|
|
189031
|
+
};
|
|
188967
189032
|
export {
|
|
188968
189033
|
xslateAdapter,
|
|
189034
|
+
conformancePins,
|
|
188969
189035
|
XslateAdapter
|
|
188970
189036
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/xslate",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Text::Xslate (Kolon) adapter for BarefootJS — compiles IR to .tx templates and ships the Xslate rendering backend; runs under any PSGI/Plack app",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,14 +55,14 @@
|
|
|
55
55
|
"directory": "packages/adapter-xslate"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@barefootjs/shared": "0.
|
|
58
|
+
"@barefootjs/shared": "0.18.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@barefootjs/jsx": ">=0.2.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@barefootjs/adapter-tests": "0.1.0",
|
|
65
|
-
"@barefootjs/jsx": "0.
|
|
65
|
+
"@barefootjs/jsx": "0.18.0",
|
|
66
66
|
"typescript": "^5.0.0"
|
|
67
67
|
}
|
|
68
68
|
}
|