marceloucker / postcss-prefixer Goto Github PK
View Code? Open in Web Editor NEWPostCSS plugin to prefix all classes and ids
License: MIT License
PostCSS plugin to prefix all classes and ids
License: MIT License
I managed to get this plugin working on a vue project, but it only prefixed classes on .css files.
How would I rename all the classes used on vue components of the project?
[class="class "]
results in:
[class="prefix-class prefix-"]
Whereas the node engine version is >=6.0.0
in package.json
, the following code is not supported by node v6 :
rule.selector = Tokenizer.stringify(interateSelectorNodes(
Tokenizer.parse(selector),
{ prefix, ignore },
));
postcss-prefixer/lib/prefixer.js
Line 69 in a8a5b88
As user I want to have the possibility to ignore some files from the prefixer.
You can edit the prefixer.js in this way:
Migration guide:
https://evilmartians.com/chronicles/postcss-8-plugin-migration
postcss-prefixer/lib/prefixer.js
Line 75 in 9b353ad
I noticed an interesting bug and narrowed it down to this plugin, here is minimum size reproduction:
https://github.com/patdx/postcss-prefix-bug
In:
/* https://github.com/twbs/bootstrap/blob/55a0f9af2738daafe8d961ca35c22800c710bb27/dist/css/bootstrap.css#L212 */
a:not([href]):not([class]),
a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
Out:
/* https://github.com/twbs/bootstrap/blob/55a0f9af2738daafe8d961ca35c22800c710bb27/dist/css/bootstrap.css#L212 */
a:not([href]):not([classundefinedundefinedundefined]),
a:not([href]):not([classundefinedundefinedundefined]):hover {
color: inherit;
text-decoration: none;
}
In this case the plugin should not have change this code at all, I think?
I added some console logs to the plugin, getting this result:
β postcss-prefix-bug git:(main) npm start
> [email protected] start /Users/pm/dev/postcss-prefix-bug
> postcss src.css -o dist.css
parseAttrSelector({"type":"attribute","content":"href"}) -> {"type":"href","classes":[]}
parseAttrSelector({"type":"attribute","content":"class"}) -> {"type":"class","classes":[]}
attrStringify({"type":"class","classes":[]}) -> classundefinedundefinedundefined
parseAttrSelector({"type":"attribute","content":"href"}) -> {"type":"href","classes":[]}
parseAttrSelector({"type":"attribute","content":"class"}) -> {"type":"class","classes":[]}
attrStringify({"type":"class","classes":[]}) -> classundefinedundefinedundefined
It think the bug may be in the line right after parseAttrSelector
is called:
if (!['class', 'id'].includes(type)) return node;
However, I'm not familiar with this kind of CSS selector, so I'm totally sure how/what this part of the code is doing π
Alternatively, perhaps the solution is to have a fallback for undefined values inside attrStringify?
attrStringify({
type, operator, head, classes, foot,
}) {
- return `${type}${operator}${head}${classes.join(' ')}${foot}`;
+ return `${type}${operator ?? ''}${head ?? ''}${classes?.join(' ') ?? ''}${foot ?? ''}`;
},
Hi,
When we give code like this:
.header [class*=" icon-"]
It shows :
.header [class*="prefix- icon-"]
instead .header [class*=" prefix-icon-"]
Given this input:
.hello:not([class*="left labeled"]) {
border-radius: 3rem;
}
This plugin outputs:
.prefix-hello:not([class*="prefix-left labeled"]) {
border-radius: 3rem;
}
See labeled
class is not prefixed.
Hi! Thanks for the plugin!
Apparently prefixing is not working when I import a file which itself contains imports.
Global.scss
@import './Grid.scss';
Grid.scss
:root {
--page-max: 1180px;
--page-padding: 7.5vw;
--gutter-widht: 16px;
--half-gutter-width: calc(var(--gutter-widht) * 0.5);
}
$brp-1: 480px; /*480px*/
$brp-2: 768px; /*768px*/
$brp-3: 992px; /*992px*/
$brp-4: 1200px; /*1200px*/
$brp-5: 1600px; /*1600px*/
$breakpoints: (sm 30em $brp-1, md 48em $brp-2, lg 62em $brp-3, xl 75em $brp-4, xxl 90em $brp-5);
$grid-breakpoints: (
brp1: $brp-1,
brp2: $brp-2,
brp3: $brp-3,
brp4: $brp-4,
brp5: $brp-5,
);
.page {
max-width: 100%;
max-width: var(--page-max);
padding: 0 var(--page-padding);
margin: 0 auto 0 auto;
&__wrapper {
display: flex;
flex-direction: column;
margin: 0 calc(var(--half-gutter-width) * -1);
> * {
padding: 0 var(--half-gutter-width);
}
}
&__container {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
max-width: 100%;
}
&__sidebar {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
max-width: 100%;
display: none;
}
}
@media only screen and (min-width: $brp-1) {
:root {
--page-padding: 12.5vw;
}
}
@media only screen and (min-width: $brp-2) {
:root {
--page-padding: var(--spacer-64);
--gutter-widht: 32px;
--half-gutter-width: calc(var(--gutter-widht) * 0.5);
}
}
@media only screen and (min-width: $brp-3) {
:root {
--page-padding: var(--spacer-64);
}
.page {
&__wrapper {
flex-direction: row;
}
&__container {
flex-basis: 75%;
max-width: 75%;
}
&__sidebar {
display: block;
flex-basis: 25%;
max-width: 25%;
}
}
}
@media only screen and (min-width: $brp-4) {
:root {
--page-padding: var(--spacer-40);
}
.page {
&__container {
flex-basis: 66.66667%;
max-width: 66.66667%;
}
&__sidebar {
display: block;
flex-basis: 33.33333%;
max-width: 33.33333%;
}
}
}
@media only screen and (min-width: $brp-5) {
:root {
--page-padding: 0;
}
}
postcss.config.js
plugins: {
'postcss-flexibility': {},
'postcss-prefixer': {
prefix: 'tt-',
},
},
syntax: require('postcss-scss'),
};
webpack.config.js
const path = require('path');
// Export a function. Accept the base config as the only param.
module.exports = async ({ config, mode }) => {
// `mode` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
// Make whatever fine-grained changes you need
config.module.rules.push({
test: /\.scss$/,
sideEffects: true,
loaders: ['style-loader', 'css-loader', 'sass-loader', 'postcss-loader'],
include: path.resolve(__dirname, '../')
});
config.module.rules.push({
test: /\.svg$/,
loader: require.resolve('svg-inline-loader'),
});
// Return the altered config
return config;
};
This is resulting in the following css
:
:root {
--page-max: 1180px;
--page-padding: 7.5vw;
--gutter-widht: 16px;
--half-gutter-width: calc(var(--gutter-widht) * 0.5); }
/*480px*/
/*768px*/
/*992px*/
/*1200px*/
/*1600px*/
.page {
max-width: 100%;
max-width: var(--page-max);
padding: 0 var(--page-padding);
margin: 0 auto 0 auto; }
.page__wrapper {
display: flex;
flex-direction: column;
margin: 0 calc(var(--half-gutter-width) * -1); }
.page__wrapper > * {
padding: 0 var(--half-gutter-width); }
.page__container {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
max-width: 100%; }
.page__sidebar {
flex-grow: 0;
flex-shrink: 0;
flex-basis: 100%;
max-width: 100%;
display: none; }
@media only screen and (min-width: 480px) {
:root {
--page-padding: 12.5vw; } }
@media only screen and (min-width: 768px) {
:root {
--page-padding: var(--spacer-64);
--gutter-widht: 32px;
--half-gutter-width: calc(var(--gutter-widht) * 0.5); } }
@media only screen and (min-width: 992px) {
:root {
--page-padding: var(--spacer-64); }
.page__wrapper {
flex-direction: row; }
.page__container {
flex-basis: 75%;
max-width: 75%; }
.page__sidebar {
display: block;
flex-basis: 25%;
max-width: 25%; } }
@media only screen and (min-width: 1200px) {
:root {
--page-padding: var(--spacer-40); }
.page__container {
flex-basis: 66.66667%;
max-width: 66.66667%; }
.page__sidebar {
display: block;
flex-basis: 33.33333%;
max-width: 33.33333%; } }
@media only screen and (min-width: 1600px) {
:root {
--page-padding: 0; } }
However, if I import the file Grid.scss
directly, it is prefixed.
Are there any workarounds I could try apart from importing every file seperately? Any help would be much appreciated!
Related to ignore
Would it be possible to add a whitelist of selectors to only prefix those?
Thanks
I want to apply this only to some pacakges in node_modules, however it seems that is not supported yet π₯
Hello, however, this plugin is wonderful.
I using this plugin in my project. my webpack.config.js like this:
...
{
loader: 'postcss-loader',
options: {
plugins() {
return [
require('autoprefixer'),
require('postcss-prefixer')({
prefix: 'header-'
})
];
},
},
},
...
.header {
...
}
.brand {
...
}
.src-index__header-header {
...
}
.src-index__header-brand {
...
}
could you tell me how 'src-index' it was added automatically?
Thanks.
[class^="icon-"]
results in
[class^=icon-]
If I add a whitespace before or after icon- it works as intended.
Hello! Is it possible to ignore specific files instead of just a selector?
Good day!
Thanks for this useful plugin!
In the README you recommend to use this plugin with the postcss-cli:
"scripts": {
"postcss": "postcss input.css -u postcss-prefixer -o output.css"
}
Could you please explain how to pass the option to the cli.
actual result
body { margin: 1; }
.some-prefix-some-class { margin: 2; }
expected result
body.some-prefix { margin: 1; }
.some-prefix-some-class { margin: 2; }
why?
this is necessary to mix different css frameworks
with custom default styles for elements
different than postcss-prefix-selector
const fs = require('fs');
const postcss = require('postcss');
const prefixer = require('postcss-prefixer');
//const input = fs.readFileSync('src.css', 'utf-8');
const input = [
"body { margin: 1; }",
".some-class { margin: 2; }",
].join("\n");
const output = postcss([
prefixer({
prefix: 'some-prefix-',
//ignore: [ /selector-/, '.ignore', '#ignore' ]
})
]).process(input);
console.log(output.toString());
According to the W3C Spec string in CSS can be single or double quoted and need to handle escaped quotes as well.
Single quoted strings are currently not prefixed.
E.g.: [class='class']
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.