Skip to content

Commit

Permalink
feat: add basic plugin functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
enjidev committed Dec 2, 2022
1 parent 46e9fd4 commit 281fdfd
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 112 deletions.
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
95 changes: 62 additions & 33 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,72 @@
const plugin = require('tailwindcss/plugin');
const colors = require('tailwindcss/colors');
const convert = require('color-convert');
const omit = require('lodash/omit');
const pick = require('lodash/pick');
const isArray = require('lodash/isArray');
const isEmpty = require('lodash/isEmpty');
const forEach = require('lodash/forEach');

module.exports = plugin(
function ({ addUtilities, theme, variants }) {
// If your plugin requires user config,
// you can access these options here.
// Docs: https://tailwindcss.com/docs/plugins#exposing-options
const options = theme('accent');
function withOpacityValue(variable) {
return ({ opacityValue }) => {
if (opacityValue === undefined) {
return `rgb(var(${variable}))`;
}
return `rgb(var(${variable}) / ${opacityValue})`;
};
}

// Add CSS-in-JS syntax to create utility classes.
// Docs: https://tailwindcss.com/docs/plugins#adding-utilities
const utilities = {
'.example-utility-class': {
display: 'block',
},
};
module.exports = plugin.withOptions(
function (options = {}) {
let accentColors = omit(colors, [
'black',
'white',
'inherit',
'current',
'transparent',
]);

// Conditionally add utility class based on user configuration.
if (options.YOUR_PLUGIN_CUSTOM_OPTION) {
utilities['.custom-utility-class'] = {
'background-color': 'red',
};
if (options.colors && isArray(options.colors) && !isEmpty(options.colors)) {
accentColors = pick(accentColors, options.colors);
}

addUtilities(utilities, {
variants: variants('accent'),
});
return function ({ addBase }) {
const baseStyle = {};

forEach(accentColors, (colorShades, name) => {
const selector = `[data-accent='${name}']`;
baseStyle[selector] = {};

forEach(colorShades, (value, shade) => {
const cssVar = `--color-accent-${shade}`;
baseStyle[selector][cssVar] = convert.hex.rgb(value).join(' ');
});
});

// Registering new base styles
addBase(baseStyle);
};
},
{
theme: {
// Default options for your custom plugin.
// Docs: https://tailwindcss.com/docs/plugins#exposing-options
accent: {
YOUR_PLUGIN_CUSTOM_OPTION: false,
function () {
return {
theme: {
extends: {
colors: {
accent: {
50: withOpacityValue('--color-accent-50'),
100: withOpacityValue('--color-accent-100'),
200: withOpacityValue('--color-accent-200'),
300: withOpacityValue('--color-accent-300'),
400: withOpacityValue('--color-accent-400'),
500: withOpacityValue('--color-accent-500'),
600: withOpacityValue('--color-accent-600'),
700: withOpacityValue('--color-accent-700'),
800: withOpacityValue('--color-accent-800'),
900: withOpacityValue('--color-accent-900'),
},
},
},
},
},
variants: {
// Default variants for your custom plugin.
// Docs: https://tailwindcss.com/docs/plugins#variants
accent: ['responsive'],
},
};
}
);
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tailwindcss-accent",
"version": "1.0.0",
"version": "0.1.0",
"description": "Add dynamic accent color to your Tailwind CSS project.",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -34,6 +34,7 @@
"author": "enjidev",
"license": "MIT",
"devDependencies": {
"color-convert": "^2.0.1",
"eslint": "^7.2.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^6.15.0",
Expand All @@ -42,7 +43,6 @@
"eslint-plugin-prettier": "^3.1.4",
"husky": "^4.3.0",
"jest": "^26.6.3",
"jest-matcher-css": "^1.1.0",
"lint-staged": "^10.5.2",
"lodash": "^4.17.20",
"postcss": "^8.1.9",
Expand Down
82 changes: 10 additions & 72 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,91 +1,29 @@
const merge = require('lodash/merge');
const cssMatcher = require('jest-matcher-css');
const postcss = require('postcss');
const tailwindcss = require('tailwindcss');
const customPlugin = require('./index.js');
const customPlugin = require('./index');

expect.extend({
toMatchCss: cssMatcher,
});

function generatePluginCss(overrides) {
function generatePluginCss(options) {
const config = {
theme: {
// Default options for your plugin.
accent: {
YOUR_PLUGIN_CUSTOM_OPTION: false,
},
},
variants: {
// Default variants for your plugin.
accent: [],
},
corePlugins: false,
plugins: [customPlugin],
plugins: [customPlugin(options)],
};

return postcss(tailwindcss(merge(config, overrides)))
.process('@tailwind utilities', {
return postcss(tailwindcss(merge(config)))
.process('@tailwind base', {
from: undefined,
})
.then(({ css }) => css);
}

test('utility classes can be generated', () => {
test('base styles selectors correctly generated.', () => {
return generatePluginCss().then(css => {
expect(css).toMatchCss(`
.example-utility-class {
display: block
}
`);
});
});

test('options can be customized', () => {
return generatePluginCss({
theme: {
accent: {
YOUR_PLUGIN_CUSTOM_OPTION: true,
},
},
}).then(css => {
expect(css).toMatchCss(`
.example-utility-class {
display: block
}
.custom-utility-class {
background-color: red
}
`);
expect(css).toContain(`[data-accent='sky']`);
});
});

test('variants can be customized', () => {
return generatePluginCss({
theme: {
screens: {
sm: '640px',
},
},
variants: {
accent: ['responsive', 'hover'],
},
}).then(css => {
expect(css).toMatchCss(`
.example-utility-class {
display: block
}
.hover\\:example-utility-class:hover {
display: block
}
@media (min-width: 640px) {
.sm\\:example-utility-class {
display: block
}
.sm\\:hover\\:example-utility-class:hover {
display: block
}
}
`);
test('selected base styles selectors correctly generated.', () => {
return generatePluginCss({ colors: ['rose'] }).then(css => {
expect(css).not.toContain(`[data-accent='sky']`);
});
});
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3357,11 +3357,6 @@ jest-leak-detector@^26.6.2:
jest-get-type "^26.3.0"
pretty-format "^26.6.2"

jest-matcher-css@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/jest-matcher-css/-/jest-matcher-css-1.1.0.tgz#d2061f4b6bda3b6c2800d4e6cc5c96dad7dc4abd"
integrity sha512-HycxxNw36Cx/CD/XjIt4qcJ0SDpEH9F2ZWTndoyfK7nLiZnIJp/sGSdpQC4GoaC/XshKEee7nBJ81FhIScc5vA==

jest-matcher-utils@^26.6.2:
version "26.6.2"
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a"
Expand Down

0 comments on commit 281fdfd

Please sign in to comment.