dbtedman / postcss-prefixwrap Goto Github PK
View Code? Open in Web Editor NEWA PostCSS plugin that is used to wrap css styles with a css selector to constrain their affect on parent elements in a page.
License: MIT License
A PostCSS plugin that is used to wrap css styles with a css selector to constrain their affect on parent elements in a page.
License: MIT License
v10 + v11
Add option appendCompoundSelector
that generates 2 selectors: PREFIX .container, PREFIX.container
. This will allow the style rules to start applying from the prefix level, removing the need to have extra divs.
Basically:
// Anything other than a root tag is always prefixed.
if (isNotRootTag(cleanedSelector)) {
let result = prefixSelector + " " + cleanedSelector;
if (appendCompoundSelector) {
result += `, ${prefixSelector}${cleanedSelector}`;
}
return result;
}
I have 3 levels of styles:
The apps need to use a css prefix to overwrite site styles, but unfortunately the component library also needs a css prefix, otherwise import will fail
`@apply` cannot be used with .font-light because .font-light is included in multiple rulesets.
This causes cascade problems between Tailwind utility classes and generic styles when dealing with slotted content (EX ".eof .eac menu" > ".eof .mx-9"). Using .eac *:not(.ssc)
prefix stops the styles from cascading (ssc - stop style cascade):
/** @type {import('postcss-load-config').Config} */
const config = {
plugins: [
require("postcss-import"),
require("tailwindcss"),
require("postcss-nested"),
require("autoprefixer"),
require("postcss-prefixwrap")('.eac *:not(.ssc)', {
ignoredSelectors: ["body" , /^body.(.+)/],
})
]
}
But it requires an extra div before the styles start applying, making the html structure cumbersome:
<template>
<div show.bind="isVisible" class="ssc eac">
<div>
<div class="tooltip-container">
<div class="e4-tooltip ${minWidth === 'wide' ? 'e4-tooltip-wide' : ''} e4-tooltip-${position}" ref="elem">
<div class="e4-tooltip-arrow" ref="tooltipArrow"></div>
<div class="overflow-hidden overflow-y-auto py-2 px-4 text-xs leading-snug text-center">
<div class="ssc ${appStylePrefix}">
<div>
<slot></slot>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
Hi,
When i use latest version, got below error.
And return to 1.34.0,back to normal.
postcss.config.js
module.exports = {
plugins: [
require("autoprefixer"),
require("postcss-prefixwrap")('.test'),
],
}
Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
Error: Cannot find module 'plugin/PostCSSPrefixWrap'
Require stack:
- /Users/.../node_modules/postcss-prefixwrap/build/plugin/PostCSS8Plugin.js
- /Users/.../node_modules/postcss-prefixwrap/build/plugin/PostCSSPlugin.js
- /Users/.../node_modules/postcss-prefixwrap/build/index.js
- /Users/.../postcss.config.js
- /Users/.../node_modules/cosmiconfig/dist/loaders.js
- /Users/.../node_modules/cosmiconfig/dist/ExplorerBase.js
Internally the "patterns" provided via whitelist
, blacklist
options are "Regex matched" against the current CSS file's "path" during post-css execution.
Check code here -> https://github.com/dbtedman/postcss-prefixwrap/blob/main/src/PostCSSPrefixWrap.ts#L113
The docs doesn't mention this explicitly. Instead it just specifies "File" whitelist & "File" blacklist.
Users may think that they can provide file paths in these configs and later suffer when running same projects in different env (windows), due to different path separator patterns.
--
Explicitly mentioning that the whitelist, blacklist options are actually Rx patterns, will help users avoid these platform issues.
how to use in webpack5?
In 1.34.0
, the plugin is properly being typed as PostCSSAcceptedPlugin
, but in 1.35.1
, it's any
.
It seems that build/index.d.ts
is trying to import the types from the wrong place? 🤔
declare const _default: import("./Types").PostCSS8Plugin | import("./Types").PostCSS7Plugin;
Hiya,
Thanks for the plug-in! Question for you. I’m using postcss
in a Webpack setup alongside CSS Modules. This requires css-loader
be run after postcss and, in turn, means css-loader
will fail because postcss-prefixwrap
has added a wrapper class. This is an issue with CSS Modules… you can’t compose
nested classes.
Do you know if there is a way around this problem?
Hello. I've tried to use this plugin to add prefix to some css frameworks to use them inside specific container. However when it replaces html
and body
with wrapper it cause unnecessary styles that applied to container (e.g. min-width, overflows and so on) that breaks container.
html {
background-color: #fff;
font-size: 16px;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
min-width: 300px;
overflow-x: hidden;
overflow-y: scroll;
text-rendering: optimizeLegibility;
}
became
.mywrapper {
background-color: #fff;
font-size: 16px;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
min-width: 300px;
overflow-x: hidden;
overflow-y: scroll;
text-rendering: optimizeLegibility;
}
Is there any option to avoid this (possibly skip such replacement)?
I am getting this error whenever I run npm start. I tried a couple of fixes but none of them work for me. I tried to change the version of postcss-prefixwrap to 1.26.0 but it didn't work. Please help me with this issue. I have updated by react script to "^5.0.0", and then I am started to get this error.
This is my package.json
{ "name": "components-web", "version": "0.1.0", "private": true, "dependencies": { "@babel/plugin-proposal-decorators": "^7.8.3", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-regular-svg-icons": "^5.12.1", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/pro-light-svg-icons": "^5.12.1", "@fortawesome/pro-regular-svg-icons": "^5.12.1", "@fortawesome/pro-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.8", "ajv": "^6.12.0", "antd": "^4.16.13", "apollo-boost": "^0.4.9", "aws-sdk": "^2.997.0", "axios": "^0.21.4", "bluebird": "^3.7.2", "cluster": "^0.7.7", "compression": "^1.7.1", "cookie-parser": "^1.4.3", "core-js": "^2.6.11", "cors": "^2.8.5", "crypto-js": "^3.3.0", "customize-cra": "^0.6.1", "evaporate": "^2.1.4", "express": "^4.16.2", "file-saver": "^1.3.8", "graphql": "^16.2.0", "helmet": "^3.21.3", "immutability-helper": "^3.0.1", "jquery": "^3.5.1", "mobx": "^4.15.4", "mobx-react": "^5.2.0", "moment": "^2.22.2", "morgan": "^1.9.0", "postcss": "^8.4.5", "postcss-cli": "^9.1.0", "postcss-loader": "^4.1.0", "postcss-prefixwrap": "^1.26.0", "primeicons": "^1.0.0", "primereact": "^3.4.0", "prop-types": "^15.6.1", "qrcode.react": "^0.9.3", "react": "^16.12.0", "react-apollo": "^2.1.9", "react-app-rewire-postcss": "^3.0.2", "react-app-rewired": "^2.1.5", "react-compound-timer": "^1.1.15", "react-dom": "^16.12.0", "react-resizable": "^3.0.4", "react-scripts": "^5.0.0", "react-test-renderer": "^16.12.0", "react-transition-group": "^2.9.0", "typescript": "^4.4.3", "validator": "^13.7.0" }, "devDependencies": { "eslint": "^7.32.0", "eslint-config-airbnb": "18.2.1", "eslint-plugin-import": "^2.20.1", "eslint-plugin-jest": "^22.21.0", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-react": "^7.26.1", "source-map-explorer": "^2.3.1" }, "peerDependencies": { "postcss": "^8.4.5" }, "scripts": { "analyze": "source-map-explorer build/static/js/main.*", "start": "mkdir -p dist/static && node eb_app_config && npm run build:new && node app", "start:test": "npm run test:nowatch && npm run start", "copy:js:new": "copy .\\build\\static\\js\\main*.js >> .\\dist\\components.new.js", "copy:css:new": "copy .\\build\\static\\css\\main*.css .\\dist\\components.new.css", "copy:build:new": "npm run copy:global:new && npm run copy:js:new && npm run copy:css:new ", "copy:global:new": "copy .\\dist\\global-functions.js > .\\dist\\components.new.js", "copy:media": "copy -r .\\build\\static\\media .\\dist\\static\\media", "build:new": "node set-build-bundle index-new-ux.js && NODE_ENV='production' react-app-rewired build && npm run copy:build:new", "start:dev:new": "node set-build-bundle index-new-ux.js && NODE_ENV='development' DISABLE_ESLINT_PLUGIN=true react-app-rewired start", "test": "react-app-rewired test --env=jsdom", "test:nowatch": "node eb_app_config && CI=true react-app-rewired test --env=jsdom", "eject": "react-app-rewired eject", "test:lint": "eslint . --ext .js" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "babel": { "env": { "test": { "plugins": [ [ "@babel/plugin-proposal-decorators", { "legacy": true } ] ] } } } }
Example
.a,
.b,
.c {color: red}
Output:
.wrapper .a,
.b,
.c {color: red}
So wrapper applied only to .a
class, but not .b
and .c
.
Docs will need to be updated to include instructions on installing PostCSS manually instead now.
This plugin is wrapping also the animation made with keyframes and it is breaking it
Example output CSS
@keyframes pulse {
.my-custom-wrap 0% {
opacity: 1;
-webkit-transform: scale(1);
transform: scale(1); }
.my-custom-wrap 80% {
opacity: 0;
-webkit-transform: scale(2);
transform: scale(2); }
.my-custom-wrap 100% {
opacity: 0;
-webkit-transform: scale(3);
transform: scale(3); } }
If postcss-prefixwrap
is used with latest 5.x
version of postcss-nested
library the end output is wrong.
Instead of wrap class being applied just once it gets applied multiple times. Based on times how many "nested" lvls are used in source file.
Example:
source:
.demo {
&--lite {
color:red;
}
}
Before upgrade to 5.x result:
.root .demo--lite {color:red}
After upgrade to 5.x result:
.root .root .demo--lite {color:red}
postcss-nested
plugin maintainers are saying that this is issue because plugin is not using PostCSS 8 plugin Api.
With the default configuration some selectors that contain "body" end up getting treated as the root body/html tag. So, for example, with a prefix of .my-custom-wrap
, something like:
tbody {
border: 10px solid red;
}
Will get turned into:
.my-custom-wrap {
border: 10px solid red;
}
Whereas, this should become:
.my-custom-wrap tbody {
border: 10px solid red;
}
This appears to be getting tripped up by the prefixRootTags
regex, since that's matching any selector that contains either body or html anywhere in the selector. As another example, the class name .foobar-body
or .foobar-html
will also gets caught by the same issue.
I was able to solve this by turning on the prefixRootTags
option, since in my case, I didn't necessarily need this logic to extract the body or html selector styles. But I think the issue might be that the regex is too aggressive. I haven't tested this, but maybe something more like /(^|[\s,]*)(body|html)([\s,]*|$)/
might help (that attempts to only match body or html surrounded by spaces, commas, or the beginning/end of line, but I'm not entirely sure about all the possible combinations).
Anyway, just thought I'd mention this and the potential workaround (if you don't need to extract those styles), but thanks for the plugin!
With 1.8.0 I get this error:
Error: Cannot find module
'/Users/developer/Devel/qbus-js/node_modules/postcss-prefixwrap/dist/main.js'.
Please verify that the package.json has a valid "main" entry
If you take a selector like .class-a :where(.class-b, .class-c)
and try prefixing it with .prefix-class
, it results in a selector .prefix-class .class-a :where(.class-b, .prefix-class .class-c)
, which is incorrect. I think the expected result should be .prefix-class .class-a :where(.class-b, .class-c)
It appears to be because the code splits a selector string using the string .split( ',' )
method:
postcss-prefixwrap/src/internal/domain/CSSRuleWrapper.ts
Lines 20 to 21 in c2636cd
I think the AST does provide an already split cssRule.selectors
property, so splitting the string might not be needed, it may be ok to lean on what the AST provides.
PostCSS had moved to version 8.0 recently and therefore using postcss-prefixwrap shows the following message:
postcss.plugin was deprecated. Migration guide:
https://evilmartians.com/chronicles/postcss-8-plugin-migration
This is an issue for tests which fail whenever any non PASS message appears at the summary, what in turn creates confusion in Jenkins having test suite fail while all the tests are green.
Add support for release provenance attestations.
Resources:
Maybe this is more of a question but I would say that root elements (html, body) are treated a bit incorrectly.
Current behaivour:
Source:
html {
color: red;
}
body {
color: blue;
}
Result:
.wrap {
color: red;
}
.wrap {
color: blue;
}
Expected result:
html {
color: red;
}
.wrap body {
color: blue;
}
or even:
html {
color: red;
}
body {
color: blue;
}
Why I think the output should be as follows is: html is the true root element and it cannot have a class on top of that. So yea html
tag should be left as it is. But body
can already be influenced by html
tag.
Our current integration testing strategy was unable to catch a recent import path bug. To avoid this in future, a rethought approach is necessary.
We need to isolate ourselves from our build tooling, operating on the build output (plugin source) directly.
Hi @dbtedman,
Thanks for this plugin as it seems to be working well overall, however, I am just noticing that it will not work for css with the :root pseudo-class. Looking at the purpose of this plugin, it seems that this should also be replaced upon processing.
It seems in this case, the easiest solution to this problem would be to modify 'IS_ROOT_TAG' inside Selector.ts to be
const IS_ROOT_TAG = /^(body|html|:root).*$/;
or alternatively, to perhaps create an option for more generic usage while allowing this to be 'opt in' and more backwards compatible. Perhaps, for example, and 'additionalRootTags' array option could be passed in and used to costruct a dynamically built root tag regex here.
What are your thoughts on this?
I am getting this error whenever I run "npm run build:new". I tried a couple of fixes but none of them work for me. I have updated by react script to "^5.0.0", and then I am started to get this error. I tried to change the version of postcss-prefixwrap to the latest v1.28.1 but it didn't work. Please help me with this issue.
In an earlier ticket, the comment is posted that "postcss-prefixwrap" should work with postcss v8. but it does not work with that.
This is my package.json
{ "name": "components-web", "version": "0.1.0", "private": true, "dependencies": { "@babel/plugin-proposal-decorators": "^7.8.3", "@e-builder/react-components": "^1.0.41", "@fortawesome/fontawesome-svg-core": "^1.2.36", "@fortawesome/free-regular-svg-icons": "^5.12.1", "@fortawesome/free-solid-svg-icons": "^5.15.4", "@fortawesome/pro-light-svg-icons": "^5.12.1", "@fortawesome/pro-regular-svg-icons": "^5.12.1", "@fortawesome/pro-solid-svg-icons": "^5.15.4", "@fortawesome/react-fontawesome": "^0.1.8", "ajv": "^6.12.0", "antd": "^4.16.13", "apollo-boost": "^0.4.9", "aws-sdk": "^2.997.0", "axios": "^0.21.4", "bluebird": "^3.7.2", "cluster": "^0.7.7", "compression": "^1.7.1", "cookie-parser": "^1.4.3", "core-js": "^2.6.11", "cors": "^2.8.5", "crypto-js": "^3.3.0", "customize-cra": "^0.6.1", "evaporate": "^2.1.4", "express": "^4.16.2", "file-saver": "^1.3.8", "graphql": "^16.2.0", "helmet": "^3.21.3", "immutability-helper": "^3.0.1", "jquery": "^3.5.1", "mobx": "^4.15.4", "mobx-react": "^5.2.0", "moment": "^2.22.2", "morgan": "^1.9.0", "postcss": "^8.2.15", "postcss-prefixwrap": "^1.28.1", "primeicons": "^1.0.0", "primereact": "^3.4.0", "prop-types": "^15.6.1", "qrcode.react": "^0.9.3", "react": "^16.12.0", "react-apollo": "^2.1.9", "react-app-rewire-postcss": "^3.0.2", "react-app-rewired": "^2.1.5", "react-compound-timer": "^1.1.15", "react-dom": "^16.12.0", "react-resizable": "^3.0.4", "react-scripts": "^5.0.0", "react-test-renderer": "^16.12.0", "react-transition-group": "^2.9.0", "typescript": "^4.4.3", "validator": "^13.7.0" }, "devDependencies": { "eslint": "^7.32.0", "eslint-config-airbnb": "18.2.1", "eslint-plugin-import": "^2.20.1", "eslint-plugin-jest": "^22.21.0", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-react": "^7.26.1", "source-map-explorer": "^2.3.1" }, "scripts": { "analyze": "source-map-explorer build/static/js/main.*", "start": "mkdir -p dist/static && node eb_app_config && npm run build && npm run build:new && node app", "start:test": "npm run test:nowatch && npm run start", "copy:global:new": "copy .\\dist\\global-functions.js > .\\dist\\components.new.js", "copy:media": "copy -r .\\build\\static\\media .\\dist\\static\\media", "build": "node set-build-bundle index-default.js && NODE_ENV='production' react-app-rewired build && npm run copy:build", "start:dev": "node set-build-bundle index-default.js && NODE_ENV='development' react-app-rewired start", "copy:js:new": "copy .\\build\\static\\js\\main*.js >> .\\dist\\components.new.js", "copy:css:new": "copy .\\build\\static\\css\\main*.css .\\dist\\components.new.css", "copy:build:new": "npm run copy:global:new && npm run copy:js:new && npm run copy:css:new ", "build:new": "node set-build-bundle index-new-ux.js && NODE_ENV='production' react-app-rewired build && npm run copy:build:new", "start:dev:new": "node set-build-bundle index-new-ux.js && NODE_ENV='development' react-app-rewired start", "test": "react-app-rewired test --env=jsdom", "test:nowatch": "node eb_app_config && CI=true react-app-rewired test --env=jsdom", "eject": "react-app-rewired eject", "test:lint": "eslint . --ext .js" }, "eslintConfig": { "extends": "react-app" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] }, "babel": { "env": { "test": { "plugins": [ [ "@babel/plugin-proposal-decorators", { "legacy": true } ] ] } } } }
Hello and thanks for this great plugin
yarn add postcss@^8
yarn add postcss-prefixwrap --dev --exact
Results in an error
[email protected]" has incorrect peer dependency "postcss@7.*.*|^8.1.0".
I'm not experienced with postCSS at all but though trial and error installed [email protected] has the
"peerDependencies": {
"postcss": "*"
},
This works for my use-case but I suspect the "or" in the dependency may be off.
I'm using yarn 1.22.10
Hi,
I run into an issue when trying to wrap rules where the first selector starts with the prefix.
Example :
There are issue with rules starting with .test-4
(.test-4
, .test-4, .test-5
, .test-4, .other
) selectors in the example below:
Trying to wrap the following with the prefix .te
:
p {
color: #ff0000;
}
.test-4 {
color: #ff0000;
}
.test-4, .test-5 {
color: #ff0000;
}
.test-4, .other {
color: #ff0000;
}
h1.test-4, .test-5 {
color: #ff0000;
}
.not-test-4 {
color: #ff0000;
}
.other {
color: #ff0000;
}
results in:
.te p {
color: #ff0000;
}
.test-4 {
color: #ff0000;
}
.test-4, .test-5 {
color: #ff0000;
}
.test-4, .other {
color: #ff0000;
}
.te h1.test-4, .te .test-5 {
color: #ff0000;
}
.te .not-test-4 {
color: #ff0000;
}
.te .other {
color: #ff0000;
}
when the expected output would be:
.te p {
color: #ff0000;
}
.te .test-4 {
color: #ff0000;
}
.te .test-4, .te .test-5 {
color: #ff0000;
}
.te .test-4, .te .other {
color: #ff0000;
}
.te h1.test-4, .te .test-5 {
color: #ff0000;
}
.te .not-test-4 {
color: #ff0000;
}
.te .other {
color: #ff0000;
}
Not necessarily a big issue as it is easy enough to change / add a letter to make it different, but it was enough to trip me up when trying to wrap blueprintjs's css with .bp
(most rules starting with .bp3-
). Examples extracted from my observations in that case.
Note: I can try to fix it sometime within the next week or so unless anyone does before.
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.