@tamagui/codemod-flat-values 0.0.0-bootstrap.0 → 3.0.0-beta.1093.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.
Files changed (44) hide show
  1. package/README.md +234 -1
  2. package/dist/builtInNames.mjs +14 -0
  3. package/dist/builtInNames.mjs.map +1 -0
  4. package/dist/containers.mjs +141 -0
  5. package/dist/containers.mjs.map +1 -0
  6. package/dist/convert.mjs +1233 -0
  7. package/dist/convert.mjs.map +1 -0
  8. package/dist/expressions.mjs +188 -0
  9. package/dist/expressions.mjs.map +1 -0
  10. package/dist/functionalVariants.mjs +469 -0
  11. package/dist/functionalVariants.mjs.map +1 -0
  12. package/dist/grammar.mjs +73 -0
  13. package/dist/grammar.mjs.map +1 -0
  14. package/dist/index.mjs +374 -0
  15. package/dist/index.mjs.map +1 -0
  16. package/dist/legacyConditions.mjs +293 -0
  17. package/dist/legacyConditions.mjs.map +1 -0
  18. package/dist/legacyNames.mjs +130 -0
  19. package/dist/legacyNames.mjs.map +1 -0
  20. package/dist/provenance.mjs +137 -0
  21. package/dist/provenance.mjs.map +1 -0
  22. package/dist/report.mjs +188 -0
  23. package/dist/report.mjs.map +1 -0
  24. package/dist/sheetAnatomy.mjs +200 -0
  25. package/dist/sheetAnatomy.mjs.map +1 -0
  26. package/dist/structuredNative.mjs +275 -0
  27. package/dist/structuredNative.mjs.map +1 -0
  28. package/dist/transition.mjs +257 -0
  29. package/dist/transition.mjs.map +1 -0
  30. package/package.json +35 -7
  31. package/src/builtInNames.ts +23 -0
  32. package/src/containers.ts +227 -0
  33. package/src/convert.ts +1977 -0
  34. package/src/expressions.ts +220 -0
  35. package/src/functionalVariants.ts +642 -0
  36. package/src/grammar.ts +190 -0
  37. package/src/index.ts +589 -0
  38. package/src/legacyConditions.ts +357 -0
  39. package/src/legacyNames.ts +160 -0
  40. package/src/provenance.ts +210 -0
  41. package/src/report.ts +362 -0
  42. package/src/sheetAnatomy.ts +277 -0
  43. package/src/structuredNative.ts +459 -0
  44. package/src/transition.ts +415 -0
