This code modifies CSS stylesheets by adding a prefix to selectors, effectively renaming elements within the stylesheet for purposes like theming or component isolation.
npm run import -- "scope css"
var css = require('css');
function prefixRule(r, str, prefix, bodyId) {
if(typeof r.rules !== 'undefined') {
r.rules.forEach(r2 => prefixRule(r2, str, prefix, bodyId))
}
if(typeof r.selectors === 'undefined') {
return;
}
r.selectors.forEach((s, i) => {
if(s.includes(bodyId)) {
r.selectors[i] = s.replace('#' + bodyId, prefix);
} else if(s.includes('body') && !s.includes('#body')) {
r.selectors[i] = s.replace(/\s*body\s*/ig, prefix);
} else {
r.selectors[i] = prefix + ' ' + s;
}
});
}
function prefixCssRules(str, prefix, bodyId) {
try {
const ast = css.parse(str);
// TODO: add a check for media queries
ast.stylesheet.rules.forEach(r => prefixRule(r, str, prefix, bodyId))
return css.stringify(ast);
} catch (e) {
console.log(e)
return str
}
}
// TODO: convert media queries to togglable javascript classes for good emulation in a golden layout tab
module.exports = prefixCssRules;
const css = require('css');
/**
* Recursively prefixes CSS selectors with the given prefix.
*
* @param {Object} rule - The CSS rule to prefix.
* @param {string} str - The original CSS string.
* @param {string} prefix - The prefix to apply.
* @param {string} bodyId - The ID of the body element.
*/
function prefixRule(rule, str, prefix, bodyId) {
if (rule.rules) {
rule.rules.forEach(r => prefixRule(r, str, prefix, bodyId));
}
if (!rule.selectors) return;
rule.selectors.forEach((selector, index) => {
if (selector.includes(`#${bodyId}`)) {
rule.selectors[index] = selector.replace(`#${bodyId}`, prefix);
} else if (selector.includes('body') &&!selector.includes('#body')) {
rule.selectors[index] = selector.replace(/\s*body\s*/gi, prefix);
} else {
rule.selectors[index] = `${prefix} ${selector}`;
}
});
}
/**
* Prefixes CSS rules in the given string with the specified prefix.
*
* @param {string} str - The CSS string to prefix.
* @param {string} prefix - The prefix to apply.
* @param {string} bodyId - The ID of the body element.
* @returns {string} The prefixed CSS string.
*/
function prefixCssRules(str, prefix, bodyId) {
try {
const ast = css.parse(str);
// Prefix rules in media queries
ast.stylesheet.rules.forEach(rule => prefixRule(rule, str, prefix, bodyId));
return css.stringify(ast);
} catch (error) {
console.error(error);
return str;
}
}
module.exports = prefixCssRules;
This code defines a function prefixCssRules
that modifies CSS rules by adding a prefix to selectors, effectively renaming elements within the stylesheet.
Here's a breakdown:
Dependencies:
css
library for parsing and manipulating CSS syntax.prefixRule
Function:
bodyId
, it replaces the #bodyId
with the provided prefix
.prefix
.prefix
to the selector.prefixCssRules
Function:
prefix
, and bodyId
as input.css.parse
.prefixRule
to modify selectors within the parsed AST.css.stringify
.Module Export:
prefixCssRules
function as a module.Overall Purpose:
This code provides a way to dynamically modify CSS stylesheets by adding a prefix to selectors, likely for purposes like theming, component isolation, or code generation. It allows for selective renaming of elements based on specific IDs or the presence of "body" in selectors.