elchininet / postcss-rtlcss

PostCSS plugin to automatically build Cascading Style Sheets (CSS) with Left-To-Right (LTR) and Right-To-Left (RTL) rules using RTLCSS
https://elchininet.github.io/postcss-rtlcss/
Apache License 2.0
100 stars 15 forks source link

Issue with converting scss to rtlcss in Angular component styles #120

Closed MatasRut closed 2 years ago

MatasRut commented 2 years ago

Hi, I have been trying to use the postcss-rtlcss plugin with postcss-loader in an Angular12 project.

All is well when styles are defined in the main styles.css file. However, the conversion does not work when styles are defined for a specific component. In such case Angular adds a [_ngcontent-] selector to each class of the component so it knows how the styles should be scoped.

So sass input:

.padding-class {
  padding-left: 250px;
  p {
    color: blue;
    margin-left: 100px;
  }
}

Is converted like in the image below: image

As you can probably already see, the tag is also added after the generated [dir] selectors which causes the classes to not be applied.

Here is a simple project that reproduces the problem: https://github.com/MatasRut/rtlcss-example

Please advise on how this issue can be resolved.

elchininet commented 2 years ago

Hi @MatasRut,

Unfortunately, this doesn‘t fall in this plugin but in Angular, those scope classes are added later in the pipeline by Angular (it assumes that all the styles in a component belong to the component itself and not to the :root element). So, this plugin does this:

[dir=ltr] .padding-class p {
    padding-left: 250px;
}

[dir=rtl] .padding-class p {
    padding-right: 250px;
}

And later Angular adds scopes to all elements in the selector, so this plugin doesn‘t have any control over that:

[dir=ltr][angular-scope] .padding-class[angular-scope] p[angular-scope] {
    padding-left: 250px;
}

[dir=rtl][angular-scope] .padding-class[angular-scope] p[angular-scope] {
    padding-right: 250px;
}

You can find the same issue here, closed back in 2018 in the postcss-rtl plugin.

Regards.

MatasRut commented 2 years ago

Thank you for the quick response, I managed to solve my issue by changing the prefix to use :host-context() where encapsulation is used like so: rtlPrefix: ':host-context([dir=\'rtl\'])'. Seems to be working fine, closing this issue.

elchininet commented 2 years ago

Thanks @MatasRut, If you push the changes of your workaround to your example repo I can add it to some section in the README so others can see workarounds to use the plugin with different libraries. Like this one. Regards.

MatasRut commented 2 years ago

@elchininet I pushed the changes of my workaround to the repo, add it to the README if you see fit.

elchininet commented 2 years ago

Hi @MatasRut,

I‘m trying to reproduce your repo but I‘m not able to do it. First I received an error:

An unhandled exception occurred: Cannot find module 'webpack'

So, I installed webpack. Now the error is gone but I don‘t get any prefix in the rules:

image

Do I need to do something special?

Regards.

MatasRut commented 2 years ago

Hey @elchininet,

I forgot to add webpack and sass to package.json as I had them installed globally. Sorry for that. I updated the dependencies so after running npm install the repo should work out of the box now :).

Also don't forget to use ng build --extra-webpack-config webpack.partial.js for building the app.

Let me know if this fixes the issue.

elchininet commented 2 years ago

Hi @MatasRut, What was missing was the command to execute the Webpack partial. Now it is working. Regards!