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 } = require('lightningcss') as typeof 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, reactNativeWeb, variables } = convertLightningCssToReactNativeWebStyleSheet(
31    cssResults.exports!
32  );
33
34  let outputModule = `module.exports=Object.assign(${JSON.stringify(
35    styles
36  )},{unstable_styles:${JSON.stringify(reactNativeWeb)}},${JSON.stringify(variables)});`;
37
38  if (props.options.dev) {
39    const runtimeCss = wrapDevelopmentCSS({
40      ...props,
41      src: codeAsString,
42    });
43
44    outputModule += '\n' + runtimeCss;
45  }
46
47  return {
48    output: outputModule,
49    css: cssResults.code,
50    map: cssResults.map,
51  };
52}
53
54export function convertLightningCssToReactNativeWebStyleSheet(
55  input: import('lightningcss').CSSModuleExports
56) {
57  const styles: Record<string, string> = {};
58  const reactNativeWeb: Record<string, any> = {};
59  const variables: Record<string, string> = {};
60  // e.g. { container: { name: 'ahs8IW_container', composes: [], isReferenced: false }, }
61  Object.entries(input).map(([key, value]) => {
62    // order matters here
63    let className = value.name;
64
65    if (value.composes.length) {
66      className += ' ' + value.composes.map((value) => value.name).join(' ');
67    }
68
69    // CSS Variables will be `{string: string}`
70    if (key.startsWith('--')) {
71      variables[key] = className;
72    }
73
74    styles[key] = className;
75    reactNativeWeb[key] = { $$css: true, [RNW_CSS_CLASS_ID]: className };
76    return {
77      [key]: { $$css: true, [RNW_CSS_CLASS_ID]: className },
78    };
79  });
80
81  return { styles, reactNativeWeb, variables };
82}
83
84export function matchCssModule(filePath: string): boolean {
85  return !!/\.module(\.(native|ios|android|web))?\.(css|s[ac]ss)$/.test(filePath);
86}
87