[READ-ONLY] Mirror of https://github.com/hacknug/tailwindcss-plugin-utils. A bunch of utilities to help you create and maintain plugins for Tailwind. www.npmjs.com/package/@hacknug/tailwindcss-plugin-utils
0

Configure Feed

Select the types of activity you want to include in your feed.

Allow users to define a custom property

Nestor Vera (Oct 12, 2019, 10:07 PM +0200) f4f58af9 355cd5b0

+76 -53
+43 -22
src/index.js
··· 36 36 * @param {...string} fallbackKeys 37 37 */ 38 38 39 - export const buildConfig = (coreUtils, tailwindConfig, themeKey, ...fallbackKeys) => { 40 - const buildFromEntries = ([modifier, value]) => [modifier, { [themeKey]: value }] 39 + export const buildConfigFromRecipe = (coreUtils, recipe) => { 40 + const { key: [themeKey, ...fallbackKeys], property, config } = recipe 41 + const buildFromEntries = ([modifier, value]) => [modifier, { [property || themeKey]: value }] 41 42 const themeSettings = getSettings(coreUtils.theme, themeKey, fallbackKeys) 42 43 43 - const settings = themeSettings || getSettings(tailwindConfig.theme, themeKey, fallbackKeys) 44 + const settings = themeSettings || getSettings(config.theme, themeKey, fallbackKeys) 44 45 const object = Array.isArray(settings) ? _.zipObject(settings, settings) : settings 45 46 const flatObject = themeSettings ? flatten(object, FLATTEN_CONFIG) : object 46 47 const entries = settings && Object.entries(flatObject).map(buildFromEntries) ··· 72 73 * 73 74 * @param {Object} tailwindConfig 74 75 * @param {Object} coreUtils 75 - * @param {Object} pluginRecipe 76 + * @param {Object} pluginRecipes 76 77 */ 78 + // TODO: Rename to denote it ONLY adds utilities 79 + export const buildPlugin = (coreUtils, tailwindConfig, pluginRecipes) => { 80 + // TODO: Add support for String recipes? 81 + const prepareRecipe = (recipe) => { 82 + const { 83 + // TODO: Add support for String keys? 84 + key, // Array 85 + base = _.kebabCase(key[0]), 86 + property = _.kebabCase(key[0]), 87 + // TODO: Support passing default config using new core API 88 + config = tailwindConfig, 89 + // TODO: Support passing addUtilitiesOptions 90 + // options = { respectPrefix: false, respectImportant: false, variants: [] }, 91 + } = recipe 92 + return key ? { key, base, property, config } : recipe 93 + } 77 94 78 - export const buildPlugin = (coreUtils, tailwindConfig, pluginRecipe) => { 79 - const { addUtilities, e, variants } = coreUtils 80 - // TODO: Support specifying a property à la `tailwindcss-alpha` and `tailwindcss-custom-native` 81 - const recipes = Array.isArray(pluginRecipe) ? pluginRecipe : [pluginRecipe] 95 + return (Array.isArray(pluginRecipes) ? pluginRecipes : [pluginRecipes]) 96 + .map(prepareRecipe) 97 + .forEach((recipe) => { 98 + const { key, base, property, config } = recipe 99 + // TODO: Support specifying a property à la `tailwindcss-alpha` and `tailwindcss-custom-native` 100 + const buildFromRecipe = ([index, value]) => [index, buildConfigFromRecipe(coreUtils, recipe)] 82 101 83 - return recipes.forEach((recipe) => { 84 - const buildFromRecipe = ([key, value]) => [key, buildConfig(coreUtils, tailwindConfig, ...value)] 85 - 86 - return Object.entries(_.fromPairs(Object.entries(recipe).map(buildFromRecipe))) 87 - .filter(([modifier, values]) => !_.isEmpty(values)) 88 - .forEach(([modifier, values]) => { 89 - const base = _.kebabCase(modifier).split('-').slice(0, 2).join('-') 90 - const variantName = Object.keys(Object.entries(values)[0][1])[0] 91 - const flatValues = Object.entries(flatten({ [base]: values }, FLATTEN_CONFIG)) 92 - .map(([className, value]) => [`.${e(`${className}`)}`, value]) 93 - const utilities = _(flatValues).fromPairs().mapKeys((value, key) => handleName(key, base)).value() 102 + // TODO: All this mess is probably not required anymore 103 + return Object.entries(_.fromPairs(Object.entries({ [base]: key }).map(buildFromRecipe))) 104 + .filter(([modifier, values]) => !_.isEmpty(values)) 105 + .forEach(([modifier, values]) => { 106 + const { addUtilities, e, variants } = coreUtils 107 + // const base = _.kebabCase(modifier).split('-').slice(0, 2).join('-') 108 + // const variantName = Object.keys(Object.entries(values)[0][1])[0] 109 + const flatValues = Object.entries(flatten({ [base]: values }, FLATTEN_CONFIG)) 110 + .map(([className, value]) => [`.${e(`${className}`)}`, value]) 111 + const utilities = _(flatValues).fromPairs().mapKeys((value, key) => handleName(key, base)).value() 94 112 95 - return addUtilities(utilities, variants(variantName, ['responsive'])) 96 - }) 97 - }) 113 + return addUtilities(utilities, { 114 + // TODO: Should it really default to ['responsive]? 115 + variants: variants(key[0], ['responsive']), 116 + }) 117 + }) 118 + }) 98 119 } 99 120 100 121 /**
+26 -26
src/index.test.js
··· 1 1 import { 2 2 FLATTEN_CONFIG, 3 3 handleName, 4 - buildConfig, 4 + buildConfigFromRecipe, 5 5 generatePluginCss, 6 6 } from './index' 7 7 ··· 53 53 }) 54 54 }) 55 55 56 - describe('buildConfig()', () => { 56 + describe('buildConfigFromRecipe()', () => { 57 57 test('from theme() object', () => { 58 - expect(buildConfig(tailwindConfig, coreUtils, 'backgroundColor')) 58 + expect(buildConfigFromRecipe(coreUtils, { config: tailwindConfig, key: ['backgroundColor'] })) 59 59 .toStrictEqual({ tailwind: { backgroundColor: '#38b2ac' } }) 60 60 }) 61 61 test('from theme() object using fallbacks', () => { 62 - expect(buildConfig(tailwindConfig, coreUtils, 'textColor', 'backgroundColor')) 62 + expect(buildConfigFromRecipe(coreUtils, { config: tailwindConfig, key: ['textColor', 'backgroundColor'] })) 63 63 .toStrictEqual({ tailwind: { textColor: '#38b2ac' } }) 64 64 }) 65 65 test('from theme() array', () => { 66 - expect(buildConfig(tailwindConfig, coreUtils, 'columnCount')) 66 + expect(buildConfigFromRecipe(coreUtils, { config: tailwindConfig, key: ['columnCount'] })) 67 67 .toStrictEqual({ 2: { columnCount: 2 }, 4: { columnCount: 4 } }) 68 68 }) 69 69 test('from theme() undefined', () => { 70 - expect(buildConfig(tailwindConfig, coreUtils, 'backgroundImage')) 70 + expect(buildConfigFromRecipe(coreUtils, { config: tailwindConfig, key: ['backgroundImage'] })) 71 71 .toStrictEqual({}) 72 72 }) 73 73 test('from defaultConfig object', () => { 74 - expect(buildConfig(tailwindConfig, coreUtils, 'columnSpan')) 74 + expect(buildConfigFromRecipe(coreUtils, { config: tailwindConfig, key: ['columnSpan'] })) 75 75 .toStrictEqual({ all: { columnSpan: 'all' }, none: { columnSpan: 'none' } }) 76 76 }) 77 77 test('from defaultConfig object using fallbacks', () => { 78 - expect(buildConfig(tailwindConfig, coreUtils, 'gap', 'columnGap')) 78 + expect(buildConfigFromRecipe(coreUtils, { config: tailwindConfig, key: ['gap', 'columnGap'] })) 79 79 .toStrictEqual({ 4: { gap: '1rem' }, 8: { gap: '2rem' }, '1/2': { gap: '50%' } }) 80 80 }) 81 81 }) ··· 94 94 .col-span-none { column-span: none } 95 95 .col-span-all { column-span: all } 96 96 97 - .text-stroke-red { text-stroke-color: red } 98 - .text-stroke-2 { text-stroke-width: 2px } 97 + .text-stroke-red { -webkit-text-stroke-color: red } 98 + .text-stroke-2 { -webkit-text-stroke-width: 2px } 99 99 ` 100 100 101 101 return generatePluginCss(tailwindConfig, testConfig) ··· 114 114 .col-span-none { column-span: none } 115 115 .col-span-all { column-span: all } 116 116 117 - .text-stroke-red { text-stroke-color: red } 118 - .text-stroke-2 { text-stroke-width: 2px } 117 + .text-stroke-red { -webkit-text-stroke-color: red } 118 + .text-stroke-2 { -webkit-text-stroke-width: 2px } 119 119 120 120 @media (min-width: 640px) { 121 121 .sm\\:col-count-2 { column-count: 2 } ··· 128 128 .sm\\:col-span-none { column-span: none } 129 129 .sm\\:col-span-all { column-span: all } 130 130 131 - .sm\\:text-stroke-red { text-stroke-color: red } 132 - .sm\\:text-stroke-2 { text-stroke-width: 2px } 131 + .sm\\:text-stroke-red { -webkit-text-stroke-color: red } 132 + .sm\\:text-stroke-2 { -webkit-text-stroke-width: 2px } 133 133 } 134 134 ` 135 135 ··· 152 152 .col-span-none { column-span: none } 153 153 .col-span-all { column-span: all } 154 154 155 - .text-stroke-red { text-stroke-color: red } 156 - .text-stroke-2 { text-stroke-width: 2px } 155 + .text-stroke-red { -webkit-text-stroke-color: red } 156 + .text-stroke-2 { -webkit-text-stroke-width: 2px } 157 157 158 158 @media (min-width: 640px) { 159 159 .sm\\:col-count-2 { column-count: 2 } ··· 166 166 .sm\\:col-span-none { column-span: none } 167 167 .sm\\:col-span-all { column-span: all } 168 168 169 - .sm\\:text-stroke-red { text-stroke-color: red } 170 - .sm\\:text-stroke-2 { text-stroke-width: 2px } 169 + .sm\\:text-stroke-red { -webkit-text-stroke-color: red } 170 + .sm\\:text-stroke-2 { -webkit-text-stroke-width: 2px } 171 171 } 172 172 173 173 @media (min-width: 768px) { ··· 181 181 .md\\:col-span-none { column-span: none } 182 182 .md\\:col-span-all { column-span: all } 183 183 184 - .md\\:text-stroke-red { text-stroke-color: red } 185 - .md\\:text-stroke-2 { text-stroke-width: 2px } 184 + .md\\:text-stroke-red { -webkit-text-stroke-color: red } 185 + .md\\:text-stroke-2 { -webkit-text-stroke-width: 2px } 186 186 } 187 187 ` 188 188 ··· 215 215 .col-span-none { column-span: none } 216 216 .col-span-all { column-span: all } 217 217 218 - .text-stroke-red { text-stroke-color: red } 219 - .text-stroke-2 { text-stroke-width: 2px } 218 + .text-stroke-red { -webkit-text-stroke-color: red } 219 + .text-stroke-2 { -webkit-text-stroke-width: 2px } 220 220 221 221 @media (min-width: 640px) { 222 222 .sm\\:col-span-none { column-span: none } 223 223 .sm\\:col-span-all { column-span: all } 224 224 225 - .sm\\:text-stroke-red { text-stroke-color: red } 226 - .sm\\:text-stroke-2 { text-stroke-width: 2px } 225 + .sm\\:text-stroke-red { -webkit-text-stroke-color: red } 226 + .sm\\:text-stroke-2 { -webkit-text-stroke-width: 2px } 227 227 } 228 228 ` 229 229 ··· 243 243 .col-span-none { column-span: none } 244 244 .col-span-all { column-span: all } 245 245 246 - .text-stroke-red { text-stroke-color: red } 247 - .text-stroke-2 { text-stroke-width: 2px } 246 + .text-stroke-red { -webkit-text-stroke-color: red } 247 + .text-stroke-2 { -webkit-text-stroke-width: 2px } 248 248 ` 249 249 250 250 return generatePluginCss(tailwindConfig, testConfig)
+7 -5
src/plugin.js
··· 3 3 4 4 module.exports = (pluginOptions) => (coreUtils) => { 5 5 return buildPlugin(coreUtils, pluginDefaultConfig, [ 6 - { 'col-count': ['columnCount'] }, 7 - { 'col-gap': ['columnGap', 'gap', 'gridGap'] }, 8 - { 'col-span': ['columnSpan'] }, 9 - { 'text-stroke': ['textStrokeColor', 'borderColor'] }, 10 - { 'text-stroke': ['textStrokeWidth', 'borderWidth'] }, 6 + { key: ['columnCount'], base: 'col-count' }, 7 + { key: ['columnGap', 'gap', 'gridGap'], base: 'col-gap' }, 8 + { key: ['columnSpan'], base: 'col-span' }, 9 + // { key: ['textFillColor', 'borderColor'], base: 'text-fill', property: '-webkit-text-fill-color' }, 10 + { key: ['textStrokeColor', 'borderColor'], base: 'text-stroke', property: '-webkit-text-stroke-color' }, 11 + { key: ['textStrokeWidth', 'borderWidth'], base: 'text-stroke', property: '-webkit-text-stroke-width' }, 12 + // { key: ['paintOrder'], base: 'paint' }, 11 13 ]) 12 14 }