@bettercms-ai/convert 0.25.0 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/cli.js +75 -45
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +73 -43
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @bettercms-ai/convert
|
|
2
2
|
|
|
3
|
+
## 0.25.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b1e5eb0: Prices and other numbers are now editable: a value written as `49` or `price={49}` in a data object, a `const`, or a component prop is bound like any other copy, and still renders the same text. `--brief` no longer writes a second `data-bcms-field` on an element, and two paths that want the same element, or a rewrite inside text another rewrite replaces, are reported as ambiguous instead of corrupting the file; a second run over converted source changes nothing.
|
|
8
|
+
- Updated dependencies [56335ff]
|
|
9
|
+
- @bettercms-ai/types@1.32.0
|
|
10
|
+
|
|
3
11
|
## 0.25.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/dist/cli.js
CHANGED
|
@@ -2715,8 +2715,9 @@ function collectSites(roots, literals) {
|
|
|
2715
2715
|
}
|
|
2716
2716
|
const bindingsAttr = node.attrs.find((a) => a.name === "bcmsBindings")?.range;
|
|
2717
2717
|
for (const attr of node.attrs) {
|
|
2718
|
-
|
|
2719
|
-
|
|
2718
|
+
const digits = attr.expression && attr.expressionRange ? attr.number : void 0;
|
|
2719
|
+
if (attr.expression && digits === void 0 || !digits && !attr.valueRange || BCMS_ATTRS.includes(attr.name)) continue;
|
|
2720
|
+
const value = norm(digits ?? attr.value);
|
|
2720
2721
|
for (const literal of wanted) {
|
|
2721
2722
|
if (value !== literal) continue;
|
|
2722
2723
|
matched.add(literal);
|
|
@@ -2724,7 +2725,7 @@ function collectSites(roots, literals) {
|
|
|
2724
2725
|
file: "",
|
|
2725
2726
|
tag: node.tag,
|
|
2726
2727
|
attrInsertAt: node.attrInsertAt,
|
|
2727
|
-
range: attr.valueRange,
|
|
2728
|
+
range: digits === void 0 ? attr.valueRange : attr.expressionRange,
|
|
2728
2729
|
inner: node.inner,
|
|
2729
2730
|
// 🔴 A COMPONENT'S ATTRIBUTE IS A PROP, and a prop is a different conversion: the value
|
|
2730
2731
|
// is rendered in another file, by an element only that file knows. @see props.ts
|
|
@@ -2832,6 +2833,8 @@ function attrsOf2(open, content) {
|
|
|
2832
2833
|
const value = attr.value;
|
|
2833
2834
|
const range = { start: attr.start ?? 0, end: attr.end ?? 0 };
|
|
2834
2835
|
const literal = value?.type === "StringLiteral";
|
|
2836
|
+
const inside = value?.type === "JSXExpressionContainer" ? value.expression : null;
|
|
2837
|
+
const numeric = inside?.type === "NumericLiteral" ? String(inside.extra.raw) : "";
|
|
2835
2838
|
return [
|
|
2836
2839
|
{
|
|
2837
2840
|
name: nameOf(attr.name),
|
|
@@ -2840,7 +2843,8 @@ function attrsOf2(open, content) {
|
|
|
2840
2843
|
valueRange: literal ? { start: (value.start ?? 0) + 1, end: (value.end ?? 0) - 1 } : null,
|
|
2841
2844
|
expression: !literal,
|
|
2842
2845
|
range,
|
|
2843
|
-
expressionRange: value?.type === "JSXExpressionContainer" ? { start: value.start ?? 0, end: value.end ?? 0 } : null
|
|
2846
|
+
expressionRange: value?.type === "JSXExpressionContainer" ? { start: value.start ?? 0, end: value.end ?? 0 } : null,
|
|
2847
|
+
...numeric ? { number: numeric } : {}
|
|
2844
2848
|
}
|
|
2845
2849
|
];
|
|
2846
2850
|
});
|
|
@@ -3316,14 +3320,21 @@ function exportedNames(ast) {
|
|
|
3316
3320
|
});
|
|
3317
3321
|
return out;
|
|
3318
3322
|
}
|
|
3323
|
+
function printed(node) {
|
|
3324
|
+
if (node?.type === "StringLiteral") return [String(node.value)];
|
|
3325
|
+
if (node?.type === "NumericLiteral") return [String(node.value), String(node.extra?.raw ?? "")];
|
|
3326
|
+
const quasis = node?.type === "TemplateLiteral" ? node.quasis ?? [] : [];
|
|
3327
|
+
const expressions = node?.expressions ?? [];
|
|
3328
|
+
return quasis.length === 1 && expressions.length === 0 ? [String(quasis[0].value.cooked ?? "")] : [];
|
|
3329
|
+
}
|
|
3319
3330
|
function propertyFor(row, literal) {
|
|
3320
3331
|
if (row?.type !== "ObjectExpression") return null;
|
|
3321
3332
|
for (const property of row.properties ?? []) {
|
|
3322
3333
|
if (property.type !== "ObjectProperty" && property.type !== "Property") continue;
|
|
3323
3334
|
const key = property.key;
|
|
3324
3335
|
const value = property.value;
|
|
3325
|
-
if (
|
|
3326
|
-
if (
|
|
3336
|
+
if (key?.type !== "Identifier") continue;
|
|
3337
|
+
if (printed(value).some((text) => norm(text) === literal)) return String(key.name);
|
|
3327
3338
|
}
|
|
3328
3339
|
return null;
|
|
3329
3340
|
}
|
|
@@ -3397,7 +3408,7 @@ function stringLiterals(ast) {
|
|
|
3397
3408
|
if (node.type !== "VariableDeclarator") return;
|
|
3398
3409
|
const id = node.id;
|
|
3399
3410
|
const init = node.init;
|
|
3400
|
-
if (id?.type !== "Identifier" || init
|
|
3411
|
+
if (id?.type !== "Identifier" || !init || printed(init).length === 0) return;
|
|
3401
3412
|
out.set(String(id.name), init);
|
|
3402
3413
|
});
|
|
3403
3414
|
return out;
|
|
@@ -3428,7 +3439,7 @@ function scalarUses(content, roots, id) {
|
|
|
3428
3439
|
}
|
|
3429
3440
|
function bindScalar(ctx, member, literals, offset) {
|
|
3430
3441
|
const rule = DIALECT_RULES[ctx.dialect];
|
|
3431
|
-
const named = [...literals].filter(([, init2]) =>
|
|
3442
|
+
const named = [...literals].filter(([, init2]) => printed(init2).some((text) => norm(text) === member.literal));
|
|
3432
3443
|
if (named.length !== 1) return { splices: [], refusal: null };
|
|
3433
3444
|
const [id, init] = named[0];
|
|
3434
3445
|
const uses = scalarUses(ctx.content, ctx.parsed.roots, id);
|
|
@@ -3643,16 +3654,17 @@ function literalTable(init) {
|
|
|
3643
3654
|
const first = elements[0];
|
|
3644
3655
|
if (!first || elements.length !== (init.elements ?? []).length) return null;
|
|
3645
3656
|
if (elements.some((element) => element.type !== first.type)) return null;
|
|
3646
|
-
if (first.
|
|
3647
|
-
|
|
3657
|
+
if (printed(first).length > 0) {
|
|
3658
|
+
if (elements.some((element) => printed(element).length === 0)) return null;
|
|
3659
|
+
return { tuple: false, rows: elements.map((element) => [norm(printed(element)[0])]) };
|
|
3648
3660
|
}
|
|
3649
3661
|
if (first.type !== "ArrayExpression") return null;
|
|
3650
3662
|
const rows = [];
|
|
3651
3663
|
for (const element of elements) {
|
|
3652
3664
|
const inner = (element.elements ?? []).filter((x) => x !== null);
|
|
3653
|
-
if (inner.length === 0 || inner.some((x) => x.
|
|
3665
|
+
if (inner.length === 0 || inner.some((x) => printed(x).length === 0)) return null;
|
|
3654
3666
|
if (inner.length !== (element.elements ?? []).length) return null;
|
|
3655
|
-
rows.push(inner.map((x) => norm(
|
|
3667
|
+
rows.push(inner.map((x) => norm(printed(x)[0])));
|
|
3656
3668
|
}
|
|
3657
3669
|
if (new Set(rows.map((row) => row.length)).size !== 1) return null;
|
|
3658
3670
|
return { tuple: true, rows };
|
|
@@ -5460,7 +5472,8 @@ function overlapping(rewrites) {
|
|
|
5460
5472
|
for (const a of rewrites) {
|
|
5461
5473
|
for (const b of rewrites) {
|
|
5462
5474
|
if (a.raw !== void 0 || b.raw !== void 0) continue;
|
|
5463
|
-
if (a
|
|
5475
|
+
if (a === b || a.key === b.key) continue;
|
|
5476
|
+
if (collide(a, b)) {
|
|
5464
5477
|
out.add(a);
|
|
5465
5478
|
out.add(b);
|
|
5466
5479
|
}
|
|
@@ -5468,6 +5481,16 @@ function overlapping(rewrites) {
|
|
|
5468
5481
|
}
|
|
5469
5482
|
return [...out];
|
|
5470
5483
|
}
|
|
5484
|
+
var writes = ({ site }) => [site.range, site.attrRange, site.where === "text" ? site.inner : null].filter((r) => r != null);
|
|
5485
|
+
function collide(a, b) {
|
|
5486
|
+
const inside = (at, spans) => spans.some((r) => r.start < at && at < r.end);
|
|
5487
|
+
const [wa, wb] = [writes(a), writes(b)];
|
|
5488
|
+
if (wa.some((x) => wb.some((y) => overlaps(x, y)))) return true;
|
|
5489
|
+
if (inside(a.site.attrInsertAt, wb) || inside(b.site.attrInsertAt, wa)) return true;
|
|
5490
|
+
const [fa, fb] = [field(a), field(b)];
|
|
5491
|
+
return a.site.attrInsertAt === b.site.attrInsertAt && !!fa && !!fb && fa !== fb;
|
|
5492
|
+
}
|
|
5493
|
+
var field = (r) => r.site.where === "prop" || r.site.where === "text" && !ownsSubtree(r.kind, r.site, r.inline) && r.site.mixed && r.site.textRange ? void 0 : declaration(r).plain[0];
|
|
5471
5494
|
function declaration(rewrite) {
|
|
5472
5495
|
const { site, path, kind, scope } = rewrite;
|
|
5473
5496
|
if (site.where === "attr" && kind !== "image") {
|
|
@@ -5482,8 +5505,8 @@ function rewriteFile(content, dialect, rewrites, imports, extra = []) {
|
|
|
5482
5505
|
const bindings = /* @__PURE__ */ new Map();
|
|
5483
5506
|
const addDeclaration = (at, add) => {
|
|
5484
5507
|
const held = attributes.get(at) ?? { plain: [], props: [] };
|
|
5485
|
-
held.plain.push(...add.plain);
|
|
5486
|
-
held.props.push(...add.props);
|
|
5508
|
+
held.plain.push(...add.plain.filter((text) => !held.plain.includes(text)));
|
|
5509
|
+
held.props.push(...add.props.filter((p) => !held.props.some((q) => JSON.stringify(q) === JSON.stringify(p))));
|
|
5487
5510
|
attributes.set(at, held);
|
|
5488
5511
|
};
|
|
5489
5512
|
for (const rewrite of rewrites) {
|
|
@@ -5906,7 +5929,8 @@ function attrsOf4(node, content) {
|
|
|
5906
5929
|
valueRange: quoted && rawStart >= 0 && attr.value !== "" ? { start: rawStart + (unquoted ? 0 : 1), end: rawStart + raw.length - (unquoted ? 0 : 1) } : null,
|
|
5907
5930
|
expression: !quoted,
|
|
5908
5931
|
range,
|
|
5909
|
-
expressionRange: !quoted && open >= 0 && close > open ? { start: open, end: close + 1 } : null
|
|
5932
|
+
expressionRange: !quoted && open >= 0 && close > open ? { start: open, end: close + 1 } : null,
|
|
5933
|
+
...attr.kind === "expression" && /^\d+(\.\d+)?$/.test(attr.value.trim()) ? { number: attr.value.trim() } : {}
|
|
5910
5934
|
}
|
|
5911
5935
|
];
|
|
5912
5936
|
});
|
|
@@ -6025,6 +6049,9 @@ function attrsOf5(node) {
|
|
|
6025
6049
|
return [{ name: `\0${name}`, value: "", valueRange: null, expression: true, expressionRange: null, range }];
|
|
6026
6050
|
}
|
|
6027
6051
|
const literal = literalValue(attr);
|
|
6052
|
+
const tag = attr.value;
|
|
6053
|
+
const raw = tag?.type === "ExpressionTag" ? tag.expression : void 0;
|
|
6054
|
+
const digits = typeof raw?.value === "number" ? String(raw.raw ?? "") : "";
|
|
6028
6055
|
return [
|
|
6029
6056
|
{
|
|
6030
6057
|
name,
|
|
@@ -6032,7 +6059,8 @@ function attrsOf5(node) {
|
|
|
6032
6059
|
valueRange: literal && literal.value !== "" ? literal.range : null,
|
|
6033
6060
|
expression: literal === null,
|
|
6034
6061
|
// Not read: svelte sections are DIALECT_UNSUPPORTED. @see componentize.ts
|
|
6035
|
-
expressionRange: null,
|
|
6062
|
+
expressionRange: digits ? { start: tag.start ?? 0, end: tag.end ?? 0 } : null,
|
|
6063
|
+
...digits ? { number: digits } : {},
|
|
6036
6064
|
range
|
|
6037
6065
|
}
|
|
6038
6066
|
];
|
|
@@ -6137,13 +6165,15 @@ var spanOf = (loc) => ({
|
|
|
6137
6165
|
function attrsOf6(node) {
|
|
6138
6166
|
return (node.props ?? []).flatMap((prop) => {
|
|
6139
6167
|
if (prop.type === DIRECTIVE && prop.name === "bind" && prop.arg?.content) {
|
|
6168
|
+
const digits = /^\d+(\.\d+)?$/.test(String(prop.exp?.content ?? "").trim()) ? String(prop.exp.content).trim() : "";
|
|
6140
6169
|
return [
|
|
6141
6170
|
{
|
|
6142
6171
|
name: prop.arg.content,
|
|
6143
6172
|
value: "",
|
|
6144
6173
|
valueRange: null,
|
|
6145
6174
|
expression: true,
|
|
6146
|
-
expressionRange: null,
|
|
6175
|
+
expressionRange: digits ? spanOf(prop.exp?.loc) : null,
|
|
6176
|
+
...digits ? { number: digits } : {},
|
|
6147
6177
|
range: spanOf(prop.loc)
|
|
6148
6178
|
}
|
|
6149
6179
|
];
|
|
@@ -6627,8 +6657,8 @@ function readPlan(value) {
|
|
|
6627
6657
|
check.optionalString(section.sectionType, `${at2}.sectionType`);
|
|
6628
6658
|
check.optionalString(section.copy, `${at2}.copy`);
|
|
6629
6659
|
if (section.fields !== void 0) {
|
|
6630
|
-
for (const [f,
|
|
6631
|
-
const shape = check.record(
|
|
6660
|
+
for (const [f, field2] of check.array(section.fields, `${at2}.fields`).entries()) {
|
|
6661
|
+
const shape = check.record(field2, `${at2}.fields[${f}]`);
|
|
6632
6662
|
check.optionalString(shape.key, `${at2}.fields[${f}].key`);
|
|
6633
6663
|
check.optionalString(shape.path, `${at2}.fields[${f}].path`);
|
|
6634
6664
|
}
|
|
@@ -6947,15 +6977,15 @@ function wire(source, candidate, form) {
|
|
|
6947
6977
|
source.remove(start, attr.range.end);
|
|
6948
6978
|
}
|
|
6949
6979
|
}
|
|
6950
|
-
for (const
|
|
6951
|
-
const control = candidate.controls.get(
|
|
6980
|
+
for (const field2 of form.fields) {
|
|
6981
|
+
const control = candidate.controls.get(field2.key);
|
|
6952
6982
|
if (candidate.foreign.has(control)) continue;
|
|
6953
6983
|
const host = candidate.wrapper.get(control) ?? control;
|
|
6954
|
-
if (!attrOf(host, "data-bcms-form-field")) source.appendLeft(host.attrInsertAt, ` data-bcms-form-field="${escapeAttr(
|
|
6984
|
+
if (!attrOf(host, "data-bcms-form-field")) source.appendLeft(host.attrInsertAt, ` data-bcms-form-field="${escapeAttr(field2.key)}"`);
|
|
6955
6985
|
const name = attrOf(control, "name");
|
|
6956
|
-
if (!name) source.appendLeft(control.attrInsertAt, ` name="${escapeAttr(
|
|
6957
|
-
else if (!name.expression && name.value !==
|
|
6958
|
-
source.overwrite(name.valueRange.start, name.valueRange.end, escapeAttr(
|
|
6986
|
+
if (!name) source.appendLeft(control.attrInsertAt, ` name="${escapeAttr(field2.key)}"`);
|
|
6987
|
+
else if (!name.expression && name.value !== field2.key && name.valueRange) {
|
|
6988
|
+
source.overwrite(name.valueRange.start, name.valueRange.end, escapeAttr(field2.key));
|
|
6959
6989
|
}
|
|
6960
6990
|
}
|
|
6961
6991
|
if (el.inner && !hasMessage(el)) {
|
|
@@ -6999,7 +7029,7 @@ async function wireForms(briefIn, sources, options_ = {}) {
|
|
|
6999
7029
|
candidates.push(candidateOf(source.path, dialect, el, imported, landmark, source.content, parsed.importAt));
|
|
7000
7030
|
}
|
|
7001
7031
|
}
|
|
7002
|
-
const holds = (c, f) => f.fields.filter((
|
|
7032
|
+
const holds = (c, f) => f.fields.filter((field2) => c.controls.has(field2.key)).length;
|
|
7003
7033
|
const byId = (c, f) => !attrOf(c.el, "data-bcms-form")?.expression && attrOf(c.el, "data-bcms-form")?.value === f.id;
|
|
7004
7034
|
const programAction = (c) => !!attrOf(c.el, "action")?.expression && calledName(exprOf(c, "action"), "bcmsFormAction") === null;
|
|
7005
7035
|
const wiredTo = (c, f) => BY_NAME.includes(c.dialect) ? calledName(exprOf(c, "data-bcms-form"), "bcmsFormId") === f.name || byId(c, f) && programAction(c) : byId(c, f);
|
|
@@ -7121,9 +7151,9 @@ async function wireForms(briefIn, sources, options_ = {}) {
|
|
|
7121
7151
|
pend2(form, "ACTION_IS_EXPRESSION", candidate.file, "its action is an expression, so this run will not replace it.");
|
|
7122
7152
|
continue;
|
|
7123
7153
|
}
|
|
7124
|
-
const misnamed = form.fields.find((
|
|
7125
|
-
const attr = attrOf(candidate.controls.get(
|
|
7126
|
-
return !!attr && attr.value !==
|
|
7154
|
+
const misnamed = form.fields.find((field2) => {
|
|
7155
|
+
const attr = attrOf(candidate.controls.get(field2.key), "name");
|
|
7156
|
+
return !!attr && attr.value !== field2.key && (attr.expression || !attr.valueRange);
|
|
7127
7157
|
});
|
|
7128
7158
|
if (misnamed) {
|
|
7129
7159
|
pend2(form, "FIELD_UNMATCHED", candidate.file, `the control for ${misnamed.key} posts under an expression, so its name cannot be set to the CMS key.`);
|
|
@@ -7203,7 +7233,7 @@ ${indent}${scriptFor(last.candidate.dialect)}`);
|
|
|
7203
7233
|
);
|
|
7204
7234
|
}
|
|
7205
7235
|
for (const { form, candidate } of matched) {
|
|
7206
|
-
const keys = form.fields.filter((
|
|
7236
|
+
const keys = form.fields.filter((field2) => candidate.foreign.has(candidate.controls.get(field2.key))).map((field2) => field2.key);
|
|
7207
7237
|
if (keys.length > 0) {
|
|
7208
7238
|
notes.push(
|
|
7209
7239
|
`form ${form.name}: ${keys.join(", ")} matched a control inside an imported component, so no data-bcms-form-field marker was written for ${keys.length === 1 ? "it" : "them"}.`
|
|
@@ -8462,7 +8492,7 @@ var inSection = (section, path) => {
|
|
|
8462
8492
|
const target = rowless(path);
|
|
8463
8493
|
return fieldPaths(section).some((fieldPath) => rowless(fieldPath) === target);
|
|
8464
8494
|
};
|
|
8465
|
-
var fieldPaths = (section) => (section.fields ?? []).map((
|
|
8495
|
+
var fieldPaths = (section) => (section.fields ?? []).map((field2) => field2.path ?? `${section.groupKey}.${field2.key ?? ""}`);
|
|
8466
8496
|
function elementIndex(roots) {
|
|
8467
8497
|
const out = /* @__PURE__ */ new Map();
|
|
8468
8498
|
const visit = (node, chain) => {
|
|
@@ -8620,8 +8650,8 @@ function componentFile(dialect, path, fromFile, content, parsed, resolved, pathP
|
|
|
8620
8650
|
const carriedDeclarations = carry.declarations.length > 0 ? `${carry.declarations.join("\n")}
|
|
8621
8651
|
` : "";
|
|
8622
8652
|
const copy = !snapshot ? "" : flat3 ? `const ${snapshot} = bcmsSectionPaths(page, bind, overrides, ${JSON.stringify(pathPrefix)}, ${JSON.stringify(pathMap)}, bindPaths);` : `const ${snapshot} = { ${key}: bcmsSection(page, bind, overrides, bindPaths) };`;
|
|
8623
|
-
const
|
|
8624
|
-
const declared = [copy,
|
|
8653
|
+
const field2 = bound > 0 ? `const ${fieldName} = ${fieldsName}({ blockId, bind, bindPaths, overrides }, ${JSON.stringify(pathPrefix)}${flat3 ? `, ${JSON.stringify(pathMap)}` : ""});` : "";
|
|
8654
|
+
const declared = [copy, field2].filter(Boolean).join("\n");
|
|
8625
8655
|
const styles = dialect === "astro" ? carriedStyles(content) : "";
|
|
8626
8656
|
if (dialect === "astro") {
|
|
8627
8657
|
return { free: [], duplicates: [], unconvertible: [], content: `---
|
|
@@ -8934,8 +8964,8 @@ function propPrefix(section) {
|
|
|
8934
8964
|
}
|
|
8935
8965
|
function exactPrefix(section) {
|
|
8936
8966
|
const prefixes = /* @__PURE__ */ new Set();
|
|
8937
|
-
for (const
|
|
8938
|
-
const { path, key } =
|
|
8967
|
+
for (const field2 of section.fields ?? []) {
|
|
8968
|
+
const { path, key } = field2;
|
|
8939
8969
|
if (typeof path !== "string" || typeof key !== "string") continue;
|
|
8940
8970
|
if (!path.endsWith(key)) return null;
|
|
8941
8971
|
prefixes.add(path.slice(0, path.length - key.length));
|
|
@@ -8947,11 +8977,11 @@ var foldKey = (remainder) => remainder.replace(/\[(\d+)\]/g, "_$1").replace(/[^a
|
|
|
8947
8977
|
function flatPrefix(section) {
|
|
8948
8978
|
const prefixes = /* @__PURE__ */ new Set();
|
|
8949
8979
|
let informative = false;
|
|
8950
|
-
for (const
|
|
8951
|
-
const { path, key } =
|
|
8980
|
+
for (const field2 of section.fields ?? []) {
|
|
8981
|
+
const { path, key } = field2;
|
|
8952
8982
|
if (typeof path !== "string" || typeof key !== "string") continue;
|
|
8953
8983
|
informative = true;
|
|
8954
|
-
const prefix = ["-", "_"].map((sep2) => `${section.groupKey}${sep2}`).find((candidate) => path.startsWith(candidate) && (typeof
|
|
8984
|
+
const prefix = ["-", "_"].map((sep2) => `${section.groupKey}${sep2}`).find((candidate) => path.startsWith(candidate) && (typeof field2.overrideKey === "string" || foldKey(path.slice(candidate.length)) === key));
|
|
8955
8985
|
if (!prefix) return null;
|
|
8956
8986
|
prefixes.add(prefix);
|
|
8957
8987
|
}
|
|
@@ -8960,15 +8990,15 @@ function flatPrefix(section) {
|
|
|
8960
8990
|
function flatPathMap(section, prefix) {
|
|
8961
8991
|
const scalars = {};
|
|
8962
8992
|
const tables = {};
|
|
8963
|
-
for (const
|
|
8964
|
-
const { path, key } =
|
|
8993
|
+
for (const field2 of section.fields ?? []) {
|
|
8994
|
+
const { path, key } = field2;
|
|
8965
8995
|
if (typeof path !== "string" || typeof key !== "string" || !path.startsWith(prefix)) continue;
|
|
8966
8996
|
const row = /^([^[]+)\[\d+\]\.(.+)$/.exec(path);
|
|
8967
8997
|
if (!row) {
|
|
8968
|
-
scalars[path] =
|
|
8998
|
+
scalars[path] = field2.overrideKey ?? key;
|
|
8969
8999
|
continue;
|
|
8970
9000
|
}
|
|
8971
|
-
const address = typeof
|
|
9001
|
+
const address = typeof field2.overrideKey === "string" ? /^([^[]+)\[\d+\]\.(.+)$/.exec(field2.overrideKey) : null;
|
|
8972
9002
|
if (!address) return null;
|
|
8973
9003
|
const table = tables[row[1]] ??= { key: address[1], columns: {} };
|
|
8974
9004
|
if (table.key !== address[1]) return null;
|
|
@@ -10833,7 +10863,7 @@ function styleEdits(before, after) {
|
|
|
10833
10863
|
// package.json
|
|
10834
10864
|
var package_default = {
|
|
10835
10865
|
name: "@bettercms-ai/convert",
|
|
10836
|
-
version: "0.25.
|
|
10866
|
+
version: "0.25.1",
|
|
10837
10867
|
type: "module",
|
|
10838
10868
|
description: "Deterministic codemod that turns an imported site's text-matched bindings into declared ones \u2014 parser offsets in, one magic-string pass out, plus a receipt of everything it could not do.",
|
|
10839
10869
|
bin: {
|
|
@@ -10866,7 +10896,7 @@ var package_default = {
|
|
|
10866
10896
|
dependencies: {
|
|
10867
10897
|
"@astrojs/compiler": "^2.13.1",
|
|
10868
10898
|
"@babel/parser": "^7.29.2",
|
|
10869
|
-
"@bettercms-ai/types": "^1.
|
|
10899
|
+
"@bettercms-ai/types": "^1.32.0",
|
|
10870
10900
|
"@vue/compiler-sfc": "^3.5.0",
|
|
10871
10901
|
"magic-string": "^0.30.21",
|
|
10872
10902
|
parse5: "^7.3.0",
|