From 22513aa969a93cb2b45a5d48f58c7d250a7fb20c Mon Sep 17 00:00:00 2001 From: Melissa Liu Date: Fri, 24 Oct 2025 14:27:59 -0400 Subject: [PATCH] [eslint-plugin] add legacyAllowMixedExports config to enforce-extension --- .../stylex-enforce-extension-test.js | 111 ++++++++++++++++-- .../src/stylex-enforce-extension.js | 13 +- 2 files changed, 108 insertions(+), 16 deletions(-) diff --git a/packages/@stylexjs/eslint-plugin/__tests__/stylex-enforce-extension-test.js b/packages/@stylexjs/eslint-plugin/__tests__/stylex-enforce-extension-test.js index 772fb0e02..6bd710c75 100644 --- a/packages/@stylexjs/eslint-plugin/__tests__/stylex-enforce-extension-test.js +++ b/packages/@stylexjs/eslint-plugin/__tests__/stylex-enforce-extension-test.js @@ -93,7 +93,6 @@ ruleTester.run('stylex-enforce-extension', rule.default, { import * as stylex from '@stylexjs/stylex'; export const vars = stylex.defineVars({ color: 'red' }); export const consts = stylex.defineConsts({ color: 'red' }); - export default stylex.defineVars({ background: 'blue' }); `, filename: 'myComponent.stylex.jsx', }, @@ -172,6 +171,82 @@ ruleTester.run('stylex-enforce-extension', rule.default, { filename: 'testComponent.custom.jsx', options: [{ themeFileExtension: '.custom' }], }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const vars = stylex.defineVars({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.jsx', + options: [{ legacyAllowMixedExports: true }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const consts = stylex.defineConsts({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.jsx', + options: [{ legacyAllowMixedExports: true }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const vars = stylex.defineVars({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.tsx', + options: [{ legacyAllowMixedExports: true }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const consts = stylex.defineConsts({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.tsx', + options: [{ legacyAllowMixedExports: true }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const vars = stylex.defineVars({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.ts', + options: [{ legacyAllowMixedExports: true }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const consts = stylex.defineConsts({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.js', + options: [{ legacyAllowMixedExports: true }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const consts = stylex.defineConsts({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.custom.ts', + options: [ + { legacyAllowMixedExports: true, themeFileExtension: '.custom' }, + ], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const consts = stylex.defineConsts({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.custom.js', + options: [ + { legacyAllowMixedExports: true, themeFileExtension: '.custom' }, + ], + }, ], invalid: [ @@ -200,39 +275,29 @@ ruleTester.run('stylex-enforce-extension', rule.default, { import * as stylex from '@stylexjs/stylex'; export const vars = stylex.defineVars({ color: 'red' }); export const somethingElse = someFunction(); - export default stylex.defineVars({ background: 'blue' }); `, filename: 'myComponent.stylex.jsx', - errors: [ - { message: invalidExportFromThemeFiles }, - { message: invalidExportFromThemeFiles }, - ], + errors: [{ message: invalidExportFromThemeFiles }], }, { code: ` import * as stylex from '@stylexjs/stylex'; export const consts = stylex.defineConsts({ color: 'red' }); export const somethingElse = someFunction(); - export default stylex.defineConsts({ background: 'blue' }); `, filename: 'myComponent.stylex.jsx', - errors: [ - { message: invalidExportFromThemeFiles }, - { message: invalidExportFromThemeFiles }, - ], + errors: [{ message: invalidExportFromThemeFiles }], }, { code: ` import * as stylex from '@stylexjs/stylex'; export const vars = someFunction(); export const somethingElse = someFunction(); - export default stylex.defineVars({ background: 'blue' }); `, filename: 'myComponent.stylex.jsx', errors: [ { message: invalidFilenameWithoutRestrictedExports('.stylex.jsx') }, { message: invalidFilenameWithoutRestrictedExports('.stylex.jsx') }, - { message: invalidExportFromThemeFiles }, ], }, { @@ -429,5 +494,25 @@ ruleTester.run('stylex-enforce-extension', rule.default, { }, ], }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const vars = stylex.defineVars({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.jsx', + options: [{ legacyAllowMixedExports: false }], + errors: [{ message: invalidExportFromThemeFiles }], + }, + { + code: ` + import * as stylex from '@stylexjs/stylex'; + export const consts = stylex.defineConsts({ color: 'red' }); + export const somethingElse = someFunction(); + `, + filename: 'myComponent.stylex.jsx', + options: [{ legacyAllowMixedExports: false }], + errors: [{ message: invalidExportFromThemeFiles }], + }, ], }); diff --git a/packages/@stylexjs/eslint-plugin/src/stylex-enforce-extension.js b/packages/@stylexjs/eslint-plugin/src/stylex-enforce-extension.js index 602b26d68..76e8280ad 100644 --- a/packages/@stylexjs/eslint-plugin/src/stylex-enforce-extension.js +++ b/packages/@stylexjs/eslint-plugin/src/stylex-enforce-extension.js @@ -47,6 +47,11 @@ const stylexEnforceExtension = { type: 'string', default: '.stylex', }, + // This is a legacy option that allows mixed exports in theme files. This is for internal legacy patterns and should not be used by external users. + legacyAllowMixedExports: { + type: 'boolean', + default: false, + }, }, additionalProperties: false, }, @@ -57,8 +62,10 @@ const stylexEnforceExtension = { let hasOtherExports = false; const fileName = context.getFilename(); const options = context.options[0] || {}; - const { validImports: importsToLookFor = ['stylex', '@stylexjs/stylex'] } = - options; + const { + validImports: importsToLookFor = ['stylex', '@stylexjs/stylex'], + legacyAllowMixedExports = false, + } = options; const themeFileExtension = ( options.themeFileExtension || '.stylex' @@ -115,7 +122,7 @@ const stylexEnforceExtension = { fileName.endsWith(ext), ); - if (hasRestrictedExports && hasOtherExports) { + if (hasRestrictedExports && hasOtherExports && !legacyAllowMixedExports) { context.report({ node, message: