@atlaskit/eslint-plugin-platform 2.9.1 → 2.9.3

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 (35) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/index.js +15 -3
  3. package/dist/cjs/rules/compiled/expand-motion-shorthand/index.js +281 -0
  4. package/dist/cjs/rules/compiled/no-css-prop-in-object-spread/index.js +162 -0
  5. package/dist/cjs/rules/compiled/use-motion-token-values/index.js +506 -0
  6. package/dist/cjs/rules/editor-example-type-import-required/index.js +321 -0
  7. package/dist/cjs/rules/no-xcss-in-cx/index.js +221 -0
  8. package/dist/cjs/rules/visit-example-type-import-required/index.js +23 -13
  9. package/dist/es2019/index.js +15 -3
  10. package/dist/es2019/rules/compiled/expand-motion-shorthand/index.js +239 -0
  11. package/dist/es2019/rules/compiled/no-css-prop-in-object-spread/index.js +136 -0
  12. package/dist/es2019/rules/compiled/use-motion-token-values/index.js +444 -0
  13. package/dist/es2019/rules/editor-example-type-import-required/index.js +286 -0
  14. package/dist/es2019/rules/no-xcss-in-cx/index.js +187 -0
  15. package/dist/es2019/rules/visit-example-type-import-required/index.js +23 -14
  16. package/dist/esm/index.js +15 -3
  17. package/dist/esm/rules/compiled/expand-motion-shorthand/index.js +275 -0
  18. package/dist/esm/rules/compiled/no-css-prop-in-object-spread/index.js +156 -0
  19. package/dist/esm/rules/compiled/use-motion-token-values/index.js +499 -0
  20. package/dist/esm/rules/editor-example-type-import-required/index.js +314 -0
  21. package/dist/esm/rules/no-xcss-in-cx/index.js +216 -0
  22. package/dist/esm/rules/visit-example-type-import-required/index.js +23 -13
  23. package/dist/types/index.d.ts +282 -243
  24. package/dist/types/rules/compiled/expand-motion-shorthand/index.d.ts +3 -0
  25. package/dist/types/rules/compiled/no-css-prop-in-object-spread/index.d.ts +3 -0
  26. package/dist/types/rules/compiled/use-motion-token-values/index.d.ts +3 -0
  27. package/dist/types/rules/editor-example-type-import-required/index.d.ts +4 -0
  28. package/dist/types/rules/no-xcss-in-cx/index.d.ts +31 -0
  29. package/dist/types-ts4.5/index.d.ts +226 -211
  30. package/dist/types-ts4.5/rules/compiled/expand-motion-shorthand/index.d.ts +3 -0
  31. package/dist/types-ts4.5/rules/compiled/no-css-prop-in-object-spread/index.d.ts +3 -0
  32. package/dist/types-ts4.5/rules/compiled/use-motion-token-values/index.d.ts +3 -0
  33. package/dist/types-ts4.5/rules/editor-example-type-import-required/index.d.ts +4 -0
  34. package/dist/types-ts4.5/rules/no-xcss-in-cx/index.d.ts +31 -0
  35. package/package.json +2 -1
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = exports.RULE_NAME = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _fs = _interopRequireDefault(require("fs"));
10
+ var _path = _interopRequireDefault(require("path"));
11
+ var _utils = require("@typescript-eslint/utils");
12
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
13
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
14
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
15
+ var RULE_NAME = exports.RULE_NAME = 'editor-example-type-import-required';
16
+
17
+ /**
18
+ * Spec files that are excluded from this rule because they don't use visitExample
19
+ * or have their own test harness that doesn't follow the exampleName fixture pattern.
20
+ *
21
+ * Paths are matched as suffixes of the file path (platform-relative).
22
+ */
23
+ var EXCLUDED_SPEC_FILES = [
24
+ // Meta-tests for the testing infrastructure itself
25
+ 'build/test-tooling/integration-testing/src/examples/__tests__/playwright/example.spec.ts', 'build/test-tooling/integration-testing/src/matchers/__tests__/playwright/to-have-height.spec.ts', 'build/test-tooling/integration-testing/src/matchers/__tests__/playwright/to-have-width.spec.ts',
26
+ // Tests the a11y decorator itself, no visitExample
27
+ 'packages/accessibility/axe-integration/a11y-playwright-testing/src/auto-a11y-setup/__tests__/playwright/skip-decorator.spec.ts',
28
+ // Stub test (expect(true).toBe(true)), no visitExample
29
+ 'packages/ai-mate/rovo-content-bridge-api/__tests__/playwright/index.spec.tsx',
30
+ // Page-object's visitExample call carries the typeof import(...) generic,
31
+ // so the typed example reference lives in _helpers/page-object.ts rather
32
+ // than in test.use({ exampleName }) in the spec itself.
33
+ 'packages/navigation/atlassian-switcher/src/__tests__/playwright/navigate-child-item.spec.ts', 'packages/navigation/atlassian-switcher/src/__tests__/playwright/navigate-link-item.spec.ts', 'packages/navigation/atlassian-switcher/src/__tests__/playwright/navigate-product-item.spec.ts',
34
+ // Spec runs through a page-object (pages/generic-form-renderer.ts) whose
35
+ // visitExample call already carries the typeof import(...) generic. The
36
+ // typed reference therefore lives in the colocated page-object, not in
37
+ // test.use({ exampleName }) in the spec.
38
+ 'packages/proforma/proforma-common-core/__tests__/playwright/json-test-cases.spec.ts', 'packages/proforma/proforma-form-renderer/__tests__/playwright/json-test-cases.spec.ts',
39
+ // Spec runs through a page-object that still uses raw page.goto() against
40
+ // /examples.html. Migrating these requires reworking the page-object to
41
+ // route through visitExample<typeof import(...)>(...).
42
+ 'packages/proforma/proforma-form-list/__tests__/playwright/form-list.spec.ts', 'packages/proforma/proforma-form-renderer/__tests__/playwright/form-renderer.spec.ts', 'packages/proforma/proforma-translations-editor/__tests__/playwright/translations-editor-with-form.spec.ts',
43
+ // Tests the website itself, not examples
44
+ 'website/src/__tests__/playwright/examples.spec.ts', 'website/src/__tests__/playwright/home.spec.ts',
45
+ // react-ufo: uses an `examplePage: string` fixture where the name (e.g. 'basic') is
46
+ // resolved to the example file internally by visitExample — the name does not match
47
+ // the file name (e.g. '01-basic.tsx'), so a typeof import assertion is not possible
48
+ // without refactoring the fixture to use keyof typeof import directly. Specs that
49
+ // happen to also use the inline `visitExample<typeof import(...)>` pattern alongside
50
+ // the fixture pass via the file-level typeof import check above and don't appear here.
51
+ 'packages/react-ufo/atlaskit/__tests__/playwright/apply-segments-threshold.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/bad-replacement-node.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/base-10-sections.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/base-100-sections.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/base-3-sections-ssr-timings.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/base-3-sections-unmount.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/css-display-contents.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/custom-cohort-data.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/custom-data.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/data-vc-ignore-if-no-layout-shift.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/full-pixel-horizontal.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/full-pixel.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/fy25_02.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/hold.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/interactions-responsiveness.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/interactions-unknown-element.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/interactions-vc.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/is-opened-in-background.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/is-tab-throttled.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/metric-variants.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/minor-interactions.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/non-visual-style.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/page-visibility-hidden-timestamp.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/payload-integrity.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/post-interaction-late-holds.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/post-interaction-log-always-send.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/replacement-node.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/revisions.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/same-attribute-value-mutation.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/speed-index.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/ssr-placeholder-v3.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/terminal-error.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/third-party-segment-extra-metrics.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/third-party-segment-iframe.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/third-party-segment-timings.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/third-party-segment.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/transition-vc.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/ttai.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/ufo-blindspot-watchdog.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/ufo-errors.spec.ts', 'packages/react-ufo/atlaskit/__tests__/playwright/vc-dirty.spec.ts',
52
+ // editor-performance-metrics: same pattern as react-ufo — uses an `examplePage: string` fixture
53
+ // where the name resolves internally and does not match the example file name.
54
+ 'packages/editor/editor-performance-metrics/__tests__/playwright/basic-editor-ttai.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/basic-react-app.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/latency-track.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/ttai-timers.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next-attribute-change.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next-element-moving.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next-moving-node.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next-placeholder.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next-react-remounting.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next-track-user-events.spec.ts', 'packages/editor/editor-performance-metrics/__tests__/playwright/vc-next.spec.ts',
55
+ // generative-ai-modal: the example name is passed dynamically at examplePage.goto({ example: '...' })
56
+ // time rather than via test.use(), so a static typeof import assertion in the spec is not possible.
57
+ 'packages/editor/generative-ai-modal/src/ui/screens/Preview/__tests__/playwright/tab-navigation.spec.ts'];
58
+ function isExcluded(filename) {
59
+ var normalised = filename.replace(/\\/g, '/');
60
+ return EXCLUDED_SPEC_FILES.some(function (excluded) {
61
+ return normalised.endsWith(excluded);
62
+ });
63
+ }
64
+ var messages = {
65
+ missingExampleName: 'Playwright spec files must include exampleName with a ' + 'typeof import type assertion in test.use(). ' + "Add: exampleName: 'testing' as keyof typeof import('../../../examples/testing.tsx') ",
66
+ missingTypeAssertion: 'exampleName must include a typeof import type assertion for the static import graph. ' + "Use: exampleName: '{{ value }}' as keyof typeof import('{{ expectedPath }}') ",
67
+ pathMismatch: 'The import path "{{ importPath }}" does not resolve to the expected example file ' + "for exampleName '{{ exampleName }}'. Expected: {{ expectedPath }}"
68
+ };
69
+ function isTargetFile(filename) {
70
+ return (filename.endsWith('.spec.tsx') || filename.endsWith('.spec.ts')) && !isExcluded(filename);
71
+ }
72
+
73
+ /**
74
+ * Resolves the example file path from the spec file's location and the example name.
75
+ * Editor specs follow: packages/{groupId}/{packageId}/src/__tests__/playwright/*.spec.ts
76
+ * Examples live at: packages/{groupId}/{packageId}/examples/{exampleName}.tsx
77
+ */
78
+ function resolveExamplePath(testFilePath, exampleName) {
79
+ var testFileDir = _path.default.dirname(testFilePath);
80
+ var segments = testFileDir.split(_path.default.sep);
81
+ var packagesIndex = segments.findIndex(function (seg) {
82
+ return seg === 'packages';
83
+ });
84
+ if (packagesIndex === -1) {
85
+ return null;
86
+ }
87
+ var groupId = segments[packagesIndex + 1];
88
+ var packageId = segments[packagesIndex + 2];
89
+ if (!groupId || !packageId) {
90
+ return null;
91
+ }
92
+ var basePath = _path.default.isAbsolute(testFilePath) ? _path.default.resolve.apply(_path.default, ['/'].concat((0, _toConsumableArray2.default)(segments.slice(0, packagesIndex + 1)))) : _path.default.resolve.apply(_path.default, [process.cwd()].concat((0, _toConsumableArray2.default)(segments.slice(0, packagesIndex + 1))));
93
+ var examplesDir = _path.default.resolve(basePath, groupId, packageId, 'examples');
94
+ var candidateRe = new RegExp("^(?:\\d+-)?".concat(exampleName, "(?:\\.examples?)?\\.tsx$"));
95
+ try {
96
+ var match = _fs.default.readdirSync(examplesDir).find(function (f) {
97
+ return candidateRe.test(f);
98
+ });
99
+ if (match) {
100
+ return _path.default.resolve(examplesDir, match);
101
+ }
102
+ } catch (_unused) {
103
+ // Directory doesn't exist (e.g. test environments)
104
+ }
105
+ return _path.default.resolve(examplesDir, "".concat(exampleName, ".tsx"));
106
+ }
107
+ function computeRelativeImportPath(fromFile, toFile) {
108
+ var fromDir = _path.default.dirname(fromFile);
109
+ var relativePath = _path.default.relative(fromDir, toFile);
110
+ relativePath = relativePath.replace(/\\/g, '/');
111
+ if (!relativePath.startsWith('.') && !relativePath.startsWith('/')) {
112
+ relativePath = "./".concat(relativePath);
113
+ }
114
+ return relativePath;
115
+ }
116
+
117
+ /**
118
+ * Check if a property value has a `keyof typeof import(...)` type assertion.
119
+ * Handles both:
120
+ * 'name' as keyof typeof import('...')
121
+ */
122
+ function extractTypeofImportPath(node) {
123
+ if (node.type !== _utils.AST_NODE_TYPES.TSAsExpression) {
124
+ return null;
125
+ }
126
+ var typeAnnotation = node.typeAnnotation;
127
+ if (typeAnnotation.type === _utils.AST_NODE_TYPES.TSTypeOperator && typeAnnotation.operator === 'keyof') {
128
+ return extractFromTypeQuery(typeAnnotation.typeAnnotation);
129
+ }
130
+ if (typeAnnotation.type === _utils.AST_NODE_TYPES.TSUnionType) {
131
+ var _iterator = _createForOfIteratorHelper(typeAnnotation.types),
132
+ _step;
133
+ try {
134
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
135
+ var member = _step.value;
136
+ if (member.type === _utils.AST_NODE_TYPES.TSTypeOperator && member.operator === 'keyof') {
137
+ var result = extractFromTypeQuery(member.typeAnnotation);
138
+ if (result) {
139
+ return result;
140
+ }
141
+ }
142
+ }
143
+ } catch (err) {
144
+ _iterator.e(err);
145
+ } finally {
146
+ _iterator.f();
147
+ }
148
+ }
149
+ return null;
150
+ }
151
+ function extractFromTypeQuery(node) {
152
+ if (!node || node.type !== _utils.AST_NODE_TYPES.TSTypeQuery) {
153
+ return null;
154
+ }
155
+ var exprName = node.exprName;
156
+ if (exprName.type !== _utils.AST_NODE_TYPES.TSImportType) {
157
+ return null;
158
+ }
159
+ var argument = exprName.argument;
160
+ if (argument.type === _utils.AST_NODE_TYPES.TSLiteralType && argument.literal.type === _utils.AST_NODE_TYPES.Literal && typeof argument.literal.value === 'string') {
161
+ return argument.literal.value;
162
+ }
163
+ return null;
164
+ }
165
+
166
+ /**
167
+ * Extract the string value from a property value, ignoring type assertions.
168
+ */
169
+ function getStringValue(node) {
170
+ if (node.type === _utils.AST_NODE_TYPES.Literal && typeof node.value === 'string') {
171
+ return node.value;
172
+ }
173
+ if (node.type === _utils.AST_NODE_TYPES.TSAsExpression) {
174
+ return getStringValue(node.expression);
175
+ }
176
+ return null;
177
+ }
178
+ var rule = {
179
+ meta: {
180
+ type: 'problem',
181
+ docs: {
182
+ description: 'Ensures that editor spec files using @af/editor-libra include exampleName with a ' + 'typeof import type assertion in test.use() for the static import graph (factsMap).'
183
+ },
184
+ fixable: 'code',
185
+ messages: messages,
186
+ schema: []
187
+ },
188
+ create: function create(context) {
189
+ var filename = context.filename;
190
+ if (!isTargetFile(filename)) {
191
+ return {};
192
+ }
193
+ return {
194
+ 'Program:exit': function ProgramExit(estreeNode) {
195
+ var program = estreeNode;
196
+
197
+ // Single AST walk: collect all test.use() calls AND detect whether the
198
+ // file contains any `typeof import('...')` reference at all (a TSImportType
199
+ // node). Either signal is sufficient evidence that the spec ties at least
200
+ // one example file into its TypeScript import graph.
201
+ var testUseCalls = [];
202
+ var hasAnyTypeofImport = false;
203
+ var visited = new Set();
204
+ var queue = [program];
205
+ while (queue.length > 0) {
206
+ var node = queue.shift();
207
+ if (visited.has(node)) {
208
+ continue;
209
+ }
210
+ visited.add(node);
211
+ if (node.type === _utils.AST_NODE_TYPES.CallExpression && node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === _utils.AST_NODE_TYPES.Identifier && node.callee.property.name === 'use' && node.arguments.length > 0 && node.arguments[0].type === _utils.AST_NODE_TYPES.ObjectExpression) {
212
+ testUseCalls.push(node);
213
+ }
214
+ if (node.type === _utils.AST_NODE_TYPES.TSImportType) {
215
+ hasAnyTypeofImport = true;
216
+ }
217
+ for (var _i = 0, _Object$keys = Object.keys(node); _i < _Object$keys.length; _i++) {
218
+ var key = _Object$keys[_i];
219
+ if (key === 'parent') {
220
+ continue;
221
+ }
222
+ var child = node[key];
223
+ if (Array.isArray(child)) {
224
+ var _iterator2 = _createForOfIteratorHelper(child),
225
+ _step2;
226
+ try {
227
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
228
+ var item = _step2.value;
229
+ if (item && typeof item.type === 'string') {
230
+ queue.push(item);
231
+ }
232
+ }
233
+ } catch (err) {
234
+ _iterator2.e(err);
235
+ } finally {
236
+ _iterator2.f();
237
+ }
238
+ } else if (child && typeof child.type === 'string') {
239
+ queue.push(child);
240
+ }
241
+ }
242
+ }
243
+
244
+ // Any `typeof import('...')` anywhere in the spec — including the
245
+ // `page.visitExample<typeof import('...')>(...)` and
246
+ // `page.visitMockedExample<typeof import('...')>(...)` patterns used
247
+ // outside of test.use() — satisfies the same goal as the canonical
248
+ // `test.use({ exampleName: '...' as keyof typeof import('...') })`
249
+ // pattern: the example file is referenced from the spec's TypeScript
250
+ // import graph.
251
+ if (hasAnyTypeofImport) {
252
+ return;
253
+ }
254
+
255
+ // Check if any test.use() call anywhere in the file has exampleName with a typeof import assertion
256
+ var fileHasExampleName = testUseCalls.some(function (call) {
257
+ var obj = call.arguments[0];
258
+ return obj.properties.some(function (prop) {
259
+ if (prop.type !== _utils.AST_NODE_TYPES.Property || prop.key.type !== _utils.AST_NODE_TYPES.Identifier || prop.key.name !== 'exampleName') {
260
+ return false;
261
+ }
262
+ return extractTypeofImportPath(prop.value) !== null;
263
+ });
264
+ });
265
+ if (fileHasExampleName) {
266
+ return;
267
+ }
268
+
269
+ // Find the first test.use() call that has exampleName without the typeof import assertion
270
+ // (if any), otherwise use the first test.use() call
271
+ var targetCall = testUseCalls[0];
272
+ var existingExampleNameProp = null;
273
+ for (var _i2 = 0, _testUseCalls = testUseCalls; _i2 < _testUseCalls.length; _i2++) {
274
+ var call = _testUseCalls[_i2];
275
+ var obj = call.arguments[0];
276
+ var prop = obj.properties.find(function (p) {
277
+ return p.type === _utils.AST_NODE_TYPES.Property && p.key.type === _utils.AST_NODE_TYPES.Identifier && p.key.name === 'exampleName';
278
+ });
279
+ if (prop) {
280
+ targetCall = call;
281
+ existingExampleNameProp = prop;
282
+ break;
283
+ }
284
+ }
285
+ if (!targetCall) {
286
+ return;
287
+ }
288
+ var objectArg = targetCall.arguments[0];
289
+
290
+ // Determine the example name to use for the import path
291
+ var exampleNameValue = existingExampleNameProp ? getStringValue(existingExampleNameProp.value) : null;
292
+ var defaultName = exampleNameValue !== null && exampleNameValue !== void 0 ? exampleNameValue : 'testing';
293
+ var examplePath = resolveExamplePath(filename, defaultName);
294
+ if (!examplePath) {
295
+ return;
296
+ }
297
+ var importPath = computeRelativeImportPath(filename, examplePath);
298
+ context.report({
299
+ node: targetCall,
300
+ messageId: 'missingExampleName',
301
+ fix: function fix(fixer) {
302
+ // If exampleName exists but lacks typeof import, replace its value
303
+ if (existingExampleNameProp) {
304
+ return fixer.replaceText(existingExampleNameProp.value, "'".concat(defaultName, "' as keyof typeof import('").concat(importPath, "') "));
305
+ }
306
+ // Otherwise insert exampleName as the first property
307
+ var firstProp = objectArg.properties[0];
308
+ if (!firstProp) {
309
+ return fixer.replaceText(targetCall.arguments[0], "{\n\texampleName: '".concat(defaultName, "' as keyof typeof import('").concat(importPath, "'),\n}"));
310
+ }
311
+ var sourceCode = context.sourceCode;
312
+ var token = sourceCode.getFirstToken(firstProp);
313
+ var indent = token ? '\t'.repeat(token.loc.start.column) : '\t';
314
+ return fixer.insertTextBefore(firstProp, "exampleName: '".concat(defaultName, "' as keyof typeof import('").concat(importPath, "') ,\n").concat(indent));
315
+ }
316
+ });
317
+ }
318
+ };
319
+ }
320
+ };
321
+ var _default = exports.default = rule;
@@ -0,0 +1,221 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _isSupportedImport = require("@atlaskit/eslint-utils/is-supported-import");
8
+ var _contextCompat = require("../util/context-compat");
9
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
10
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
11
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
12
+ /**
13
+ * Disallows passing xcss() results into cx() when used in an xcss prop.
14
+ *
15
+ * xcss() from @atlaskit/primitives and cx() from @atlaskit/css / @compiled/react
16
+ * are incompatible — xcss() produces an opaque StyleRule object, while cx()
17
+ * expects Compiled atomic class name strings. Mixing them causes runtime errors.
18
+ * xcss() results must never be passed to cx(), whether inline or pre-defined.
19
+ *
20
+ * ❌ Wrong — xcss() called inline inside cx():
21
+ * xcss={cx(xcss({ color: 'red' }), xcss({ fontWeight: 'bold' }))}
22
+ *
23
+ * ❌ Also wrong — xcss() results pre-defined but still passed into cx():
24
+ * const baseStyles = xcss({ color: 'red' });
25
+ * const boldStyles = xcss({ fontWeight: 'bold' });
26
+ * xcss={cx(baseStyles, boldStyles)}
27
+ *
28
+ * ✅ Correct — pass xcss() results directly to the xcss prop (no cx()):
29
+ * const baseStyles = xcss({ color: 'red' });
30
+ * xcss={baseStyles}
31
+ *
32
+ * ✅ Correct — use cssMap() + cx() (cssMap is compatible with cx()):
33
+ * const styles = cssMap({ base: { color: 'red' } });
34
+ * xcss={cx(styles.base, condition && styles.focused)}
35
+ *
36
+ * This rule is import-aware: it only flags xcss() calls (inline or via variable)
37
+ * imported from @atlaskit/primitives inside cx() calls imported from @atlaskit/css
38
+ * or @compiled/react that appear inside an xcss prop.
39
+ */
40
+ var rule = {
41
+ meta: {
42
+ type: 'problem',
43
+ docs: {
44
+ description: 'Disallow calling xcss() inline inside cx() in an xcss prop. Define styles at module level instead.'
45
+ },
46
+ messages: {
47
+ noXcssInCx: 'Do not pass xcss() results into cx(). ' + 'xcss() produces a StyleRule object that is incompatible with cx(), which expects Compiled atomic class names. ' + 'Pass xcss() results directly to the xcss prop instead: xcss={myStyles}. ' + 'To conditionally combine styles, use cssMap() + cx(): const styles = cssMap({...}); xcss={cx(styles.base, cond && styles.active)}'
48
+ },
49
+ schema: []
50
+ },
51
+ create: function create(context) {
52
+ return {
53
+ JSXAttribute: function JSXAttribute(node) {
54
+ // Narrow Rule.Node to JSXAttribute (estree-jsx augments the `estree` Node
55
+ // union with JSX members, so this discriminated narrowing is safe).
56
+ if (node.type !== 'JSXAttribute') {
57
+ return;
58
+ }
59
+
60
+ // Only check `xcss` props
61
+ if (node.name.type !== 'JSXIdentifier' || node.name.name !== 'xcss') {
62
+ return;
63
+ }
64
+ if (!node.value || node.value.type !== 'JSXExpressionContainer') {
65
+ return;
66
+ }
67
+ var expression = node.value.expression;
68
+ if (expression.type === 'JSXEmptyExpression') {
69
+ return;
70
+ }
71
+
72
+ // Early-return if the expression cannot possibly contain a cx() call —
73
+ // avoids the cost of getImportSources/getScope on simple references like xcss={baseStyles}.
74
+ var isCallOrArray = expression.type === 'CallExpression' || expression.type === 'ArrayExpression';
75
+ if (!isCallOrArray) {
76
+ return;
77
+ }
78
+ var importSources = (0, _isSupportedImport.getImportSources)(context);
79
+ var _getScope = (0, _contextCompat.getScope)(context, node),
80
+ references = _getScope.references;
81
+
82
+ /**
83
+ * Returns true if an Identifier node resolves to a variable whose
84
+ * initializer is a call to xcss() imported from @atlaskit/primitives.
85
+ *
86
+ * Walks up the scope chain from the current JSXAttribute scope to find
87
+ * the variable definition, since module-level variables are not in the
88
+ * local scope's references list.
89
+ *
90
+ * e.g. `const baseStyles = xcss({ color: 'red' })` — passing `baseStyles`
91
+ * here returns true.
92
+ */
93
+ var isXcssVariable = function isXcssVariable(identNode) {
94
+ if (identNode.type !== 'Identifier') {
95
+ return false;
96
+ }
97
+ var name = identNode.name;
98
+ // Walk up the scope chain to find the variable definition
99
+ var currentScope = (0, _contextCompat.getScope)(context, node);
100
+ while (currentScope) {
101
+ var variable = currentScope.set.get(name);
102
+ if (variable) {
103
+ var _iterator = _createForOfIteratorHelper(variable.defs),
104
+ _step;
105
+ try {
106
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
107
+ var _def$node$init;
108
+ var def = _step.value;
109
+ if (def.type === 'Variable' && def.node.type === 'VariableDeclarator' && ((_def$node$init = def.node.init) === null || _def$node$init === void 0 ? void 0 : _def$node$init.type) === 'CallExpression') {
110
+ // isXcss checks the callee identifier against referencesInScope to
111
+ // find the import binding. The callee lives in the same scope as the
112
+ // variable definition, so use all references from that scope.
113
+ var defScopeRefs = currentScope.references;
114
+ if ((0, _isSupportedImport.isXcss)(def.node.init.callee, defScopeRefs, importSources)) {
115
+ return true;
116
+ }
117
+ }
118
+ }
119
+ // Found the variable but it's not an xcss() call
120
+ } catch (err) {
121
+ _iterator.e(err);
122
+ } finally {
123
+ _iterator.f();
124
+ }
125
+ return false;
126
+ }
127
+ currentScope = currentScope.upper;
128
+ }
129
+ return false;
130
+ };
131
+
132
+ /**
133
+ * Recursively check a node that is an argument to cx() for xcss() results —
134
+ * both inline calls and references to variables initialised with xcss().
135
+ * Recurses into LogicalExpression (&&, ||) and ConditionalExpression (? :) so that
136
+ * patterns like cx(cond && xcss({...})) and cx(cond ? baseStyles : a) are caught.
137
+ */
138
+ var _checkArgForXcss = function checkArgForXcss(argNode) {
139
+ if (!argNode) {
140
+ return;
141
+ }
142
+ // Inline: cx(xcss({ color: 'red' }))
143
+ if (argNode.type === 'CallExpression' && (0, _isSupportedImport.isXcss)(argNode.callee, references, importSources)) {
144
+ context.report({
145
+ node: argNode,
146
+ messageId: 'noXcssInCx'
147
+ });
148
+ return;
149
+ }
150
+ // Variable reference: cx(baseStyles) where baseStyles = xcss({...})
151
+ if (isXcssVariable(argNode)) {
152
+ context.report({
153
+ node: argNode,
154
+ messageId: 'noXcssInCx'
155
+ });
156
+ return;
157
+ }
158
+ // Recurse into `cond && xcss({...})` or `cond || xcss({...})`
159
+ if (argNode.type === 'LogicalExpression') {
160
+ _checkArgForXcss(argNode.left);
161
+ _checkArgForXcss(argNode.right);
162
+ }
163
+ // Recurse into `cond ? xcss({...}) : fallback`
164
+ if (argNode.type === 'ConditionalExpression') {
165
+ _checkArgForXcss(argNode.consequent);
166
+ _checkArgForXcss(argNode.alternate);
167
+ }
168
+ };
169
+
170
+ /**
171
+ * Check all arguments of a cx() call for inline xcss() calls.
172
+ * Reports each xcss() call found as a violation.
173
+ */
174
+ var checkCxArgs = function checkCxArgs(callNode) {
175
+ if (callNode.type !== 'CallExpression') {
176
+ return;
177
+ }
178
+ if (!(0, _isSupportedImport.isCxFunction)(callNode.callee, references, importSources)) {
179
+ return;
180
+ }
181
+ var _iterator2 = _createForOfIteratorHelper(callNode.arguments),
182
+ _step2;
183
+ try {
184
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
185
+ var arg = _step2.value;
186
+ if (arg) {
187
+ _checkArgForXcss(arg.type === 'SpreadElement' ? arg.argument : arg);
188
+ }
189
+ }
190
+ } catch (err) {
191
+ _iterator2.e(err);
192
+ } finally {
193
+ _iterator2.f();
194
+ }
195
+ };
196
+
197
+ // Case 1: xcss={cx(...)} — cx() directly as the xcss value
198
+ checkCxArgs(expression);
199
+
200
+ // Case 2: xcss={[..., cx(...), ...]} — cx() inside an xcss array
201
+ if (expression.type === 'ArrayExpression') {
202
+ var _iterator3 = _createForOfIteratorHelper(expression.elements),
203
+ _step3;
204
+ try {
205
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
206
+ var element = _step3.value;
207
+ if (element) {
208
+ checkCxArgs(element.type === 'SpreadElement' ? element.argument : element);
209
+ }
210
+ }
211
+ } catch (err) {
212
+ _iterator3.e(err);
213
+ } finally {
214
+ _iterator3.f();
215
+ }
216
+ }
217
+ }
218
+ };
219
+ }
220
+ };
221
+ var _default = exports.default = rule;
@@ -118,7 +118,8 @@ function resolveVariableToConstant(programBody, variableName, cache) {
118
118
  * Returns null for any argument that can't be statically resolved.
119
119
  */
120
120
  function extractCallArgs(node, programBody, variableCache) {
121
- if (node.arguments.length < 3) {
121
+ var argOffset = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
122
+ if (node.arguments.length < argOffset + 3) {
122
123
  return null;
123
124
  }
124
125
  function resolveArg(arg) {
@@ -130,9 +131,9 @@ function extractCallArgs(node, programBody, variableCache) {
130
131
  }
131
132
  return null;
132
133
  }
133
- var groupId = resolveArg(node.arguments[0]);
134
- var packageId = resolveArg(node.arguments[1]);
135
- var exampleId = resolveArg(node.arguments[2]);
134
+ var groupId = resolveArg(node.arguments[argOffset]);
135
+ var packageId = resolveArg(node.arguments[argOffset + 1]);
136
+ var exampleId = resolveArg(node.arguments[argOffset + 2]);
136
137
  if (!groupId || !packageId || !exampleId) {
137
138
  return null;
138
139
  }
@@ -180,8 +181,13 @@ function resolveExamplePathFromArgs(groupId, packageId, exampleId, testFilePath)
180
181
  var examplesDir = _path.default.resolve(packagesBase.basePath, groupId, packageId, 'examples');
181
182
  var fallback = _path.default.resolve(examplesDir, "".concat(exampleId, ".tsx"));
182
183
 
183
- // Match: exact name OR numeric-prefixed variant, with optional `.examples` infix
184
- var candidateRe = new RegExp("^(?:\\d+-)?".concat(exampleId, "(?:\\.examples?)?\\.tsx$"));
184
+ // Phase 4: loosen candidateRe to match both pre- and post-rename filename shapes.
185
+ // Pre-rename: ^(\d+-)?<id>(\.(examples?))?\.tsx$
186
+ // Post-rename: ^(\d+-)?<id>(\.<ident>){0,3}\.tsx$ (Volt prefix, optional .dup<N>, optional role)
187
+ // The {0,3} cap prevents matching arbitrary strings (e.g. 4-component names).
188
+ // Escape regex metacharacters in exampleId (ids are kebab-case today, but defensive).
189
+ var escapedId = exampleId.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
190
+ var candidateRe = new RegExp("^(?:\\d+-)?".concat(escapedId, "(?:\\.[A-Za-z][A-Za-z0-9_]*){0,3}\\.tsx$"));
185
191
  try {
186
192
  var match = _fs.default.readdirSync(examplesDir).find(function (f) {
187
193
  return candidateRe.test(f);
@@ -279,20 +285,24 @@ var rule = {
279
285
  return;
280
286
  }
281
287
  var node = estreeNode;
282
- // Only handle `<anything>.visitExample(...)` calls
283
- if (node.callee.type !== _utils.AST_NODE_TYPES.MemberExpression || node.callee.property.type !== _utils.AST_NODE_TYPES.Identifier || node.callee.property.name !== 'visitExample') {
288
+ var calleeIdentifier = null;
289
+ var argOffset = 0;
290
+ if (node.callee.type === _utils.AST_NODE_TYPES.MemberExpression && node.callee.property.type === _utils.AST_NODE_TYPES.Identifier && node.callee.property.name === 'visitExample') {
291
+ calleeIdentifier = node.callee.property;
292
+ } else if (node.callee.type === _utils.AST_NODE_TYPES.Identifier && node.callee.name === 'visitMockedExample') {
293
+ calleeIdentifier = node.callee;
294
+ argOffset = 1; // first arg is `page`
295
+ } else {
284
296
  return;
285
297
  }
286
298
 
287
- // Narrow callee — we've confirmed property is an Identifier above
288
- var callee = node.callee;
289
299
  // reportCallee is typed as estree.Node for context.report compatibility
290
300
  var reportCallee = estreeNode.callee;
291
301
  var genericType = extractGenericType(node);
292
302
 
293
303
  // ── Case 1: No generic type parameter ────────────────────────────────
294
304
  if (genericType === null) {
295
- var _args = extractCallArgs(node, programBody, variableCache);
305
+ var _args = extractCallArgs(node, programBody, variableCache, argOffset);
296
306
  context.report({
297
307
  node: reportCallee,
298
308
  messageId: 'missingTypeofImport',
@@ -305,7 +315,7 @@ var rule = {
305
315
  return null;
306
316
  }
307
317
  var importPath = computeRelativeImportPath(filename, examplePath);
308
- var _ref2 = callee.property.range,
318
+ var _ref2 = calleeIdentifier.range,
309
319
  _ref3 = (0, _slicedToArray2.default)(_ref2, 2),
310
320
  start = _ref3[0],
311
321
  end = _ref3[1];
@@ -367,7 +377,7 @@ var rule = {
367
377
  }
368
378
 
369
379
  // Validate that the import path matches the arguments
370
- var args = extractCallArgs(node, programBody, variableCache);
380
+ var args = extractCallArgs(node, programBody, variableCache, argOffset);
371
381
  if (!args) {
372
382
  // Dynamic arguments — can't validate statically
373
383
  return;