Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are aliases possible inside the scss file? #19

Open
toshiSat opened this issue Jan 25, 2019 · 10 comments
Open

Are aliases possible inside the scss file? #19

toshiSat opened this issue Jan 25, 2019 · 10 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@toshiSat
Copy link

I haven't figured out a way yet to have aliases inside the scss file.

@kristerkari
Copy link
Owner

Sorry, but I'm not sure what you mean. Can you give a code example of what you are trying to do?

@toshiSat
Copy link
Author

So with React.js I'm able to create aliases in webpack. I can then transpile them in .js, .jsx, .css, .scss, etc files. I can make aliases in React Native to doing something like this
["module-resolver", { "root": ["./src"], "alias": { "@api": "./src/api", "@app": "./src/modules/app", "@common": "./src/common", "@components": "./src/common/components", "@modules": "./src/modules", "styles": "./src/common/styles", "@utils": "./src/common/utils" } }]

So if I want to import something from the components directory i can import component from '@components/component'

In React.js I can also do this from scss files, I was wondering if it's possible to do this using your module as well. I think it looks something like this:
@import '~styles/colors.scss"

@kristerkari
Copy link
Owner

kristerkari commented Jan 25, 2019

Thanks, I understand now what you mean.

The aliases are not supported by default as the library does not use Webpack, but I think that you should be able to use aliases by adding this library to your project:
https://www.npmjs.com/package/node-sass-importer-alias

You can pass the aliases inside importer in Sass' options:
https://github.com/kristerkari/react-native-sass-transformer#sass-options

@kristerkari kristerkari pinned this issue Jan 25, 2019
@kristerkari
Copy link
Owner

Actually I just tested the example that I gave, and I could not make it work like that. I need to have another look to try to figure out how to get the aliases to work.

@arminsalcin
Copy link

Hello, is there any update for this case, i have monorepo where aliases are set in ts config, i also tried using babel config to set aliases there in expo project but yet it doesn't work, it just doesn't seem to see those kind of imports.

@arminsalcin
Copy link

arminsalcin commented Nov 13, 2024

Apparently i found this way as others didnt worked

const fs = require('fs');
const svgTransformer = require('react-native-svg-transformer');
const sassTransformer = require('react-native-sass-transformer');
const metroTransformer = require('metro-react-native-babel-transformer');

// Define your SCSS import aliases
const scssAliasMap = {
  '@styles': '../../shared/styles',
  // Add other aliases here
};

// Custom function to resolve aliases
function resolveScssAliases(src) {
  let transformedSrc = src;
  Object.keys(scssAliasMap).forEach((alias) => {
    const aliasPath = scssAliasMap[alias];
    const aliasRegex = new RegExp(`@use\\s+['"]${alias}`, 'g');
    transformedSrc = transformedSrc.replace(aliasRegex, `@use '${aliasPath}`);
  });
  return transformedSrc;
}

/**
 * Reads and formats the content of a CSS/SCSS file.
 */
function readAndTransformCSS(filePath) {
  try {
    const fileContent = fs.readFileSync(filePath, 'utf8');
    return fileContent.replace(/\r\n/g, '\n');
  } catch (error) {
    console.error('Error reading the CSS file:', error);
    return '';
  }
}

module.exports.transform = ({ src, filename, ...rest }) => {
  if (filename.endsWith('.svg')) {
    return svgTransformer.transform({ src, filename, ...rest });
  } else if (filename.endsWith('.scss') || filename.endsWith('.sass')) {
    const formattedSrc = resolveScssAliases(readAndTransformCSS(filename));
    return sassTransformer.transform({ src: formattedSrc, filename, ...rest });
  }

  // Use the default Metro transformer for other file types
  return metroTransformer.transform({ src, filename, ...rest });
};

@Lev-Shapiro
Copy link

@arminsalcin I liked the approach, however the compiler says .transform is an unknown option. Does your solution still work for you?

Screenshot 2024-12-29 at 13 32 12

@Lev-Shapiro
Copy link

Oh and if the solution actually still works, would you mind running npm list metro && npm list -g metro and sharing the results?

@Lev-Shapiro
Copy link

K, nevermind, figured it out :)

@arminsalcin
Copy link

Sorry its holiday time, so i was off, hre ismy latest transofrmer file, bear in mind:

  • I use rems in my scss files as they are compatible with my web versions so it will find rem values and convert them to px (mine base font size was 10px not 16px as usual)
const fs = require('fs');
const sass = require('sass'); // Dart Sass
const svgTransformer = require('react-native-svg-transformer/expo');
const sassTransformer = require('react-native-sass-transformer');
const metroTransformer = require('metro-react-native-babel-transformer');

// Define your SCSS import aliases
const scssAliasMap = {
  '@styles': '../../shared/styles',
  // Add other aliases here
};

const remBase = 10;

/**
 * Resolves aliases in SCSS content.
 * Replaces `@use` or `@import` paths with their mapped aliases.
 */
function resolveAliases(src) {
  let transformedSrc = src;

  Object.keys(scssAliasMap).forEach((alias) => {
    const aliasPath = scssAliasMap[alias];
    const aliasRegex = new RegExp(`@(use|import)\\s+['"]${alias}`, 'g');
    transformedSrc = transformedSrc.replace(aliasRegex, `@$1 '${aliasPath}`);
  });
  return transformedSrc;
}

function compileScssToCss(filePath) {
  try {
    const rawContent = fs.readFileSync(filePath, 'utf8');

    // Resolve aliases in SCSS content
    const aliasedContent = resolveAliases(rawContent);

    // Compile SCSS to CSS with Sass
    const result = sass.compileString(aliasedContent, {
      loadPaths: ['src', '../../shared/styles'], // Add other paths as needed
    });

    return result.css;
  } catch (error) {
    console.error(`Error compiling SCSS for file ${filePath}:`, error.message);
    return '';
  }
}

/**
 * Preprocess SCSS by resolving variables and converting rem to px.
 */
function preprocessScss(filePath) {
  // Step 1: Compile SCSS to CSS to resolve variables
  const compiledCss = compileScssToCss(filePath);

  // Step 2: Convert rem values to px in the resolved CSS
  return compiledCss.replace(
    /\b(\d+(\.\d+)?)rem\b/g,
    (match, remValue) => `${parseFloat(remValue) * remBase}px`
  );
}

module.exports.transform = ({ src, filename, ...rest }) => {
  if (filename.endsWith('.svg')) {
    return svgTransformer.transform({ src, filename, ...rest });
  }
  if (filename.endsWith('.scss') || filename.endsWith('.sass')) {
    // Preprocess and transform SCSS/SASS files
    const transformedSrc = preprocessScss(filename);

    const transform = sassTransformer.transform({
      src: transformedSrc,
      filename,
      ...rest,
    });

    // Debugging logs
    console.log(`Transformed SCSS/SASS for file: ${filename}`);

    return transform;
  }

  // Use the default Metro transformer for other file types
  return metroTransformer.transform({ src, filename, ...rest });
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants