diff --git a/__tests__/processPlugins.test.js b/__tests__/processPlugins.test.js index 73b7aff57..ff2350e55 100644 --- a/__tests__/processPlugins.test.js +++ b/__tests__/processPlugins.test.js @@ -418,3 +418,55 @@ test("plugins can apply the user's chosen prefix", () => { } `) }) + +test("utilities are escaped and automatically respect prefix and important options when created via `utility`", () => { + const [, utilities] = processPlugins({ + plugins: [ + function({ utility, addUtilities }) { + addUtilities([ + utility('.rotate-1/4', { + transform: 'rotate(90deg)', + }), + ]) + }, + ], + options: { + prefix: 'tw-', + important: true, + }, + }) + + expect(css(utilities)).toMatchCss(` + @variants { + .tw-rotate-1\\/4 { + transform: rotate(90deg) !important + } + } + `) +}) + +test("leading '.' is optional when creating utilities via `utility`", () => { + const [, utilities] = processPlugins({ + plugins: [ + function({ utility, addUtilities }) { + addUtilities([ + utility('rotate-1/4', { + transform: 'rotate(90deg)', + }), + ]) + }, + ], + options: { + prefix: 'tw-', + important: true, + }, + }) + + expect(css(utilities)).toMatchCss(` + @variants { + .tw-rotate-1\\/4 { + transform: rotate(90deg) !important + } + } + `) +}) diff --git a/src/util/processPlugins.js b/src/util/processPlugins.js index d8fd1b616..9d136c047 100644 --- a/src/util/processPlugins.js +++ b/src/util/processPlugins.js @@ -15,6 +15,20 @@ function defineRule(selector, properties) { return postcss.rule({ selector }).append(decls) } +function defineUtility(selector, properties, options) { + if (selector.startsWith('.')) { + return defineUtility(selector.slice(1), properties, options) + } + + const rule = defineRule(prefixSelector(options.prefix, `.${escapeClassName(selector)}`), properties) + + if (options.important) { + rule.walkDecls(decl => (decl.important = true)) + } + + return rule +} + function defineAtRule(atRule, rules) { const [name, ...params] = atRule.split(' ') @@ -34,6 +48,7 @@ export default function(config) { plugin({ config: (path, defaultValue) => _.get(config, path, defaultValue), rule: defineRule, + utility: (selector, properties) => defineUtility(selector, properties, config.options), atRule: defineAtRule, e: escapeClassName, addUtilities: (utilities, variants = []) => {