1import { wrapDevelopmentCSS } from './css'; 2 3const RNW_CSS_CLASS_ID = '_'; 4 5export async function transformCssModuleWeb(props: { 6 filename: string; 7 src: string; 8 options: { projectRoot: string; minify: boolean; dev: boolean; sourceMap: boolean }; 9}) { 10 const { transform } = await import('lightningcss'); 11 12 // TODO: Add bundling to resolve imports 13 // https://lightningcss.dev/bundling.html#bundling-order 14 15 const cssResults = transform({ 16 filename: props.filename, 17 code: Buffer.from(props.src), 18 sourceMap: props.options.sourceMap, 19 cssModules: { 20 // Prevent renaming CSS variables to ensure 21 // variables created in global files are available. 22 dashedIdents: false, 23 }, 24 // cssModules: true, 25 projectRoot: props.options.projectRoot, 26 minify: props.options.minify, 27 }); 28 const codeAsString = cssResults.code.toString(); 29 30 const { styles, variables } = convertLightningCssToReactNativeWebStyleSheet(cssResults.exports!); 31 32 let outputModule = `module.exports=Object.assign(${JSON.stringify(styles)},${JSON.stringify( 33 variables 34 )});`; 35 36 if (props.options.dev) { 37 const runtimeCss = wrapDevelopmentCSS({ 38 ...props, 39 src: codeAsString, 40 }); 41 42 outputModule += '\n' + runtimeCss; 43 } 44 45 return { 46 output: outputModule, 47 css: cssResults.code, 48 map: cssResults.map, 49 }; 50} 51 52export function convertLightningCssToReactNativeWebStyleSheet( 53 input: import('lightningcss').CSSModuleExports 54) { 55 const styles: Record<string, any> = {}; 56 const variables: Record<string, string> = {}; 57 // e.g. { container: { name: 'ahs8IW_container', composes: [], isReferenced: false }, } 58 Object.entries(input).map(([key, value]) => { 59 // order matters here 60 let className = value.name; 61 62 if (value.composes.length) { 63 className += ' ' + value.composes.map((value) => value.name).join(' '); 64 } 65 66 // CSS Variables will be `{string: string}` 67 if (key.startsWith('--')) { 68 variables[key] = className; 69 } 70 71 styles[key] = { $$css: true, [RNW_CSS_CLASS_ID]: className }; 72 return { 73 [key]: { $$css: true, [RNW_CSS_CLASS_ID]: className }, 74 }; 75 }); 76 77 return { styles, variables }; 78} 79 80export function matchCssModule(filePath: string): boolean { 81 return !!/\.module(\.(native|ios|android|web))?\.(css|s[ac]ss)$/.test(filePath); 82} 83