@@ -0,0 +1,1233 @@
1
+ import { Node, SyntaxKind } from "ts-morph";
2
+ import { compact, literalTree, numericValue, runtimeType, staticLeafValue, unwrapExpression } from "./expressions.mjs";
3
+ import { assessFlatConversion, convertLegacyConditionProp, expandToLonghands, flatStringValue, mergeProgramValues, parseValue, printProgram, resolveProp, sharedPayload, shorthands, styleProps, tokenVariantProps, unitSuffix } from "./grammar.mjs";
4
+ import { isLegacyConditionName, resolveLegacyName } from "./legacyNames.mjs";
5
+ import { classifyStructuredNativeValue } from "./structuredNative.mjs";
6
+
7
+ function assessmentVerdict(assessments) {
8
+ if (assessments.some((assessment) => assessment.verdict === "ineligible")) {
9
+ return "ineligible";
10
+ }
11
+ if (assessments.some((assessment) => assessment.verdict === "needs-relocation")) {
12
+ return "needs-relocation";
13
+ }
14
+ return assessments.length ? "unknown-host" : "clean";
15
+ }
16
+ function createSite(kind, registry, containers, targets, host) {
17
+ return {
18
+ kind,
19
+ registry,
20
+ containers,
21
+ targets,
22
+ host,
23
+ members: [],
24
+ comments: /* @__PURE__ */ new Map(),
25
+ extras: [],
26
+ respelled: [],
27
+ warnings: [],
28
+ flags: [],
29
+ inventory: [],
30
+ pending: [],
31
+ assessments: [],
32
+ notes: [],
33
+ legacy: false,
34
+ index: 0
35
+ };
36
+ }
37
+ function assessProgram(site, property, modifiers) {
38
+ const targetProperty = resolveProp(property);
39
+ const assessment = assessFlatConversion({
40
+ property: targetProperty,
41
+ modifiers,
42
+ targets: site.targets,
43
+ host: site.host
44
+ }, site.registry);
45
+ if (assessment.verdict !== "clean") addAssessment(site, targetProperty, assessment);
46
+ return assessment.verdict !== "ineligible";
47
+ }
48
+ function addAssessment(site, property, assessment) {
49
+ if (assessment.verdict === "clean") return;
50
+ if (!site.assessments.some((finding) => finding.property === property && finding.verdict === assessment.verdict && JSON.stringify(finding.reasons) === JSON.stringify(assessment.reasons))) {
51
+ site.assessments.push({
52
+ property,
53
+ verdict: assessment.verdict,
54
+ reasons: assessment.reasons
55
+ });
56
+ }
57
+ }
58
+ function legacyKeysInSpread(expression) {
59
+ const names = /* @__PURE__ */ new Set();
60
+ for (const object of expression.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {
61
+ for (const property of object.getProperties()) {
62
+ if (!Node.isPropertyAssignment(property)) continue;
63
+ const name = propertyName(property.getNameNode());
64
+ if (name !== null && isLegacyConditionName(name)) names.add(name);
65
+ }
66
+ }
67
+ return [...names];
68
+ }
69
+ function pushSpread(site, expression, text) {
70
+ const keys = legacyKeysInSpread(expression);
71
+ if (keys.length) {
72
+ site.legacy = true;
73
+ addFlag(site.flags, "legacy-condition-in-spread", `"${compact(text)}" is not an inline object literal, so its ${keys.map((key) => `"${key}"`).join(", ")} ${keys.length === 1 ? "entry stays" : "entries stay"} authored`);
74
+ }
75
+ site.members.push({
76
+ type: "spread",
77
+ index: site.index++,
78
+ text,
79
+ legacy: keys.length > 0
80
+ });
81
+ }
82
+ function converted(site, report) {
83
+ return report.programs.length > 0 || site.extras.length > 0 || site.members.some((member) => member.type === "authored" && member.activated || member.type === "legacy" && !member.failed);
84
+ }
85
+ function legacyLeft(site) {
86
+ return site.members.filter((member) => member.type === "legacy" && member.failed || member.type === "spread" && member.legacy).length;
87
+ }
88
+ function isConvertedName(name) {
89
+ return name === "group" || styleProps.has(name) || tokenVariantProps.has(name) || isLegacyConditionName(name);
90
+ }
91
+ function addFlag(list, code, detail) {
92
+ if (!list.some((flag) => flag.code === code && flag.detail === detail)) {
93
+ list.push({
94
+ code,
95
+ detail
96
+ });
97
+ }
98
+ }
99
+ function addNote(site, note) {
100
+ if (!site.notes.includes(note)) site.notes.push(note);
101
+ }
102
+ const legacyPaletteStepPattern = /(?:^|[^\w-])\$?((?:gray|mauve|slate|sage|olive|sand|tomato|red|ruby|crimson|pink|plum|purple|violet|iris|indigo|blue|cyan|teal|jade|green|grass|bronze|gold|brown|orange|amber|yellow|lime|mint|sky)(?:1[0-2]|[1-9]))(?![\w-])/g;
103
+ const legacyTrueTokenPattern = /(?:^|[^\w-])\$true(?![\w-])/;
104
+ function legacyTokenWarnings(prop, values) {
105
+ const warnings = [];
106
+ if (values.some((value) => legacyTrueTokenPattern.test(value))) {
107
+ warnings.push({
108
+ code: "legacy-true-token",
109
+ detail: `${prop} spelled the \`$true\` alias, written as \`4\` because the default config aliased it there; confirm the app's tokens agree`
110
+ });
111
+ }
112
+ const names = /* @__PURE__ */ new Set();
113
+ for (const value of values) {
114
+ legacyPaletteStepPattern.lastIndex = 0;
115
+ for (const match of value.matchAll(legacyPaletteStepPattern)) names.add(match[1]);
116
+ }
117
+ if (!names.size) return warnings;
118
+ const formatted = [...names].sort().map((name) => `\`${name}\``).join(", ");
119
+ warnings.push({
120
+ code: "legacy-palette-token",
121
+ detail: `${prop} preserves ${formatted}, which @tamagui/config/v6 does not define; choose an absolute palette token or an adaptive colorN value`
122
+ });
123
+ return warnings;
124
+ }
125
+ const empty = {
126
+ payload: null,
127
+ text: null,
128
+ dynamic: false,
129
+ problem: null,
130
+ warnings: [],
131
+ blocked: null,
132
+ inventory: null
133
+ };
134
+ function interpolate(prop, text, kind, registry) {
135
+ return `\${${text}}${kind === "number" ? unitSuffix(resolveProp(prop), registry) : ""}`;
136
+ }
137
+ function classifyStatic(prop, value, registry) {
138
+ const probe = sharedPayload(prop, value, registry);
139
+ const error = probe.errors[0];
140
+ if (error || probe.payload === null) {
141
+ const flag = {
142
+ code: error?.code ?? "unsupported-legacy-value",
143
+ detail: `${prop}: ${error?.message ?? `"${String(value)}" has no flat spelling`}`
144
+ };
145
+ return {
146
+ ...empty,
147
+ problem: flag,
148
+ blocked: flag
149
+ };
150
+ }
151
+ return {
152
+ ...empty,
153
+ payload: probe.payload
154
+ };
155
+ }
156
+ function reparsesAsBase(value, registry) {
157
+ const parsed = parseValue(value, registry);
158
+ return parsed.ok && parsed.value.clauses.length === 0 && parsed.value.base === value.trim();
159
+ }
160
+ function classifyDynamic(prop, expression, registry) {
161
+ const current = unwrapExpression(expression);
162
+ const source = compact(current.getText());
163
+ const structured = classifyStructuredNativeValue(resolveProp(prop), current, source, registry);
164
+ if (structured) {
165
+ return {
166
+ ...empty,
167
+ payload: structured.payload,
168
+ blocked: structured.blocked
169
+ };
170
+ }
171
+ const tree = literalTree(current, registry);
172
+ if (tree && tree.error) {
173
+ const flag2 = {
174
+ code: tree.error.code,
175
+ detail: `${prop}: ${tree.error.message}`
176
+ };
177
+ return {
178
+ ...empty,
179
+ problem: flag2,
180
+ blocked: flag2
181
+ };
182
+ }
183
+ if (tree && tree.kind !== "nullish") {
184
+ const rewrittenTokenText = /\$(?=[\w-])/.test(source) && tree.text !== source ? tree.text : null;
185
+ return {
186
+ ...empty,
187
+ payload: interpolate(prop, tree.text, tree.kind, registry),
188
+ text: rewrittenTokenText,
189
+ dynamic: true,
190
+ warnings: legacyTokenWarnings(prop, tree.strings)
191
+ };
192
+ }
193
+ if (tree) {
194
+ const flag2 = {
195
+ code: "empty-style-value",
196
+ detail: `${prop} value "${source}" is always nullish and cannot join a program`
197
+ };
198
+ return {
199
+ ...empty,
200
+ blocked: flag2
201
+ };
202
+ }
203
+ const runtime = runtimeType(current);
204
+ if (runtime.kind === "number") {
205
+ return {
206
+ ...empty,
207
+ payload: interpolate(prop, source, "number", registry),
208
+ dynamic: true
209
+ };
210
+ }
211
+ if (runtime.kind === "string") {
212
+ const tokens = runtime.literals?.filter((literal) => literal.startsWith("$"));
213
+ if (tokens?.length) {
214
+ const flag2 = {
215
+ code: "legacy-token-constant",
216
+ detail: `${prop} value "${source}" resolves to legacy token ${tokens.map((token) => `"${token}"`).join(", ")}; migrate the constant it comes from`
217
+ };
218
+ return {
219
+ ...empty,
220
+ problem: flag2,
221
+ blocked: flag2
222
+ };
223
+ }
224
+ if (runtime.literals === null) {
225
+ return {
226
+ ...empty,
227
+ payload: interpolate(prop, source, "string", registry),
228
+ dynamic: true,
229
+ inventory: {
230
+ code: "dynamic-string-value",
231
+ detail: `${prop} value "${source}" is an open string; confirm it never holds a legacy "$token" spelling`
232
+ }
233
+ };
234
+ }
235
+ return {
236
+ ...empty,
237
+ payload: interpolate(prop, source, "string", registry),
238
+ dynamic: true
239
+ };
240
+ }
241
+ const flag = {
242
+ code: "unprovable-dynamic-value",
243
+ detail: `${prop} value "${source}" has no provable number or string type, so it cannot fold into a program`
244
+ };
245
+ return {
246
+ ...empty,
247
+ blocked: flag
248
+ };
249
+ }
250
+ function pushBase(site, prop, text, value, literalString) {
251
+ const index = site.index++;
252
+ if (literalString !== null) {
253
+ for (const warning of legacyTokenWarnings(prop, [literalString])) {
254
+ addFlag(site.warnings, warning.code, warning.detail);
255
+ }
256
+ if (literalString.includes("$")) {
257
+ site.legacy = true;
258
+ const allowed2 = assessProgram(site, prop, []);
259
+ const flat = flatStringValue(literalString, site.registry);
260
+ const problem = flat.text === null ? {
261
+ code: flat.error?.code ?? "unsupported-legacy-value",
262
+ detail: `${prop}: ${flat.error?.message ?? `${JSON.stringify(literalString)} has no flat spelling`}`
263
+ } : !reparsesAsBase(flat.text, site.registry) ? {
264
+ code: "value-reparses-as-program",
265
+ detail: `${prop} value ${JSON.stringify(flat.text)} does not read back as one flat base value`
266
+ } : null;
267
+ if (problem !== null) addFlag(site.flags, problem.code, problem.detail);
268
+ site.members.push({
269
+ type: "authored",
270
+ index,
271
+ prop,
272
+ text,
273
+ payload: allowed2 && problem === null ? flat.text : null,
274
+ dynamic: false,
275
+ blocked: problem,
276
+ token: allowed2,
277
+ activated: false
278
+ });
279
+ return;
280
+ }
281
+ if (!reparsesAsBase(literalString, site.registry)) {
282
+ const flag = {
283
+ code: "value-reparses-as-program",
284
+ detail: `${prop} value ${JSON.stringify(literalString)} does not read back as one flat base value`
285
+ };
286
+ addFlag(site.flags, flag.code, flag.detail);
287
+ site.members.push({
288
+ type: "authored",
289
+ index,
290
+ prop,
291
+ text,
292
+ payload: null,
293
+ dynamic: false,
294
+ blocked: flag,
295
+ token: false,
296
+ activated: false
297
+ });
298
+ return;
299
+ }
300
+ site.members.push({
301
+ type: "authored",
302
+ index,
303
+ prop,
304
+ text,
305
+ payload: literalString,
306
+ dynamic: false,
307
+ blocked: null,
308
+ token: false,
309
+ activated: false
310
+ });
311
+ return;
312
+ }
313
+ const number = value ? numericValue(value) : null;
314
+ if (number !== null) {
315
+ const classified2 = classifyStatic(prop, number, site.registry);
316
+ site.members.push({
317
+ type: "authored",
318
+ index,
319
+ prop,
320
+ text,
321
+ payload: classified2.payload,
322
+ dynamic: false,
323
+ blocked: classified2.blocked,
324
+ token: false,
325
+ activated: false
326
+ });
327
+ return;
328
+ }
329
+ const kind = value?.getKind();
330
+ if (value === null || kind === SyntaxKind.TrueKeyword || kind === SyntaxKind.FalseKeyword || kind === SyntaxKind.NullKeyword) {
331
+ site.members.push({
332
+ type: "authored",
333
+ index,
334
+ prop,
335
+ text,
336
+ payload: null,
337
+ dynamic: false,
338
+ blocked: {
339
+ code: "non-css-style-value",
340
+ detail: `${prop} value "${compact(text)}" is not a CSS value and cannot join a program`
341
+ },
342
+ token: false,
343
+ activated: false
344
+ });
345
+ return;
346
+ }
347
+ const classified = classifyDynamic(prop, value, site.registry);
348
+ if (classified.problem) {
349
+ site.legacy = true;
350
+ addFlag(site.flags, classified.problem.code, classified.problem.detail);
351
+ }
352
+ for (const warning of classified.warnings) {
353
+ addFlag(site.warnings, warning.code, warning.detail);
354
+ }
355
+ if (classified.inventory) {
356
+ addFlag(site.inventory, classified.inventory.code, classified.inventory.detail);
357
+ }
358
+ if (classified.text !== null) site.legacy = true;
359
+ const allowed = classified.text === null || assessProgram(site, prop, []);
360
+ site.members.push({
361
+ type: "authored",
362
+ index,
363
+ prop,
364
+ text,
365
+ payload: allowed ? classified.payload : null,
366
+ dynamic: classified.dynamic,
367
+ blocked: classified.blocked,
368
+ token: allowed && classified.text !== null,
369
+ activated: false
370
+ });
371
+ }
372
+ const sentinelMark = "";
373
+ function evaluateLegacyObject(object, rootPath) {
374
+ const leaves = [];
375
+ const visit = (current, currentPath) => {
376
+ const value = {};
377
+ for (const property of current.getProperties()) {
378
+ if (Node.isSpreadAssignment(property)) {
379
+ return {
380
+ value: null,
381
+ fatal: `spread "${compact(property.getText())}" hides legacy condition entries`
382
+ };
383
+ }
384
+ if (!Node.isPropertyAssignment(property)) {
385
+ return {
386
+ value: null,
387
+ fatal: `property "${compact(property.getText())}" is not a static assignment`
388
+ };
389
+ }
390
+ const nameNode = property.getNameNode();
391
+ if (Node.isComputedPropertyName(nameNode)) {
392
+ return {
393
+ value: null,
394
+ fatal: `computed property "${compact(nameNode.getText())}" hides the affected style property`
395
+ };
396
+ }
397
+ const name = propertyName(nameNode);
398
+ if (name === null) {
399
+ return {
400
+ value: null,
401
+ fatal: `property name "${compact(nameNode.getText())}" is not statically known`
402
+ };
403
+ }
404
+ const path = `${currentPath}.${name}`;
405
+ const initializer = unwrapExpression(property.getInitializerOrThrow());
406
+ if (Node.isObjectLiteralExpression(initializer)) {
407
+ const nested = visit(initializer, path);
408
+ if (nested.fatal) return nested;
409
+ value[name] = nested.value;
410
+ continue;
411
+ }
412
+ const leaf = staticLeafValue(initializer);
413
+ if (leaf) {
414
+ value[name] = leaf.value;
415
+ continue;
416
+ }
417
+ value[name] = `${sentinelMark}${leaves.length}${sentinelMark}`;
418
+ leaves.push({
419
+ path,
420
+ prop: name,
421
+ expression: initializer
422
+ });
423
+ }
424
+ return {
425
+ value,
426
+ fatal: null
427
+ };
428
+ };
429
+ const result = visit(object, rootPath);
430
+ return {
431
+ ...result,
432
+ leaves
433
+ };
434
+ }
435
+ function conditionProperties(value) {
436
+ const properties = /* @__PURE__ */ new Set();
437
+ const visit = (object) => {
438
+ for (const key in object) {
439
+ const child = object[key];
440
+ if (child !== null && typeof child === "object" && isLegacyConditionName(key)) {
441
+ visit(child);
442
+ continue;
443
+ }
444
+ if (!styleProps.has(key)) continue;
445
+ for (const property of expandToLonghands(key, shorthands)) properties.add(property);
446
+ }
447
+ };
448
+ visit(value);
449
+ return properties;
450
+ }
451
+ function pushLegacy(site, name, text, initializer, node) {
452
+ const index = site.index++;
453
+ site.legacy = true;
454
+ const keep = (properties2) => {
455
+ site.members.push({
456
+ type: "legacy",
457
+ index,
458
+ name,
459
+ text,
460
+ contributions: [],
461
+ properties: properties2,
462
+ failed: true
463
+ });
464
+ };
465
+ if (initializer === null || !Node.isObjectLiteralExpression(initializer)) {
466
+ addFlag(site.flags, "dynamic-legacy-condition", `"${name}" is not an inline object literal, so its entries are not statically known`);
467
+ keep(null);
468
+ return;
469
+ }
470
+ const evaluated = evaluateLegacyObject(initializer, name);
471
+ if (evaluated.fatal || evaluated.value === null) {
472
+ addFlag(site.flags, "dynamic-legacy-condition", evaluated.fatal ?? "unresolved");
473
+ keep(null);
474
+ return;
475
+ }
476
+ const properties = conditionProperties(evaluated.value);
477
+ const eligibilityStack = [{
478
+ object: evaluated.value,
479
+ path: name
480
+ }];
481
+ let hasRejectedProperty = false;
482
+ while (eligibilityStack.length > 0) {
483
+ const current = eligibilityStack.pop();
484
+ for (const prop in current.object) {
485
+ const value = current.object[prop];
486
+ const targetProp = resolveProp(prop);
487
+ if (styleProps.has(targetProp) && !isLegacyConditionName(prop)) {
488
+ const assessment = assessFlatConversion({
489
+ property: targetProp,
490
+ targets: site.targets,
491
+ host: site.host
492
+ }, site.registry);
493
+ if (assessment.verdict === "ineligible") {
494
+ addAssessment(site, targetProp, assessment);
495
+ hasRejectedProperty = true;
496
+ }
497
+ continue;
498
+ }
499
+ if (value !== null && typeof value === "object" && !Array.isArray(value) && isLegacyConditionName(prop)) {
500
+ eligibilityStack.push({
501
+ object: value,
502
+ path: `${current.path}.${prop}`
503
+ });
504
+ }
505
+ }
506
+ }
507
+ if (hasRejectedProperty) {
508
+ keep(properties);
509
+ return;
510
+ }
511
+ const unresolved = site.containers.unresolved.get(node);
512
+ if (unresolved !== void 0) {
513
+ addFlag(site.flags, unresolved.code, unresolved.detail);
514
+ keep(properties);
515
+ return;
516
+ }
517
+ const resolution = resolveLegacyName(name, site.registry);
518
+ if (!resolution.ok) {
519
+ addFlag(site.flags, resolution.code, resolution.message);
520
+ keep(properties);
521
+ return;
522
+ }
523
+ const payloads = /* @__PURE__ */ new Map();
524
+ let failed = false;
525
+ for (let index2 = 0; index2 < evaluated.leaves.length; index2++) {
526
+ const leaf = evaluated.leaves[index2];
527
+ const classified = classifyDynamic(leaf.prop, leaf.expression, site.registry);
528
+ for (const warning of classified.warnings) {
529
+ addFlag(site.warnings, warning.code, `${leaf.path}: ${warning.detail}`);
530
+ }
531
+ if (classified.payload === null) {
532
+ const flag = classified.problem ?? classified.blocked;
533
+ addFlag(site.flags, flag?.code ?? "dynamic-condition-value", `${leaf.path}: ${flag?.detail ?? "the value is not statically known"}`);
534
+ failed = true;
535
+ continue;
536
+ }
537
+ payloads.set(`${sentinelMark}${index2}${sentinelMark}`, classified.payload);
538
+ }
539
+ if (failed) {
540
+ keep(properties);
541
+ return;
542
+ }
543
+ const { canonical, replaceRoot } = resolution.resolved;
544
+ const converted2 = convertLegacyConditionProp(canonical, evaluated.value, { registry: site.registry });
545
+ if (converted2 === null) {
546
+ addFlag(site.flags, "unknown-legacy-condition", `"${name}" is not a registered legacy condition spelling`);
547
+ keep(properties);
548
+ return;
549
+ }
550
+ for (const error of converted2.errors) {
551
+ const path = error.path.startsWith(canonical) ? `${name}${error.path.slice(canonical.length)}` : error.path;
552
+ addFlag(site.flags, error.code, `${path}: ${error.message}`);
553
+ failed = true;
554
+ }
555
+ const contributions = [];
556
+ for (const contribution of converted2.contributions) {
557
+ if (!styleProps.has(contribution.prop)) {
558
+ addFlag(site.flags, "non-style-condition-entry", `${name}.${contribution.prop} is not a style property, so a flat value cannot carry it`);
559
+ failed = true;
560
+ continue;
561
+ }
562
+ const modifiers = replaceRoot ? [...replaceRoot, ...contribution.clause.modifiers.slice(1)] : contribution.clause.modifiers;
563
+ const dynamicPayload = payloads.get(contribution.clause.payload);
564
+ contributions.push({
565
+ prop: contribution.prop,
566
+ clause: {
567
+ modifiers,
568
+ payload: dynamicPayload ?? contribution.clause.payload
569
+ },
570
+ dynamic: dynamicPayload !== void 0
571
+ });
572
+ if (!assessProgram(site, contribution.prop, modifiers)) failed = true;
573
+ }
574
+ if (failed) {
575
+ keep(properties);
576
+ return;
577
+ }
578
+ site.members.push({
579
+ type: "legacy",
580
+ index,
581
+ name,
582
+ text,
583
+ contributions,
584
+ properties,
585
+ failed: false
586
+ });
587
+ }
588
+ function activationName(prop) {
589
+ return resolveProp(prop);
590
+ }
591
+ const noProperties = /* @__PURE__ */ new Set();
592
+ const legacyStatePriorities = Object.freeze({
593
+ hover: 2,
594
+ press: 3,
595
+ active: 3,
596
+ focus: 4,
597
+ "focus-visible": 4,
598
+ "focus-within": 4,
599
+ enter: 4,
600
+ disabled: 5,
601
+ exit: 5
602
+ });
603
+ function legacyStatePriority(modifiers) {
604
+ let priority = null;
605
+ for (const modifier of modifiers) {
606
+ const candidate = legacyStatePriorities[modifier];
607
+ if (candidate !== void 0 && (priority === null || candidate > priority)) {
608
+ priority = candidate;
609
+ }
610
+ }
611
+ return priority;
612
+ }
613
+ function orderedEntries(site) {
614
+ const ordered = [];
615
+ for (const member of site.members) {
616
+ if (member.type === "authored") {
617
+ if (!member.activated || member.payload === null) continue;
618
+ ordered.push({
619
+ prop: member.prop,
620
+ value: {
621
+ base: member.payload,
622
+ clauses: []
623
+ },
624
+ dynamic: member.dynamic,
625
+ index: member.index,
626
+ base: true,
627
+ from: null,
628
+ legacyStatePriority: null
629
+ });
630
+ continue;
631
+ }
632
+ if (member.type !== "legacy" || member.failed) continue;
633
+ for (const contribution of member.contributions) {
634
+ ordered.push({
635
+ prop: contribution.prop,
636
+ value: {
637
+ base: null,
638
+ clauses: [contribution.clause]
639
+ },
640
+ dynamic: contribution.dynamic,
641
+ index: member.index,
642
+ base: false,
643
+ from: member,
644
+ legacyStatePriority: legacyStatePriority(contribution.clause.modifiers)
645
+ });
646
+ }
647
+ }
648
+ const ranked = ordered.filter((entry) => entry.legacyStatePriority !== null).sort((left, right) => left.legacyStatePriority - right.legacyStatePriority || left.index - right.index);
649
+ if (ranked.length < 2) return ordered;
650
+ let rankedIndex = 0;
651
+ return ordered.map((entry) => entry.legacyStatePriority === null ? entry : ranked[rankedIndex++]);
652
+ }
653
+ function buildSlots(ordered) {
654
+ const slots = /* @__PURE__ */ new Map();
655
+ for (const entry of ordered) {
656
+ for (const property of expandToLonghands(entry.prop, shorthands)) {
657
+ const previous = slots.get(property);
658
+ const value = previous ? mergeProgramValues(previous.value, entry.value) : entry.value;
659
+ slots.delete(property);
660
+ slots.set(property, {
661
+ property,
662
+ sourceProp: entry.prop,
663
+ value,
664
+ anchor: previous ? Math.min(previous.anchor, entry.index) : entry.index,
665
+ last: previous ? Math.max(previous.last, entry.index) : entry.index,
666
+ dynamic: (previous?.dynamic ?? false) || entry.dynamic
667
+ });
668
+ }
669
+ }
670
+ return slots;
671
+ }
672
+ function barriers(site) {
673
+ const list = [];
674
+ for (const member of site.members) {
675
+ if (member.type === "spread") {
676
+ list.push({
677
+ index: member.index,
678
+ source: member.text,
679
+ bases: null,
680
+ clauses: null
681
+ });
682
+ continue;
683
+ }
684
+ if (member.type === "authored" && !member.activated) {
685
+ list.push({
686
+ index: member.index,
687
+ source: member.text,
688
+ bases: new Set(expandToLonghands(member.prop, shorthands)),
689
+ clauses: noProperties
690
+ });
691
+ continue;
692
+ }
693
+ if (member.type === "legacy" && member.failed) {
694
+ list.push({
695
+ index: member.index,
696
+ source: member.name,
697
+ bases: noProperties,
698
+ clauses: member.properties
699
+ });
700
+ }
701
+ }
702
+ return list;
703
+ }
704
+ function resolveBarriers(site, ordered, slots) {
705
+ let changed = false;
706
+ for (const slot of slots.values()) {
707
+ const contributions = ordered.filter((entry) => expandToLonghands(entry.prop, shorthands).includes(slot.property));
708
+ for (const barrier of barriers(site)) {
709
+ if (barrier.index <= slot.anchor || barrier.index >= slot.last) continue;
710
+ if (barrier.clauses === null || barrier.clauses.has(slot.property)) {
711
+ for (const entry of contributions) {
712
+ if (entry.base || entry.index < barrier.index || !entry.from) continue;
713
+ addFlag(site.flags, "condition-order-not-preservable", `"${compact(barrier.source)}" can set "${slot.property}" between the values contributing to it, so "${entry.from.name}" stays authored instead of merging`);
714
+ entry.from.failed = true;
715
+ changed = true;
716
+ }
717
+ }
718
+ if (barrier.bases === null || barrier.bases.has(slot.property)) {
719
+ for (const entry of contributions) {
720
+ if (!entry.base || entry.index < barrier.index) continue;
721
+ const authored = site.members.find((member) => member.type === "authored" && member.index === entry.index && member.activated);
722
+ if (authored && authored.type === "authored") {
723
+ authored.payload = null;
724
+ authored.blocked = {
725
+ code: "base-order-not-preservable",
726
+ detail: `"${compact(barrier.source)}" can set "${slot.property}" between the values contributing to it, so this base cannot move`
727
+ };
728
+ changed = true;
729
+ continue;
730
+ }
731
+ addFlag(site.flags, "base-order-not-preservable", `"${compact(barrier.source)}" can set "${slot.property}" between the values contributing to it, so the merged base may win where it did not before`);
732
+ }
733
+ }
734
+ }
735
+ }
736
+ return changed;
737
+ }
738
+ function assemble(site) {
739
+ let slots = /* @__PURE__ */ new Map();
740
+ for (;;) {
741
+ let changed = false;
742
+ const contributed = /* @__PURE__ */ new Set();
743
+ for (const member of site.members) {
744
+ if (member.type !== "legacy" || member.failed) continue;
745
+ for (const contribution of member.contributions) {
746
+ contributed.add(activationName(contribution.prop));
747
+ }
748
+ }
749
+ for (const member of site.members) {
750
+ if (member.type !== "authored") continue;
751
+ const name = activationName(member.prop);
752
+ member.activated = member.token && member.payload !== null || contributed.has(name);
753
+ if (!member.activated || member.payload !== null) continue;
754
+ const blocked = member.blocked;
755
+ addFlag(site.flags, blocked?.code ?? "unprovable-dynamic-value", `a legacy condition targets "${member.prop}": ${blocked?.detail ?? `its base value "${compact(member.text)}" cannot join a program`}`);
756
+ member.activated = false;
757
+ for (const other of site.members) {
758
+ if (other.type !== "legacy" || other.failed) continue;
759
+ if (other.contributions.some((one) => activationName(one.prop) === name)) {
760
+ other.failed = true;
761
+ changed = true;
762
+ }
763
+ }
764
+ }
765
+ if (changed) continue;
766
+ const ordered = orderedEntries(site);
767
+ slots = buildSlots(ordered);
768
+ if (!resolveBarriers(site, ordered, slots)) break;
769
+ }
770
+ const entries = [];
771
+ for (const member of site.members) {
772
+ if (member.type === "authored" && member.activated) continue;
773
+ if (member.type === "legacy" && !member.failed) continue;
774
+ entries.push({
775
+ index: member.index,
776
+ text: member.text
777
+ });
778
+ }
779
+ const printed = printSlots(site, slots);
780
+ entries.push(...printed.output);
781
+ entries.push(...site.extras);
782
+ entries.sort((left, right) => left.index - right.index);
783
+ return {
784
+ entries,
785
+ programs: printed.programs
786
+ };
787
+ }
788
+ function printSlots(site, slots) {
789
+ const printed = /* @__PURE__ */ new Set();
790
+ const output = [];
791
+ const programs = [];
792
+ const outputCommentRanges = [];
793
+ for (const [property, slot] of slots) {
794
+ if (printed.has(property)) continue;
795
+ const serialized = printProgram(slot.value);
796
+ const expansion = expandToLonghands(slot.sourceProp, shorthands);
797
+ const collapses = expansion.length > 0 && expansion.every((expanded) => {
798
+ const candidate = slots.get(expanded);
799
+ return candidate !== void 0 && candidate.sourceProp === slot.sourceProp && candidate.anchor === slot.anchor && candidate.dynamic === slot.dynamic && printProgram(candidate.value) === serialized;
800
+ });
801
+ const name = collapses ? slot.sourceProp : property;
802
+ if (collapses) for (const expanded of expansion) printed.add(expanded);
803
+ else printed.add(property);
804
+ const value = slot.dynamic ? `\`${serialized}\`` : JSON.stringify(serialized);
805
+ programs.push({
806
+ name,
807
+ value: serialized,
808
+ dynamic: slot.dynamic
809
+ });
810
+ const propertyText = site.kind === "styled" ? `${name}: ${value}` : `${name}=${slot.dynamic ? `{${value}}` : value}`;
811
+ output.push({
812
+ index: slot.anchor,
813
+ text: propertyText
814
+ });
815
+ outputCommentRanges.push({
816
+ outputIndex: output.length - 1,
817
+ first: slot.anchor,
818
+ last: slot.last
819
+ });
820
+ }
821
+ verify(site, slots, [...output].sort((left, right) => left.index - right.index));
822
+ if (site.kind === "styled") {
823
+ const commentedIndexes = /* @__PURE__ */ new Set();
824
+ for (const range of outputCommentRanges) {
825
+ const comments = [];
826
+ for (const [index, texts] of site.comments) {
827
+ if (index < range.first || index > range.last || commentedIndexes.has(index)) {
828
+ continue;
829
+ }
830
+ comments.push(...texts);
831
+ commentedIndexes.add(index);
832
+ }
833
+ if (comments.length) {
834
+ output[range.outputIndex].text = `${comments.join("\n")}
835
+ ${output[range.outputIndex].text}`;
836
+ }
837
+ }
838
+ }
839
+ return {
840
+ output,
841
+ programs
842
+ };
843
+ }
844
+ function sanitize(text) {
845
+ let result = "";
846
+ for (let index = 0; index < text.length; index++) {
847
+ if (text[index] !== "$" || text[index + 1] !== "{") {
848
+ result += text[index];
849
+ continue;
850
+ }
851
+ let depth = 0;
852
+ let end = index + 1;
853
+ for (; end < text.length; end++) {
854
+ if (text[end] === "{") depth++;
855
+ else if (text[end] === "}" && --depth === 0) break;
856
+ }
857
+ result += "zz";
858
+ index = end;
859
+ }
860
+ return result;
861
+ }
862
+ function verify(site, slots, output) {
863
+ const separator = site.kind === "styled" ? ": " : "=";
864
+ const reparsed = /* @__PURE__ */ new Map();
865
+ for (const entry of output) {
866
+ const split = entry.text.indexOf(separator);
867
+ const prop = entry.text.slice(0, split);
868
+ let raw = entry.text.slice(split + separator.length);
869
+ if (raw.startsWith("{")) raw = raw.slice(1, -1);
870
+ const text = sanitize(raw.slice(1, -1));
871
+ const parsed = parseValue(text, site.registry);
872
+ if (!parsed.ok) {
873
+ addFlag(site.flags, "emitted-value-invalid", `"${prop}=${text}" does not parse: ${parsed.errors.map((error) => error.message).join("; ")}`);
874
+ return;
875
+ }
876
+ for (const property of expandToLonghands(prop, shorthands)) {
877
+ const previous = reparsed.get(property);
878
+ reparsed.set(property, previous ? mergeProgramValues(previous, parsed.value) : parsed.value);
879
+ }
880
+ }
881
+ for (const [property, slot] of slots) {
882
+ const actual = reparsed.get(property);
883
+ const expected = sanitize(printProgram(slot.value));
884
+ if (actual === void 0 || sanitize(printProgram(actual)) !== expected) {
885
+ addFlag(site.flags, "emitted-program-mismatch", `"${property}" reads back as "${actual ? sanitize(printProgram(actual)) : "(missing)"}" instead of "${expected}"`);
886
+ }
887
+ }
888
+ }
889
+ function propertyName(node) {
890
+ if (Node.isIdentifier(node) || Node.isStringLiteral(node) || Node.isNumericLiteral(node)) {
891
+ return node.getText().replace(/^['"]|['"]$/g, "");
892
+ }
893
+ return null;
894
+ }
895
+ function jsxAttributeName(attribute) {
896
+ const name = attribute.getNameNode();
897
+ return Node.isIdentifier(name) ? name.getText() : null;
898
+ }
899
+ function jsxLiteralString(attribute) {
900
+ const initializer = attribute.getInitializer();
901
+ if (Node.isStringLiteral(initializer)) return initializer.getLiteralValue();
902
+ const expression = jsxExpression(attribute);
903
+ if (expression && (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression))) {
904
+ return expression.getLiteralValue();
905
+ }
906
+ return null;
907
+ }
908
+ function jsxExpression(attribute) {
909
+ const initializer = attribute.getInitializer();
910
+ if (!Node.isJsxExpression(initializer)) return null;
911
+ const expression = initializer.getExpression();
912
+ return expression ? unwrapExpression(expression) : null;
913
+ }
914
+ function isConvertedJsxAttribute(attribute) {
915
+ if (Node.isJsxSpreadAttribute(attribute)) return true;
916
+ if (!Node.isJsxAttribute(attribute)) return false;
917
+ const name = jsxAttributeName(attribute);
918
+ return !!name && isConvertedName(name);
919
+ }
920
+ function rewriteJsxSite(opening, entries) {
921
+ const attributes = opening.getAttributes();
922
+ const rendered = [];
923
+ let inserted = false;
924
+ for (const attribute of attributes) {
925
+ if (isConvertedJsxAttribute(attribute)) {
926
+ if (!inserted) {
927
+ rendered.push(...entries.map((entry) => entry.text));
928
+ inserted = true;
929
+ }
930
+ } else {
931
+ rendered.push(attribute.getText());
932
+ }
933
+ }
934
+ const source = opening.getText();
935
+ const start = opening.getStart();
936
+ const first = attributes[0];
937
+ const last = attributes[attributes.length - 1];
938
+ const prefix = source.slice(0, first.getStart() - start);
939
+ const suffix = source.slice(last.getEnd() - start);
940
+ const authoredMultiline = prefix.includes("\n") || source.slice(first.getStart() - start, last.getEnd() - start).includes("\n");
941
+ opening.replaceWithText(authoredMultiline ? `${prefix.replace(/[ \t]+$/, "")}${rendered.map((text) => ` ${text}`).join("\n")}${suffix.replace(/\n[ \t]+/, "\n")}` : `${prefix}${rendered.join(" ")}${suffix}`);
942
+ }
943
+ function containerExtras(site, declaration, index) {
944
+ const target = site.containers.targets.get(declaration);
945
+ if (target === void 0) return;
946
+ const name = target.named && target.group !== "" ? target.group : null;
947
+ const text = site.kind === "styled" ? name === null ? "container: true" : `container: ${JSON.stringify(name)}` : name === null ? "container" : `container=${JSON.stringify(name)}`;
948
+ site.legacy = true;
949
+ site.extras.push({
950
+ index,
951
+ text
952
+ });
953
+ if (target.flag !== null) addFlag(site.flags, target.flag.code, target.flag.detail);
954
+ addNote(site, `a descendant uses a legacy container-size condition on this group, so it declares a query container`);
955
+ }
956
+ function convertJsxSite(opening, registry, containers, targets, host, write = false) {
957
+ const site = createSite("jsx", registry, containers, targets, host);
958
+ const before = [];
959
+ for (const attribute of opening.getAttributes()) {
960
+ if (Node.isJsxSpreadAttribute(attribute)) {
961
+ const expression = unwrapExpression(attribute.getExpression());
962
+ if (Node.isObjectLiteralExpression(expression)) {
963
+ before.push(compact(attribute.getText()));
964
+ for (const property of expression.getProperties()) {
965
+ if (Node.isPropertyAssignment(property)) {
966
+ const name2 = propertyName(property.getNameNode());
967
+ if (name2 !== null) {
968
+ if (isConvertedName(name2)) {
969
+ pushStyledProperty(site, name2, property, `${name2}={${property.getInitializerOrThrow().getText()}}`);
970
+ } else {
971
+ site.members.push({
972
+ type: "passthrough",
973
+ index: site.index++,
974
+ text: `${name2}={${property.getInitializerOrThrow().getText()}}`
975
+ });
976
+ }
977
+ continue;
978
+ }
979
+ }
980
+ pushSpread(site, property, Node.isSpreadAssignment(property) ? `{${property.getText()}}` : `{...{ ${property.getText()} }}`);
981
+ }
982
+ continue;
983
+ }
984
+ before.push(compact(attribute.getText()));
985
+ pushSpread(site, expression, attribute.getText());
986
+ continue;
987
+ }
988
+ const name = jsxAttributeName(attribute);
989
+ if (!name) continue;
990
+ const text = compact(attribute.getText());
991
+ if (name === "group") {
992
+ before.push(text);
993
+ containerExtras(site, attribute, site.index);
994
+ site.members.push({
995
+ type: "passthrough",
996
+ index: site.index++,
997
+ text
998
+ });
999
+ continue;
1000
+ }
1001
+ if (isLegacyConditionName(name)) {
1002
+ before.push(text);
1003
+ pushLegacy(site, name, text, jsxExpression(attribute), attribute);
1004
+ continue;
1005
+ }
1006
+ if (tokenVariantProps.has(name)) {
1007
+ if (pushTokenVariant(site, name, attribute, text)) before.push(text);
1008
+ continue;
1009
+ }
1010
+ if (!styleProps.has(name)) continue;
1011
+ before.push(text);
1012
+ const literal = jsxLiteralString(attribute);
1013
+ pushBase(site, name, text, literal === null ? jsxExpression(attribute) : null, literal);
1014
+ }
1015
+ if (!site.legacy) return null;
1016
+ const { entries, programs } = assemble(site);
1017
+ const sourceFile = opening.getSourceFile();
1018
+ const report = {
1019
+ kind: "jsx",
1020
+ label: `<${opening.getTagNameNode().getText()}>`,
1021
+ line: sourceFile.getLineAndColumnAtPos(opening.getStart()).line,
1022
+ before: before.join(" "),
1023
+ after: entries.map((entry) => entry.text).join(" ") || "(no style props left)",
1024
+ programs: [...programs, ...site.respelled],
1025
+ assessments: site.assessments,
1026
+ assessmentVerdict: assessmentVerdict(site.assessments),
1027
+ warnings: site.warnings,
1028
+ flags: site.flags,
1029
+ inventory: site.inventory,
1030
+ pending: site.pending,
1031
+ notes: site.notes,
1032
+ legacyLeft: legacyLeft(site)
1033
+ };
1034
+ if (write && converted(site, report) && !site.flags.some((flag) => flag.code === "emitted-program-mismatch" || flag.code === "emitted-value-invalid")) {
1035
+ rewriteJsxSite(opening, entries);
1036
+ }
1037
+ return report;
1038
+ }
1039
+ function pushStyledProperty(site, name, property, authoredText) {
1040
+ const comments = allCommentTexts(property);
1041
+ if (comments.length) site.comments.set(site.index, comments);
1042
+ const text = authoredText ?? textWithOuterComments(property);
1043
+ const initializer = unwrapExpression(property.getInitializerOrThrow());
1044
+ if (name === "group") {
1045
+ containerExtras(site, property, site.index);
1046
+ site.members.push({
1047
+ type: "passthrough",
1048
+ index: site.index++,
1049
+ text
1050
+ });
1051
+ return;
1052
+ }
1053
+ if (isLegacyConditionName(name)) {
1054
+ pushLegacy(site, name, text, initializer, property);
1055
+ return;
1056
+ }
1057
+ if (tokenVariantProps.has(name)) {
1058
+ pushTokenVariant(site, name, property, text);
1059
+ return;
1060
+ }
1061
+ if (!styleProps.has(name)) return;
1062
+ const literal = Node.isStringLiteral(initializer) || Node.isNoSubstitutionTemplateLiteral(initializer) ? initializer.getLiteralValue() : null;
1063
+ pushBase(site, name, text, literal === null ? initializer : null, literal);
1064
+ }
1065
+ function pushTokenVariant(site, name, node, text) {
1066
+ const index = site.index++;
1067
+ const initializer = node.getInitializer();
1068
+ const value = initializer !== void 0 && Node.isJsxExpression(initializer) ? initializer.getExpression() : initializer;
1069
+ const literals = value === void 0 ? [] : [value, ...value.getDescendants()].filter((candidate) => (Node.isStringLiteral(candidate) || Node.isNoSubstitutionTemplateLiteral(candidate)) && candidate.getLiteralValue().startsWith("$"));
1070
+ if (value === void 0 || literals.length === 0) {
1071
+ site.members.push({
1072
+ type: "passthrough",
1073
+ index,
1074
+ text
1075
+ });
1076
+ return false;
1077
+ }
1078
+ const source = value.getText();
1079
+ const start = value.getStart();
1080
+ let rewritten = "";
1081
+ let cursor = start;
1082
+ for (const literal of literals) {
1083
+ let replacement = "true";
1084
+ if (literal.getLiteralValue() !== "$true") {
1085
+ const flat = flatStringValue(literal.getLiteralValue(), site.registry);
1086
+ if (flat.text === null) {
1087
+ site.legacy = true;
1088
+ addFlag(site.flags, flat.error?.code ?? "unsupported-legacy-value", `${name}: ${flat.error?.message ?? `${literal.getText()} has no flat spelling`}`);
1089
+ site.members.push({
1090
+ type: "passthrough",
1091
+ index,
1092
+ text
1093
+ });
1094
+ return true;
1095
+ }
1096
+ const quote = literal.getText()[0];
1097
+ replacement = `${quote}${flat.text}${quote}`;
1098
+ }
1099
+ rewritten += source.slice(cursor - start, literal.getStart() - start);
1100
+ rewritten += replacement;
1101
+ cursor = literal.getEnd();
1102
+ }
1103
+ rewritten += source.slice(cursor - start);
1104
+ site.legacy = true;
1105
+ const output = Node.isJsxAttribute(node) ? Node.isStringLiteral(initializer) ? rewritten === "true" ? name : `${name}=${rewritten}` : `${name}={${rewritten}}` : site.kind === "jsx" ? `${name}={${rewritten}}` : textWithOuterComments(node, `${node.getNameNode().getText()}: ${rewritten}`);
1106
+ site.members.push({
1107
+ type: "passthrough",
1108
+ index,
1109
+ text: output
1110
+ });
1111
+ site.respelled.push({
1112
+ name,
1113
+ value: rewritten,
1114
+ dynamic: literals.length !== 1 || literals[0] !== value
1115
+ });
1116
+ return true;
1117
+ }
1118
+ function convertStyleObject(object, kind, label, registry, containers, targets, host, write = false) {
1119
+ const site = createSite(kind, registry, containers, targets, host);
1120
+ const before = [];
1121
+ for (const property of object.getProperties()) {
1122
+ if (Node.isSpreadAssignment(property)) {
1123
+ const expression = unwrapExpression(property.getExpression());
1124
+ before.push(compact(property.getText()));
1125
+ if (Node.isObjectLiteralExpression(expression)) {
1126
+ for (const nested of expression.getProperties()) {
1127
+ if (Node.isPropertyAssignment(nested)) {
1128
+ const name2 = propertyName(nested.getNameNode());
1129
+ if (name2 !== null) {
1130
+ if (isConvertedName(name2)) {
1131
+ pushStyledProperty(site, name2, nested);
1132
+ } else {
1133
+ site.members.push({
1134
+ type: "passthrough",
1135
+ index: site.index++,
1136
+ text: compact(nested.getText())
1137
+ });
1138
+ }
1139
+ continue;
1140
+ }
1141
+ }
1142
+ pushSpread(site, nested, compact(nested.getText()));
1143
+ }
1144
+ continue;
1145
+ }
1146
+ pushSpread(site, expression, compact(property.getText()));
1147
+ continue;
1148
+ }
1149
+ if (!Node.isPropertyAssignment(property)) continue;
1150
+ const nameNode = property.getNameNode();
1151
+ if (Node.isComputedPropertyName(nameNode)) {
1152
+ addFlag(site.flags, "computed-property", `"${compact(nameNode.getText())}" hides the affected style property`);
1153
+ continue;
1154
+ }
1155
+ const name = propertyName(nameNode);
1156
+ if (name === null) continue;
1157
+ if (!isConvertedName(name)) continue;
1158
+ before.push(compact(property.getText()));
1159
+ pushStyledProperty(site, name, property);
1160
+ }
1161
+ if (!site.legacy) return null;
1162
+ const { entries, programs } = assemble(site);
1163
+ const sourceFile = object.getSourceFile();
1164
+ const report = {
1165
+ kind,
1166
+ label,
1167
+ line: sourceFile.getLineAndColumnAtPos(object.getStart()).line,
1168
+ before: before.join(", "),
1169
+ after: entries.map((entry) => entry.text).join(", ") || "(no style props left)",
1170
+ programs: [...programs, ...site.respelled],
1171
+ assessments: site.assessments,
1172
+ assessmentVerdict: assessmentVerdict(site.assessments),
1173
+ warnings: site.warnings,
1174
+ flags: site.flags,
1175
+ inventory: site.inventory,
1176
+ pending: site.pending,
1177
+ notes: site.notes,
1178
+ legacyLeft: legacyLeft(site)
1179
+ };
1180
+ if (write && converted(site, report) && !site.flags.some((flag) => flag.code === "emitted-program-mismatch" || flag.code === "emitted-value-invalid")) {
1181
+ rewriteStyleObject(object, entries);
1182
+ }
1183
+ return report;
1184
+ }
1185
+ function isConvertedStyledProperty(property) {
1186
+ if (Node.isSpreadAssignment(property)) return true;
1187
+ if (!Node.isPropertyAssignment(property)) return false;
1188
+ const nameNode = property.getNameNode();
1189
+ if (Node.isComputedPropertyName(nameNode)) return false;
1190
+ const name = propertyName(nameNode);
1191
+ return !!name && isConvertedName(name);
1192
+ }
1193
+ function allCommentTexts(node) {
1194
+ const comments = /* @__PURE__ */ new Map();
1195
+ for (const current of [node, ...node.getDescendants()]) {
1196
+ for (const range of [...current.getLeadingCommentRanges(), ...current.getTrailingCommentRanges()]) {
1197
+ comments.set(range.getPos(), range.getText());
1198
+ }
1199
+ }
1200
+ return [...comments.entries()].sort((left, right) => left[0] - right[0]).map((entry) => entry[1]);
1201
+ }
1202
+ function textWithOuterComments(node, text = node.getText()) {
1203
+ const comments = /* @__PURE__ */ new Map();
1204
+ for (const range of [...node.getLeadingCommentRanges(), ...node.getTrailingCommentRanges()]) {
1205
+ comments.set(range.getPos(), range.getText());
1206
+ }
1207
+ const prefix = [...comments.entries()].sort((left, right) => left[0] - right[0]).map((entry) => entry[1]);
1208
+ return [...prefix, text].join("\n ");
1209
+ }
1210
+ function rewriteStyleObject(object, entries) {
1211
+ const rendered = [];
1212
+ let inserted = false;
1213
+ for (const property of object.getProperties()) {
1214
+ if (isConvertedStyledProperty(property)) {
1215
+ if (!inserted) {
1216
+ rendered.push(...entries.map((entry) => entry.text));
1217
+ inserted = true;
1218
+ }
1219
+ } else {
1220
+ rendered.push(textWithOuterComments(property));
1221
+ }
1222
+ }
1223
+ if (rendered.length === 0) {
1224
+ object.replaceWithText("{}");
1225
+ return;
1226
+ }
1227
+ object.replaceWithText(`{
1228
+ ${rendered.map((text) => ` ${text}`).join(",\n")}
1229
+ }`);
1230
+ }
1231
+
1232
+ export { convertJsxSite, convertStyleObject, sanitize };
1233
+ //# sourceMappingURL=convert.mjs.map