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

RTLCSS errors when processing a value directive marked as important #329

Open
svieira opened this issue Sep 25, 2023 · 1 comment · May be fixed by #346
Open

RTLCSS errors when processing a value directive marked as important #329

svieira opened this issue Sep 25, 2023 · 1 comment · May be fixed by #346

Comments

@svieira
Copy link

svieira commented Sep 25, 2023

Setup

Given the following little program:

const postcss = require('postcss');
const rtlcss = require('rtlcss');

const plugin = {
  postcssPlugin: 'make-declarations-important',
  Declaration(decl) {
    if (decl.important) return;
    decl.important = true;
  }
};

const defaultRuleSwitchCss = `
.default-rule-switch {
  left: 10px;
}
`;

const valueReplacementCss = `
.value-replacement{
  color: #F00 /*rtl:#00F*/;
}
`;

const declarationReplacementCss = `
.declaration-replacement {
  text-decoration: underline;
  /*rtl:remove*/
  text-decoration: none;
}
`;

const brokenCss = `${valueReplacementCss}`;
const workingCss = `${defaultRuleSwitchCss}${declarationReplacementCss}`;

console.log(postcss([plugin, rtlcss]).process(brokenCss, {from: 'example.css'}).css);

Expected result

.value-replacement {
  color: #00F !important;
}

Actual result

Uncaught TypeError: Cannot read properties of undefined (reading 'substr')
    at /CWD/example.css:3:3
    at Object.action (/CWD/node_modules/rtlcss/lib/plugin.js:184:141)
    at /CWD/node_modules/rtlcss/lib/rtlcss.js:136:27
    at /CWD/node_modules/rtlcss/lib/util.js:259:37

RTLCSS 2 used to work with programmatically set !important declarations - and it worked in RTLCSS v3.0.
However, in v3.1 RTLCSS started erroring on such nodes and it appears to have been broken ever since. The error message line is from v4.1.1, the latest version at the time of writing.

I have traced the issue down to ee9dc53, which presumes that PostCSS will always have a raws.important if Declaration.important is true, but PostCSS' documentation explicitly says that DeclarationRaws.important contains "The content of the important statement, if it is not just !important." (emphasis mine).

@elchininet
Copy link
Contributor

elchininet commented Dec 14, 2024

Hi @svieira,

I am not a maintainer of the project but at least I can explain you what happens 🙂

Plugins are applied left to right, so when you run decl.important = true in this declaration:

color: #F00 /*rtl:#00F*/;

PostCSS is the first one to run, and it doesn't expect to have comments between the declaration value and the semicolon, so it puts the important in this way:

color: #F00 /*rtl:#00F*/ !important;

But RTLCSS expects that a replace directive is written after the important:

color: #F00 !important /*rtl:#00F*/;

You can go to the playground and insert this CSS code:

.value-replacement{
  color: #F00 /*rtl:#00F*/ !important; 
}

You will notice the same error as a result. It is failing in this line, specifically in this part:

decl.raws.important.substr(9).trim()
                   ^
                   |
                  here

Because even is important is true, raws.important is undefined in the previous case.

As a workaround you can change the order of the plugins, let RTLCSS to run first.

console.log(postcss([rtlcss, plugin]).process(brokenCss, {from: 'example.css'}).css);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants