19b2597baSEvan Baconimport { wrapDevelopmentCSS } from './css'; 29b2597baSEvan Bacon 39b2597baSEvan Baconconst RNW_CSS_CLASS_ID = '_'; 49b2597baSEvan Bacon 59b2597baSEvan Baconexport async function transformCssModuleWeb(props: { 69b2597baSEvan Bacon filename: string; 79b2597baSEvan Bacon src: string; 89b2597baSEvan Bacon options: { projectRoot: string; minify: boolean; dev: boolean; sourceMap: boolean }; 99b2597baSEvan Bacon}) { 10*1a3a1db5SEvan Bacon const { transform } = require('lightningcss') as typeof import('lightningcss'); 119b2597baSEvan Bacon 129b2597baSEvan Bacon // TODO: Add bundling to resolve imports 139b2597baSEvan Bacon // https://lightningcss.dev/bundling.html#bundling-order 149b2597baSEvan Bacon 159b2597baSEvan Bacon const cssResults = transform({ 169b2597baSEvan Bacon filename: props.filename, 179b2597baSEvan Bacon code: Buffer.from(props.src), 189b2597baSEvan Bacon sourceMap: props.options.sourceMap, 199b2597baSEvan Bacon cssModules: { 209b2597baSEvan Bacon // Prevent renaming CSS variables to ensure 219b2597baSEvan Bacon // variables created in global files are available. 229b2597baSEvan Bacon dashedIdents: false, 239b2597baSEvan Bacon }, 249b2597baSEvan Bacon // cssModules: true, 259b2597baSEvan Bacon projectRoot: props.options.projectRoot, 269b2597baSEvan Bacon minify: props.options.minify, 279b2597baSEvan Bacon }); 289b2597baSEvan Bacon const codeAsString = cssResults.code.toString(); 299b2597baSEvan Bacon 30e62df662SEvan Bacon const { styles, reactNativeWeb, variables } = convertLightningCssToReactNativeWebStyleSheet( 31e62df662SEvan Bacon cssResults.exports! 32e62df662SEvan Bacon ); 339b2597baSEvan Bacon 34e62df662SEvan Bacon let outputModule = `module.exports=Object.assign(${JSON.stringify( 35e62df662SEvan Bacon styles 36201c72c1SEvan Bacon )},{unstable_styles:${JSON.stringify(reactNativeWeb)}},${JSON.stringify(variables)});`; 379b2597baSEvan Bacon 389b2597baSEvan Bacon if (props.options.dev) { 399b2597baSEvan Bacon const runtimeCss = wrapDevelopmentCSS({ 409b2597baSEvan Bacon ...props, 419b2597baSEvan Bacon src: codeAsString, 429b2597baSEvan Bacon }); 439b2597baSEvan Bacon 449b2597baSEvan Bacon outputModule += '\n' + runtimeCss; 459b2597baSEvan Bacon } 469b2597baSEvan Bacon 479b2597baSEvan Bacon return { 489b2597baSEvan Bacon output: outputModule, 499b2597baSEvan Bacon css: cssResults.code, 509b2597baSEvan Bacon map: cssResults.map, 519b2597baSEvan Bacon }; 529b2597baSEvan Bacon} 539b2597baSEvan Bacon 549b2597baSEvan Baconexport function convertLightningCssToReactNativeWebStyleSheet( 559b2597baSEvan Bacon input: import('lightningcss').CSSModuleExports 569b2597baSEvan Bacon) { 57e62df662SEvan Bacon const styles: Record<string, string> = {}; 58e62df662SEvan Bacon const reactNativeWeb: Record<string, any> = {}; 599b2597baSEvan Bacon const variables: Record<string, string> = {}; 609b2597baSEvan Bacon // e.g. { container: { name: 'ahs8IW_container', composes: [], isReferenced: false }, } 619b2597baSEvan Bacon Object.entries(input).map(([key, value]) => { 629b2597baSEvan Bacon // order matters here 639b2597baSEvan Bacon let className = value.name; 649b2597baSEvan Bacon 659b2597baSEvan Bacon if (value.composes.length) { 669b2597baSEvan Bacon className += ' ' + value.composes.map((value) => value.name).join(' '); 679b2597baSEvan Bacon } 689b2597baSEvan Bacon 699b2597baSEvan Bacon // CSS Variables will be `{string: string}` 709b2597baSEvan Bacon if (key.startsWith('--')) { 719b2597baSEvan Bacon variables[key] = className; 729b2597baSEvan Bacon } 739b2597baSEvan Bacon 74e62df662SEvan Bacon styles[key] = className; 75e62df662SEvan Bacon reactNativeWeb[key] = { $$css: true, [RNW_CSS_CLASS_ID]: className }; 769b2597baSEvan Bacon return { 779b2597baSEvan Bacon [key]: { $$css: true, [RNW_CSS_CLASS_ID]: className }, 789b2597baSEvan Bacon }; 799b2597baSEvan Bacon }); 809b2597baSEvan Bacon 81e62df662SEvan Bacon return { styles, reactNativeWeb, variables }; 829b2597baSEvan Bacon} 839b2597baSEvan Bacon 849b2597baSEvan Baconexport function matchCssModule(filePath: string): boolean { 857cebda5aSEvan Bacon return !!/\.module(\.(native|ios|android|web))?\.(css|s[ac]ss)$/.test(filePath); 869b2597baSEvan Bacon} 87