From 60a7a4f01d1d1548059cd304e2ac82649acc6603 Mon Sep 17 00:00:00 2001 From: Andrea Moretti Date: Fri, 29 May 2020 15:26:39 +0200 Subject: [PATCH 1/4] feat: nested rules --- example/example.config.js | 18 +++++++++++ src/util/applyRules.js | 64 ++++++++++++++++++++++++++++++++++----- src/util/defineClass.js | 4 +-- src/util/defineSeries.js | 9 ++++-- src/util/template.js | 5 +++ 5 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 src/util/template.js diff --git a/example/example.config.js b/example/example.config.js index be17040..f86645a 100644 --- a/example/example.config.js +++ b/example/example.config.js @@ -63,11 +63,29 @@ const modules = [ isResponsive: true }), colors({ + nestedRules: { + ".dark {}": { + whitelist: ["c"], + isResponsive: true, + colorValues: { + black: "#ffffff", + white: "#1a1a1a" + } + }, + "@media foo": { + whitelist: ["c"], + colorValues: { + black: "#ffffff", + white: "#1a1a1a" + } + } + }, whitelist: ["c", "bgc", "bdc"], pseudoClasses: { c: [":hover"], bgc: [":hover", ":active"] }, colorValues: { orange: "#ff6900", black: "#1a1a1a", + white: "#ffffff", grey: "#777777", grey2: "#a5a5a5", grey3: "#dddddd", diff --git a/src/util/applyRules.js b/src/util/applyRules.js index 8da7d94..a8b8352 100644 --- a/src/util/applyRules.js +++ b/src/util/applyRules.js @@ -1,8 +1,17 @@ +const postcss = require("postcss"); const defineClass = require("./defineClass"); const defineSeries = require("./defineSeries"); const responsive = require("./responsive"); +const template = require("./template"); -module.exports = ({ config, globalConfig, defaultNames, getRules, meta }) => { +const applyRules = ({ + config, + globalConfig, + defaultNames, + getRules, + meta, + classTemplate = "{}" +}) => { const { names = {}, whitelist = [], @@ -10,17 +19,16 @@ module.exports = ({ config, globalConfig, defaultNames, getRules, meta }) => { isResponsive = false, responsiveWhiteList = [], responsiveBlackList = [], - pseudoClasses = {} - } = - config || {}; + pseudoClasses = {}, + nestedRules + } = config || {}; const { breakPoints = {}, breakPointSeparator = "", pseudoClassesSeparator = "", seriesSeparator = "" - } = - globalConfig || {}; + } = globalConfig || {}; const customNames = Object.assign({}, defaultNames, names); const customRules = getRules(customNames, config || {}); @@ -45,7 +53,8 @@ module.exports = ({ config, globalConfig, defaultNames, getRules, meta }) => { seriesSeparator, pseudoClasses: modifiers, pseudoClassesSeparator, - meta: { ...meta, id: curr } + meta: { ...meta, id: curr }, + classTemplate }) ); } else if (typeof value === "string" || typeof value === "number") { @@ -57,7 +66,10 @@ module.exports = ({ config, globalConfig, defaultNames, getRules, meta }) => { return prev.concat( defineClass( - `${name}${separator}${pseudoClass}${pseudo}`, + template( + classTemplate, + `${name}${separator}${pseudoClass}${pseudo}` + ), { [`${key}`]: value }, { ...meta, id: curr } ) @@ -88,5 +100,41 @@ module.exports = ({ config, globalConfig, defaultNames, getRules, meta }) => { ); } + if (nestedRules) { + Object.keys(nestedRules).forEach(nestedRule => { + const isAtRule = nestedRule[0] === "@"; + + if (isAtRule) { + const name = nestedRule.split(" ")[0].slice(1); + const nestedRuleNode = postcss.atRule({ + name: name, + params: nestedRule.split(`${name} `)[1], + nodes: applyRules({ + config: nestedRules[nestedRule], + globalConfig, + defaultNames, + getRules, + meta + }) + }); + + result = result.concat(nestedRuleNode); + } else { + result = result.concat( + applyRules({ + config: nestedRules[nestedRule], + globalConfig, + defaultNames, + getRules, + meta, + classTemplate: nestedRule + }) + ); + } + }); + } + return result; }; + +module.exports = applyRules; diff --git a/src/util/defineClass.js b/src/util/defineClass.js index 43e1c1a..6efe382 100644 --- a/src/util/defineClass.js +++ b/src/util/defineClass.js @@ -1,7 +1,7 @@ const postcss = require("postcss"); const escapeClassName = className => - className.replace(/([^A-Za-z0-9\-\:\_])/g, "\\$1"); //eslint-disable-line + className.replace(/([^A-Za-z0-9\-\:\_\ \.])/g, "\\$1"); //eslint-disable-line module.exports = (name, props, meta = {}) => { const decls = Object.keys(props).map(prop => @@ -13,7 +13,7 @@ module.exports = (name, props, meta = {}) => { return postcss .rule({ - selector: `.${escapeClassName(name)}`, + selectors: `.${escapeClassName(name)}`.split(" "), meta }) .append(decls); diff --git a/src/util/defineSeries.js b/src/util/defineSeries.js index 4ba67ca..41e223f 100644 --- a/src/util/defineSeries.js +++ b/src/util/defineSeries.js @@ -1,11 +1,13 @@ const defineClass = require("./defineClass"); +const template = require("./template"); module.exports = (name, prop, values, options = {}) => { const { seriesSeparator = "", pseudoClassesSeparator = "", pseudoClasses = [], - meta = {} + meta = {}, + classTemplate = "{}" } = options; return [""].concat(pseudoClasses).reduce((prev, pseudo) => { @@ -14,7 +16,10 @@ module.exports = (name, prop, values, options = {}) => { const pseudoClass = pseudo.replace(/:/g, ""); const nodes = Object.keys(values).map(value => defineClass( - `${name}${separator}${value}${pseudoSeparator}${pseudoClass}${pseudo}`, + template( + classTemplate, + `${name}${separator}${value}${pseudoSeparator}${pseudoClass}${pseudo}` + ), { [`${prop}`]: values[value] }, diff --git a/src/util/template.js b/src/util/template.js new file mode 100644 index 0000000..b882f5d --- /dev/null +++ b/src/util/template.js @@ -0,0 +1,5 @@ +/** + * template function to generate class selectors. + * the placeholder "{}" will get substituted with str + */ +module.exports = (t, str) => t.replace(/{}/g, `.${str}`).replace(".", ""); From 6fcf50fe20d160ad8ec5f5d0bc47a8061e5cbbb0 Mon Sep 17 00:00:00 2001 From: Andrea Moretti Date: Fri, 29 May 2020 15:27:32 +0200 Subject: [PATCH 2/4] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc8a905..39b4a89 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@utilitycss/utility", - "version": "0.5.5", + "version": "0.6.0", "description": "Generator for Utility CSS frameworks", "author": "Andrea Moretti (@axyz) ", "repository": "utilitycss/utility", From 23c55cf0df0c8c1fed006b8f831b7bed9a661568 Mon Sep 17 00:00:00 2001 From: Andrea Moretti Date: Fri, 29 May 2020 15:49:26 +0200 Subject: [PATCH 3/4] fix: hide docs for nested rules --- src/helpers/build-sections.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/helpers/build-sections.js b/src/helpers/build-sections.js index 304b425..05c6aa1 100644 --- a/src/helpers/build-sections.js +++ b/src/helpers/build-sections.js @@ -20,12 +20,14 @@ module.exports = function({ modules }) { modules[module].forEach(rule => { // console.log(JSON.stringify(rule)); const { nodes, selector, media } = rule; - rules.push({ - selector, - nodes, - media, - class: selectorReplace(selector) - }); + if (/^\.[A-Za-z0-9\-\:\_]+$/.test(selector)) { + rules.push({ + selector, + nodes, + media, + class: selectorReplace(selector) + }); + } }); const sectionHtml = sectionTemplate({ module: moduleName, From 2593021735332f3a23c3df91725b8073dc42ff97 Mon Sep 17 00:00:00 2001 From: Andrea Moretti Date: Fri, 29 May 2020 15:59:32 +0200 Subject: [PATCH 4/4] fix: do not add commas --- src/util/defineClass.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/defineClass.js b/src/util/defineClass.js index 6efe382..74e482d 100644 --- a/src/util/defineClass.js +++ b/src/util/defineClass.js @@ -13,7 +13,7 @@ module.exports = (name, props, meta = {}) => { return postcss .rule({ - selectors: `.${escapeClassName(name)}`.split(" "), + selector: `.${escapeClassName(name)}`, meta }) .append(decls);